kernel: bump 5.15 to 5.15.100
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-5.15 / 950-0807-Revert-drm-vc4-hvs-Defer-dlist-slots-deallocation.patch
1 From a6ee757ad5ba809e8bc3fd6f14167425cff91498 Mon Sep 17 00:00:00 2001
2 From: Maxime Ripard <maxime@cerno.tech>
3 Date: Thu, 31 Mar 2022 15:27:43 +0200
4 Subject: [PATCH] Revert "drm/vc4: hvs: Defer dlist slots deallocation"
5
6 This reverts commit e99a1b69da07ee3b89a6b8005b854e6c04bfb450.
7 ---
8 drivers/gpu/drm/vc4/vc4_crtc.c | 10 +-
9 drivers/gpu/drm/vc4/vc4_drv.h | 15 +--
10 drivers/gpu/drm/vc4/vc4_hvs.c | 181 +++------------------------------
11 drivers/gpu/drm/vc4/vc4_regs.h | 1 -
12 4 files changed, 23 insertions(+), 184 deletions(-)
13
14 --- a/drivers/gpu/drm/vc4/vc4_crtc.c
15 +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
16 @@ -982,8 +982,14 @@ void vc4_crtc_destroy_state(struct drm_c
17 struct vc4_dev *vc4 = to_vc4_dev(crtc->dev);
18 struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state);
19
20 - vc4_hvs_mark_dlist_entry_stale(vc4->hvs, vc4_state->mm);
21 - vc4_state->mm = NULL;
22 + if (drm_mm_node_allocated(&vc4_state->mm)) {
23 + unsigned long flags;
24 +
25 + spin_lock_irqsave(&vc4->hvs->mm_lock, flags);
26 + drm_mm_remove_node(&vc4_state->mm);
27 + spin_unlock_irqrestore(&vc4->hvs->mm_lock, flags);
28 +
29 + }
30
31 drm_atomic_helper_crtc_destroy_state(crtc, state);
32 }
33 --- a/drivers/gpu/drm/vc4/vc4_drv.h
34 +++ b/drivers/gpu/drm/vc4/vc4_drv.h
35 @@ -335,9 +335,6 @@ struct vc4_hvs {
36 struct drm_mm lbm_mm;
37 spinlock_t mm_lock;
38
39 - struct list_head stale_dlist_entries;
40 - struct work_struct free_dlist_work;
41 -
42 struct drm_mm_node mitchell_netravali_filter;
43
44 struct debugfs_regset32 regset;
45 @@ -576,16 +573,10 @@ struct drm_connector *vc4_get_crtc_conne
46 struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc,
47 struct drm_crtc_state *state);
48
49 -struct vc4_hvs_dlist_allocation {
50 - struct list_head node;
51 - struct drm_mm_node mm_node;
52 - unsigned int channel;
53 - u8 target_frame_count;
54 -};
55 -
56 struct vc4_crtc_state {
57 struct drm_crtc_state base;
58 - struct vc4_hvs_dlist_allocation *mm;
59 + /* Dlist area for this CRTC configuration. */
60 + struct drm_mm_node mm;
61 bool txp_armed;
62 unsigned int assigned_channel;
63
64 @@ -972,8 +963,6 @@ extern struct platform_driver vc4_hvs_dr
65 void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int output);
66 int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output);
67 u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo);
68 -void vc4_hvs_mark_dlist_entry_stale(struct vc4_hvs *hvs,
69 - struct vc4_hvs_dlist_allocation *alloc);
70 int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state);
71 void vc4_hvs_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state);
72 void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state);
73 --- a/drivers/gpu/drm/vc4/vc4_hvs.c
74 +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
75 @@ -315,150 +315,6 @@ static void vc4_hvs_update_gamma_lut(str
76 vc4_hvs_lut_load(hvs, vc4_crtc);
77 }
78
79 -static void vc4_hvs_irq_enable_eof(const struct vc4_hvs *hvs,
80 - unsigned int channel)
81 -{
82 - u32 irq_mask = hvs->hvs5 ?
83 - SCALER5_DISPCTRL_DSPEIEOF(channel) :
84 - SCALER_DISPCTRL_DSPEIEOF(channel);
85 -
86 - HVS_WRITE(SCALER_DISPCTRL,
87 - HVS_READ(SCALER_DISPCTRL) | irq_mask);
88 -}
89 -
90 -static void vc4_hvs_irq_clear_eof(const struct vc4_hvs *hvs,
91 - unsigned int channel)
92 -{
93 - u32 irq_mask = hvs->hvs5 ?
94 - SCALER5_DISPCTRL_DSPEIEOF(channel) :
95 - SCALER_DISPCTRL_DSPEIEOF(channel);
96 -
97 - HVS_WRITE(SCALER_DISPCTRL,
98 - HVS_READ(SCALER_DISPCTRL) & ~irq_mask);
99 -}
100 -
101 -static struct vc4_hvs_dlist_allocation *
102 -vc4_hvs_alloc_dlist_entry(struct vc4_hvs *hvs,
103 - unsigned int channel,
104 - size_t dlist_count)
105 -{
106 - struct vc4_hvs_dlist_allocation *alloc;
107 - unsigned long flags;
108 - int ret;
109 -
110 - if (channel == VC4_HVS_CHANNEL_DISABLED)
111 - return NULL;
112 -
113 - alloc = kzalloc(sizeof(*alloc), GFP_KERNEL);
114 - if (!alloc)
115 - return ERR_PTR(-ENOMEM);
116 -
117 - spin_lock_irqsave(&hvs->mm_lock, flags);
118 - ret = drm_mm_insert_node(&hvs->dlist_mm, &alloc->mm_node,
119 - dlist_count);
120 - spin_unlock_irqrestore(&hvs->mm_lock, flags);
121 - if (ret)
122 - return ERR_PTR(ret);
123 -
124 - alloc->channel = channel;
125 -
126 - return alloc;
127 -}
128 -
129 -void vc4_hvs_mark_dlist_entry_stale(struct vc4_hvs *hvs,
130 - struct vc4_hvs_dlist_allocation *alloc)
131 -{
132 - unsigned long flags;
133 - u8 frcnt;
134 -
135 - if (!alloc)
136 - return;
137 -
138 - if (!drm_mm_node_allocated(&alloc->mm_node))
139 - return;
140 -
141 - frcnt = vc4_hvs_get_fifo_frame_count(hvs, alloc->channel);
142 - alloc->target_frame_count = (frcnt + 1) & ((1 << 6) - 1);
143 -
144 - spin_lock_irqsave(&hvs->mm_lock, flags);
145 -
146 - list_add_tail(&alloc->node, &hvs->stale_dlist_entries);
147 -
148 - HVS_WRITE(SCALER_DISPSTAT, SCALER_DISPSTAT_EOF(alloc->channel));
149 - vc4_hvs_irq_enable_eof(hvs, alloc->channel);
150 -
151 - spin_unlock_irqrestore(&hvs->mm_lock, flags);
152 -}
153 -
154 -static void vc4_hvs_schedule_dlist_sweep(struct vc4_hvs *hvs,
155 - unsigned int channel)
156 -{
157 - unsigned long flags;
158 -
159 - spin_lock_irqsave(&hvs->mm_lock, flags);
160 -
161 - if (!list_empty(&hvs->stale_dlist_entries))
162 - queue_work(system_unbound_wq, &hvs->free_dlist_work);
163 -
164 - vc4_hvs_irq_clear_eof(hvs, channel);
165 -
166 - spin_unlock_irqrestore(&hvs->mm_lock, flags);
167 -}
168 -
169 -/*
170 - * Frame counts are essentially sequence numbers over 6 bits, and we
171 - * thus can use sequence number arithmetic and follow the RFC1982 to
172 - * implement proper comparison between them.
173 - */
174 -static bool vc4_hvs_frcnt_lte(u8 cnt1, u8 cnt2)
175 -{
176 - return (s8)((cnt1 << 2) - (cnt2 << 2)) <= 0;
177 -}
178 -
179 -/*
180 - * Some atomic commits (legacy cursor updates, mostly) will not wait for
181 - * the next vblank and will just return once the commit has been pushed
182 - * to the hardware.
183 - *
184 - * On the hardware side, our HVS stores the planes parameters in its
185 - * context RAM, and will use part of the RAM to store data during the
186 - * frame rendering.
187 - *
188 - * This interacts badly if we get multiple commits before the next
189 - * vblank since we could end up overwriting the DLIST entries used by
190 - * previous commits if our dlist allocation reuses that entry. In such a
191 - * case, we would overwrite the data currently being used by the
192 - * hardware, resulting in a corrupted frame.
193 - *
194 - * In order to work around this, we'll queue the dlist entries in a list
195 - * once the associated CRTC state is destroyed. The HVS only allows us
196 - * to know which entry is being active, but not which one are no longer
197 - * being used, so in order to avoid freeing entries that are still used
198 - * by the hardware we add a guesstimate of the frame count where our
199 - * entry will no longer be used, and thus will only free those entries
200 - * when we will have reached that frame count.
201 - */
202 -static void vc4_hvs_dlist_free_work(struct work_struct *work)
203 -{
204 - struct vc4_hvs *hvs = container_of(work, struct vc4_hvs, free_dlist_work);
205 - struct vc4_hvs_dlist_allocation *cur, *next;
206 - unsigned long flags;
207 -
208 - spin_lock_irqsave(&hvs->mm_lock, flags);
209 - list_for_each_entry_safe(cur, next, &hvs->stale_dlist_entries, node) {
210 - u8 frcnt;
211 -
212 - frcnt = vc4_hvs_get_fifo_frame_count(hvs, cur->channel);
213 - if (!vc4_hvs_frcnt_lte(cur->target_frame_count, frcnt))
214 - continue;
215 -
216 - list_del(&cur->node);
217 - drm_mm_remove_node(&cur->mm_node);
218 - kfree(cur);
219 - }
220 - spin_unlock_irqrestore(&hvs->mm_lock, flags);
221 -}
222 -
223 u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo)
224 {
225 u8 field = 0;
226 @@ -732,12 +588,13 @@ int vc4_hvs_atomic_check(struct drm_crtc
227 {
228 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
229 struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
230 - struct vc4_hvs_dlist_allocation *alloc;
231 struct drm_device *dev = crtc->dev;
232 struct vc4_dev *vc4 = to_vc4_dev(dev);
233 struct drm_plane *plane;
234 + unsigned long flags;
235 const struct drm_plane_state *plane_state;
236 u32 dlist_count = 0;
237 + int ret;
238
239 /* The pixelvalve can only feed one encoder (and encoders are
240 * 1:1 with connectors.)
241 @@ -750,11 +607,12 @@ int vc4_hvs_atomic_check(struct drm_crtc
242
243 dlist_count++; /* Account for SCALER_CTL0_END. */
244
245 - alloc = vc4_hvs_alloc_dlist_entry(vc4->hvs, vc4_state->assigned_channel, dlist_count);
246 - if (IS_ERR(alloc))
247 - return PTR_ERR(alloc);
248 -
249 - vc4_state->mm = alloc;
250 + spin_lock_irqsave(&vc4->hvs->mm_lock, flags);
251 + ret = drm_mm_insert_node(&vc4->hvs->dlist_mm, &vc4_state->mm,
252 + dlist_count);
253 + spin_unlock_irqrestore(&vc4->hvs->mm_lock, flags);
254 + if (ret)
255 + return ret;
256
257 return vc4_hvs_gamma_check(crtc, state);
258 }
259 @@ -766,9 +624,8 @@ static void vc4_hvs_install_dlist(struct
260 struct vc4_hvs *hvs = vc4->hvs;
261 struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
262
263 - WARN_ON(!vc4_state->mm);
264 HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
265 - vc4_state->mm->mm_node.start);
266 + vc4_state->mm.start);
267 }
268
269 static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
270 @@ -793,10 +650,8 @@ static void vc4_hvs_update_dlist(struct
271 spin_unlock_irqrestore(&dev->event_lock, flags);
272 }
273
274 - WARN_ON(!vc4_state->mm);
275 -
276 spin_lock_irqsave(&vc4_crtc->irq_lock, flags);
277 - vc4_crtc->current_dlist = vc4_state->mm->mm_node.start;
278 + vc4_crtc->current_dlist = vc4_state->mm.start;
279 spin_unlock_irqrestore(&vc4_crtc->irq_lock, flags);
280 }
281
282 @@ -853,7 +708,8 @@ void vc4_hvs_atomic_flush(struct drm_crt
283 struct vc4_plane_state *vc4_plane_state;
284 bool debug_dump_regs = false;
285 bool enable_bg_fill = false;
286 - u32 __iomem *dlist_start, *dlist_next;
287 + u32 __iomem *dlist_start = vc4->hvs->dlist + vc4_state->mm.start;
288 + u32 __iomem *dlist_next = dlist_start;
289 unsigned int zpos = 0;
290 bool found = false;
291
292 @@ -865,9 +721,6 @@ void vc4_hvs_atomic_flush(struct drm_crt
293 vc4_hvs_dump_state(hvs);
294 }
295
296 - dlist_start = vc4->hvs->dlist + vc4_state->mm->mm_node.start;
297 - dlist_next = dlist_start;
298 -
299 /* Copy all the active planes' dlist contents to the hardware dlist. */
300 do {
301 found = false;
302 @@ -901,8 +754,7 @@ void vc4_hvs_atomic_flush(struct drm_crt
303 writel(SCALER_CTL0_END, dlist_next);
304 dlist_next++;
305
306 - WARN_ON(!vc4_state->mm);
307 - WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm->mm_node.size);
308 + WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm.size);
309
310 if (enable_bg_fill)
311 /* This sets a black background color fill, as is the case
312 @@ -1007,11 +859,6 @@ static irqreturn_t vc4_hvs_irq_handler(i
313
314 irqret = IRQ_HANDLED;
315 }
316 -
317 - if (status & SCALER_DISPSTAT_EOF(channel)) {
318 - vc4_hvs_schedule_dlist_sweep(hvs, channel);
319 - irqret = IRQ_HANDLED;
320 - }
321 }
322
323 /* Clear every per-channel interrupt flag. */
324 @@ -1069,8 +916,6 @@ static int vc4_hvs_bind(struct device *d
325 hvs->dlist = hvs->regs + SCALER5_DLIST_START;
326
327 spin_lock_init(&hvs->mm_lock);
328 - INIT_LIST_HEAD(&hvs->stale_dlist_entries);
329 - INIT_WORK(&hvs->free_dlist_work, vc4_hvs_dlist_free_work);
330
331 /* Set up the HVS display list memory manager. We never
332 * overwrite the setup from the bootloader (just 128b out of
333 --- a/drivers/gpu/drm/vc4/vc4_regs.h
334 +++ b/drivers/gpu/drm/vc4/vc4_regs.h
335 @@ -240,7 +240,6 @@
336 # define SCALER_DISPCTRL_DSPEIEOLN(x) BIT(8 + ((x) * 2))
337 /* Enables Display 0 EOF contribution to SCALER_DISPSTAT_IRQDISP0 */
338 # define SCALER_DISPCTRL_DSPEIEOF(x) BIT(7 + ((x) * 2))
339 -# define SCALER5_DISPCTRL_DSPEIEOF(x) BIT(7 + ((x) * 4))
340
341 # define SCALER_DISPCTRL_SLVRDEIRQ BIT(6)
342 # define SCALER_DISPCTRL_SLVWREIRQ BIT(5)