fix short copy handling in copy_mc_pipe_to_iter()
[sfrench/cifs-2.6.git] / drivers / gpu / drm / vc4 / vc4_irq.c
1 /*
2  * Copyright © 2014 Broadcom
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23
24 /**
25  * DOC: Interrupt management for the V3D engine
26  *
27  * We have an interrupt status register (V3D_INTCTL) which reports
28  * interrupts, and where writing 1 bits clears those interrupts.
29  * There are also a pair of interrupt registers
30  * (V3D_INTENA/V3D_INTDIS) where writing a 1 to their bits enables or
31  * disables that specific interrupt, and 0s written are ignored
32  * (reading either one returns the set of enabled interrupts).
33  *
34  * When we take a binning flush done interrupt, we need to submit the
35  * next frame for binning and move the finished frame to the render
36  * thread.
37  *
38  * When we take a render frame interrupt, we need to wake the
39  * processes waiting for some frame to be done, and get the next frame
40  * submitted ASAP (so the hardware doesn't sit idle when there's work
41  * to do).
42  *
43  * When we take the binner out of memory interrupt, we need to
44  * allocate some new memory and pass it to the binner so that the
45  * current job can make progress.
46  */
47
48 #include <linux/platform_device.h>
49
50 #include <drm/drm_drv.h>
51
52 #include "vc4_drv.h"
53 #include "vc4_regs.h"
54 #include "vc4_trace.h"
55
56 #define V3D_DRIVER_IRQS (V3D_INT_OUTOMEM | \
57                          V3D_INT_FLDONE | \
58                          V3D_INT_FRDONE)
59
60 DECLARE_WAIT_QUEUE_HEAD(render_wait);
61
62 static void
63 vc4_overflow_mem_work(struct work_struct *work)
64 {
65         struct vc4_dev *vc4 =
66                 container_of(work, struct vc4_dev, overflow_mem_work);
67         struct vc4_bo *bo;
68         int bin_bo_slot;
69         struct vc4_exec_info *exec;
70         unsigned long irqflags;
71
72         mutex_lock(&vc4->bin_bo_lock);
73
74         if (!vc4->bin_bo)
75                 goto complete;
76
77         bo = vc4->bin_bo;
78
79         bin_bo_slot = vc4_v3d_get_bin_slot(vc4);
80         if (bin_bo_slot < 0) {
81                 DRM_ERROR("Couldn't allocate binner overflow mem\n");
82                 goto complete;
83         }
84
85         spin_lock_irqsave(&vc4->job_lock, irqflags);
86
87         if (vc4->bin_alloc_overflow) {
88                 /* If we had overflow memory allocated previously,
89                  * then that chunk will free when the current bin job
90                  * is done.  If we don't have a bin job running, then
91                  * the chunk will be done whenever the list of render
92                  * jobs has drained.
93                  */
94                 exec = vc4_first_bin_job(vc4);
95                 if (!exec)
96                         exec = vc4_last_render_job(vc4);
97                 if (exec) {
98                         exec->bin_slots |= vc4->bin_alloc_overflow;
99                 } else {
100                         /* There's nothing queued in the hardware, so
101                          * the old slot is free immediately.
102                          */
103                         vc4->bin_alloc_used &= ~vc4->bin_alloc_overflow;
104                 }
105         }
106         vc4->bin_alloc_overflow = BIT(bin_bo_slot);
107
108         V3D_WRITE(V3D_BPOA, bo->base.paddr + bin_bo_slot * vc4->bin_alloc_size);
109         V3D_WRITE(V3D_BPOS, bo->base.base.size);
110         V3D_WRITE(V3D_INTCTL, V3D_INT_OUTOMEM);
111         V3D_WRITE(V3D_INTENA, V3D_INT_OUTOMEM);
112         spin_unlock_irqrestore(&vc4->job_lock, irqflags);
113
114 complete:
115         mutex_unlock(&vc4->bin_bo_lock);
116 }
117
118 static void
119 vc4_irq_finish_bin_job(struct drm_device *dev)
120 {
121         struct vc4_dev *vc4 = to_vc4_dev(dev);
122         struct vc4_exec_info *next, *exec = vc4_first_bin_job(vc4);
123
124         if (!exec)
125                 return;
126
127         trace_vc4_bcl_end_irq(dev, exec->seqno);
128
129         vc4_move_job_to_render(dev, exec);
130         next = vc4_first_bin_job(vc4);
131
132         /* Only submit the next job in the bin list if it matches the perfmon
133          * attached to the one that just finished (or if both jobs don't have
134          * perfmon attached to them).
135          */
136         if (next && next->perfmon == exec->perfmon)
137                 vc4_submit_next_bin_job(dev);
138 }
139
140 static void
141 vc4_cancel_bin_job(struct drm_device *dev)
142 {
143         struct vc4_dev *vc4 = to_vc4_dev(dev);
144         struct vc4_exec_info *exec = vc4_first_bin_job(vc4);
145
146         if (!exec)
147                 return;
148
149         /* Stop the perfmon so that the next bin job can be started. */
150         if (exec->perfmon)
151                 vc4_perfmon_stop(vc4, exec->perfmon, false);
152
153         list_move_tail(&exec->head, &vc4->bin_job_list);
154         vc4_submit_next_bin_job(dev);
155 }
156
157 static void
158 vc4_irq_finish_render_job(struct drm_device *dev)
159 {
160         struct vc4_dev *vc4 = to_vc4_dev(dev);
161         struct vc4_exec_info *exec = vc4_first_render_job(vc4);
162         struct vc4_exec_info *nextbin, *nextrender;
163
164         if (!exec)
165                 return;
166
167         trace_vc4_rcl_end_irq(dev, exec->seqno);
168
169         vc4->finished_seqno++;
170         list_move_tail(&exec->head, &vc4->job_done_list);
171
172         nextbin = vc4_first_bin_job(vc4);
173         nextrender = vc4_first_render_job(vc4);
174
175         /* Only stop the perfmon if following jobs in the queue don't expect it
176          * to be enabled.
177          */
178         if (exec->perfmon && !nextrender &&
179             (!nextbin || nextbin->perfmon != exec->perfmon))
180                 vc4_perfmon_stop(vc4, exec->perfmon, true);
181
182         /* If there's a render job waiting, start it. If this is not the case
183          * we may have to unblock the binner if it's been stalled because of
184          * perfmon (this can be checked by comparing the perfmon attached to
185          * the finished renderjob to the one attached to the next bin job: if
186          * they don't match, this means the binner is stalled and should be
187          * restarted).
188          */
189         if (nextrender)
190                 vc4_submit_next_render_job(dev);
191         else if (nextbin && nextbin->perfmon != exec->perfmon)
192                 vc4_submit_next_bin_job(dev);
193
194         if (exec->fence) {
195                 dma_fence_signal_locked(exec->fence);
196                 dma_fence_put(exec->fence);
197                 exec->fence = NULL;
198         }
199
200         wake_up_all(&vc4->job_wait_queue);
201         schedule_work(&vc4->job_done_work);
202 }
203
204 static irqreturn_t
205 vc4_irq(int irq, void *arg)
206 {
207         struct drm_device *dev = arg;
208         struct vc4_dev *vc4 = to_vc4_dev(dev);
209         uint32_t intctl;
210         irqreturn_t status = IRQ_NONE;
211
212         barrier();
213         intctl = V3D_READ(V3D_INTCTL);
214
215         /* Acknowledge the interrupts we're handling here. The binner
216          * last flush / render frame done interrupt will be cleared,
217          * while OUTOMEM will stay high until the underlying cause is
218          * cleared.
219          */
220         V3D_WRITE(V3D_INTCTL, intctl);
221
222         if (intctl & V3D_INT_OUTOMEM) {
223                 /* Disable OUTOMEM until the work is done. */
224                 V3D_WRITE(V3D_INTDIS, V3D_INT_OUTOMEM);
225                 schedule_work(&vc4->overflow_mem_work);
226                 status = IRQ_HANDLED;
227         }
228
229         if (intctl & V3D_INT_FLDONE) {
230                 spin_lock(&vc4->job_lock);
231                 vc4_irq_finish_bin_job(dev);
232                 spin_unlock(&vc4->job_lock);
233                 status = IRQ_HANDLED;
234         }
235
236         if (intctl & V3D_INT_FRDONE) {
237                 spin_lock(&vc4->job_lock);
238                 vc4_irq_finish_render_job(dev);
239                 spin_unlock(&vc4->job_lock);
240                 status = IRQ_HANDLED;
241         }
242
243         return status;
244 }
245
246 static void
247 vc4_irq_prepare(struct drm_device *dev)
248 {
249         struct vc4_dev *vc4 = to_vc4_dev(dev);
250
251         if (!vc4->v3d)
252                 return;
253
254         init_waitqueue_head(&vc4->job_wait_queue);
255         INIT_WORK(&vc4->overflow_mem_work, vc4_overflow_mem_work);
256
257         /* Clear any pending interrupts someone might have left around
258          * for us.
259          */
260         V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
261 }
262
263 void
264 vc4_irq_enable(struct drm_device *dev)
265 {
266         struct vc4_dev *vc4 = to_vc4_dev(dev);
267
268         if (!vc4->v3d)
269                 return;
270
271         /* Enable the render done interrupts. The out-of-memory interrupt is
272          * enabled as soon as we have a binner BO allocated.
273          */
274         V3D_WRITE(V3D_INTENA, V3D_INT_FLDONE | V3D_INT_FRDONE);
275 }
276
277 void
278 vc4_irq_disable(struct drm_device *dev)
279 {
280         struct vc4_dev *vc4 = to_vc4_dev(dev);
281
282         if (!vc4->v3d)
283                 return;
284
285         /* Disable sending interrupts for our driver's IRQs. */
286         V3D_WRITE(V3D_INTDIS, V3D_DRIVER_IRQS);
287
288         /* Clear any pending interrupts we might have left. */
289         V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
290
291         /* Finish any interrupt handler still in flight. */
292         disable_irq(vc4->irq);
293
294         cancel_work_sync(&vc4->overflow_mem_work);
295 }
296
297 int vc4_irq_install(struct drm_device *dev, int irq)
298 {
299         int ret;
300
301         if (irq == IRQ_NOTCONNECTED)
302                 return -ENOTCONN;
303
304         vc4_irq_prepare(dev);
305
306         ret = request_irq(irq, vc4_irq, 0, dev->driver->name, dev);
307         if (ret)
308                 return ret;
309
310         vc4_irq_enable(dev);
311
312         return 0;
313 }
314
315 void vc4_irq_uninstall(struct drm_device *dev)
316 {
317         struct vc4_dev *vc4 = to_vc4_dev(dev);
318
319         vc4_irq_disable(dev);
320         free_irq(vc4->irq, dev);
321 }
322
323 /** Reinitializes interrupt registers when a GPU reset is performed. */
324 void vc4_irq_reset(struct drm_device *dev)
325 {
326         struct vc4_dev *vc4 = to_vc4_dev(dev);
327         unsigned long irqflags;
328
329         /* Acknowledge any stale IRQs. */
330         V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
331
332         /*
333          * Turn all our interrupts on.  Binner out of memory is the
334          * only one we expect to trigger at this point, since we've
335          * just come from poweron and haven't supplied any overflow
336          * memory yet.
337          */
338         V3D_WRITE(V3D_INTENA, V3D_DRIVER_IRQS);
339
340         spin_lock_irqsave(&vc4->job_lock, irqflags);
341         vc4_cancel_bin_job(dev);
342         vc4_irq_finish_render_job(dev);
343         spin_unlock_irqrestore(&vc4->job_lock, irqflags);
344 }