blob: a9d020e7e891c89d14d139baa6d5a71aff2d2949 [file] [log] [blame]
Eric Anholtd5b1a782015-11-30 12:13:37 -08001/*
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#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/device.h>
27#include <linux/io.h>
28
29#include "uapi/drm/vc4_drm.h"
30#include "vc4_drv.h"
31#include "vc4_regs.h"
32#include "vc4_trace.h"
33
34static void
35vc4_queue_hangcheck(struct drm_device *dev)
36{
37 struct vc4_dev *vc4 = to_vc4_dev(dev);
38
39 mod_timer(&vc4->hangcheck.timer,
40 round_jiffies_up(jiffies + msecs_to_jiffies(100)));
41}
42
Eric Anholt21461362015-10-30 10:09:02 -070043struct vc4_hang_state {
44 struct drm_vc4_get_hang_state user_state;
45
46 u32 bo_count;
47 struct drm_gem_object **bo;
48};
49
50static void
51vc4_free_hang_state(struct drm_device *dev, struct vc4_hang_state *state)
52{
53 unsigned int i;
54
55 mutex_lock(&dev->struct_mutex);
56 for (i = 0; i < state->user_state.bo_count; i++)
57 drm_gem_object_unreference(state->bo[i]);
58 mutex_unlock(&dev->struct_mutex);
59
60 kfree(state);
61}
62
63int
64vc4_get_hang_state_ioctl(struct drm_device *dev, void *data,
65 struct drm_file *file_priv)
66{
67 struct drm_vc4_get_hang_state *get_state = data;
68 struct drm_vc4_get_hang_state_bo *bo_state;
69 struct vc4_hang_state *kernel_state;
70 struct drm_vc4_get_hang_state *state;
71 struct vc4_dev *vc4 = to_vc4_dev(dev);
72 unsigned long irqflags;
73 u32 i;
Dan Carpenter65c47772015-12-17 15:36:28 +030074 int ret = 0;
Eric Anholt21461362015-10-30 10:09:02 -070075
76 spin_lock_irqsave(&vc4->job_lock, irqflags);
77 kernel_state = vc4->hang_state;
78 if (!kernel_state) {
79 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
80 return -ENOENT;
81 }
82 state = &kernel_state->user_state;
83
84 /* If the user's array isn't big enough, just return the
85 * required array size.
86 */
87 if (get_state->bo_count < state->bo_count) {
88 get_state->bo_count = state->bo_count;
89 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
90 return 0;
91 }
92
93 vc4->hang_state = NULL;
94 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
95
96 /* Save the user's BO pointer, so we don't stomp it with the memcpy. */
97 state->bo = get_state->bo;
98 memcpy(get_state, state, sizeof(*state));
99
100 bo_state = kcalloc(state->bo_count, sizeof(*bo_state), GFP_KERNEL);
101 if (!bo_state) {
102 ret = -ENOMEM;
103 goto err_free;
104 }
105
106 for (i = 0; i < state->bo_count; i++) {
107 struct vc4_bo *vc4_bo = to_vc4_bo(kernel_state->bo[i]);
108 u32 handle;
109
110 ret = drm_gem_handle_create(file_priv, kernel_state->bo[i],
111 &handle);
112
113 if (ret) {
114 state->bo_count = i - 1;
115 goto err;
116 }
117 bo_state[i].handle = handle;
118 bo_state[i].paddr = vc4_bo->base.paddr;
119 bo_state[i].size = vc4_bo->base.base.size;
120 }
121
Dan Carpenter65c47772015-12-17 15:36:28 +0300122 if (copy_to_user((void __user *)(uintptr_t)get_state->bo,
123 bo_state,
124 state->bo_count * sizeof(*bo_state)))
125 ret = -EFAULT;
126
Eric Anholt21461362015-10-30 10:09:02 -0700127 kfree(bo_state);
128
129err_free:
130
131 vc4_free_hang_state(dev, kernel_state);
132
133err:
134 return ret;
135}
136
137static void
138vc4_save_hang_state(struct drm_device *dev)
139{
140 struct vc4_dev *vc4 = to_vc4_dev(dev);
141 struct drm_vc4_get_hang_state *state;
142 struct vc4_hang_state *kernel_state;
143 struct vc4_exec_info *exec;
144 struct vc4_bo *bo;
145 unsigned long irqflags;
146 unsigned int i, unref_list_count;
147
Dan Carpenter7e5082f2015-12-17 15:39:08 +0300148 kernel_state = kcalloc(1, sizeof(*kernel_state), GFP_KERNEL);
Eric Anholt21461362015-10-30 10:09:02 -0700149 if (!kernel_state)
150 return;
151
152 state = &kernel_state->user_state;
153
154 spin_lock_irqsave(&vc4->job_lock, irqflags);
155 exec = vc4_first_job(vc4);
156 if (!exec) {
157 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
158 return;
159 }
160
161 unref_list_count = 0;
162 list_for_each_entry(bo, &exec->unref_list, unref_head)
163 unref_list_count++;
164
165 state->bo_count = exec->bo_count + unref_list_count;
166 kernel_state->bo = kcalloc(state->bo_count, sizeof(*kernel_state->bo),
167 GFP_ATOMIC);
168 if (!kernel_state->bo) {
169 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
170 return;
171 }
172
173 for (i = 0; i < exec->bo_count; i++) {
174 drm_gem_object_reference(&exec->bo[i]->base);
175 kernel_state->bo[i] = &exec->bo[i]->base;
176 }
177
178 list_for_each_entry(bo, &exec->unref_list, unref_head) {
179 drm_gem_object_reference(&bo->base.base);
180 kernel_state->bo[i] = &bo->base.base;
181 i++;
182 }
183
184 state->start_bin = exec->ct0ca;
185 state->start_render = exec->ct1ca;
186
187 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
188
189 state->ct0ca = V3D_READ(V3D_CTNCA(0));
190 state->ct0ea = V3D_READ(V3D_CTNEA(0));
191
192 state->ct1ca = V3D_READ(V3D_CTNCA(1));
193 state->ct1ea = V3D_READ(V3D_CTNEA(1));
194
195 state->ct0cs = V3D_READ(V3D_CTNCS(0));
196 state->ct1cs = V3D_READ(V3D_CTNCS(1));
197
198 state->ct0ra0 = V3D_READ(V3D_CT00RA0);
199 state->ct1ra0 = V3D_READ(V3D_CT01RA0);
200
201 state->bpca = V3D_READ(V3D_BPCA);
202 state->bpcs = V3D_READ(V3D_BPCS);
203 state->bpoa = V3D_READ(V3D_BPOA);
204 state->bpos = V3D_READ(V3D_BPOS);
205
206 state->vpmbase = V3D_READ(V3D_VPMBASE);
207
208 state->dbge = V3D_READ(V3D_DBGE);
209 state->fdbgo = V3D_READ(V3D_FDBGO);
210 state->fdbgb = V3D_READ(V3D_FDBGB);
211 state->fdbgr = V3D_READ(V3D_FDBGR);
212 state->fdbgs = V3D_READ(V3D_FDBGS);
213 state->errstat = V3D_READ(V3D_ERRSTAT);
214
215 spin_lock_irqsave(&vc4->job_lock, irqflags);
216 if (vc4->hang_state) {
217 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
218 vc4_free_hang_state(dev, kernel_state);
219 } else {
220 vc4->hang_state = kernel_state;
221 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
222 }
223}
224
Eric Anholtd5b1a782015-11-30 12:13:37 -0800225static void
226vc4_reset(struct drm_device *dev)
227{
228 struct vc4_dev *vc4 = to_vc4_dev(dev);
229
230 DRM_INFO("Resetting GPU.\n");
231 vc4_v3d_set_power(vc4, false);
232 vc4_v3d_set_power(vc4, true);
233
234 vc4_irq_reset(dev);
235
236 /* Rearm the hangcheck -- another job might have been waiting
237 * for our hung one to get kicked off, and vc4_irq_reset()
238 * would have started it.
239 */
240 vc4_queue_hangcheck(dev);
241}
242
243static void
244vc4_reset_work(struct work_struct *work)
245{
246 struct vc4_dev *vc4 =
247 container_of(work, struct vc4_dev, hangcheck.reset_work);
248
Eric Anholt21461362015-10-30 10:09:02 -0700249 vc4_save_hang_state(vc4->dev);
250
Eric Anholtd5b1a782015-11-30 12:13:37 -0800251 vc4_reset(vc4->dev);
252}
253
254static void
255vc4_hangcheck_elapsed(unsigned long data)
256{
257 struct drm_device *dev = (struct drm_device *)data;
258 struct vc4_dev *vc4 = to_vc4_dev(dev);
259 uint32_t ct0ca, ct1ca;
260
261 /* If idle, we can stop watching for hangs. */
262 if (list_empty(&vc4->job_list))
263 return;
264
265 ct0ca = V3D_READ(V3D_CTNCA(0));
266 ct1ca = V3D_READ(V3D_CTNCA(1));
267
268 /* If we've made any progress in execution, rearm the timer
269 * and wait.
270 */
271 if (ct0ca != vc4->hangcheck.last_ct0ca ||
272 ct1ca != vc4->hangcheck.last_ct1ca) {
273 vc4->hangcheck.last_ct0ca = ct0ca;
274 vc4->hangcheck.last_ct1ca = ct1ca;
275 vc4_queue_hangcheck(dev);
276 return;
277 }
278
279 /* We've gone too long with no progress, reset. This has to
280 * be done from a work struct, since resetting can sleep and
281 * this timer hook isn't allowed to.
282 */
283 schedule_work(&vc4->hangcheck.reset_work);
284}
285
286static void
287submit_cl(struct drm_device *dev, uint32_t thread, uint32_t start, uint32_t end)
288{
289 struct vc4_dev *vc4 = to_vc4_dev(dev);
290
291 /* Set the current and end address of the control list.
292 * Writing the end register is what starts the job.
293 */
294 V3D_WRITE(V3D_CTNCA(thread), start);
295 V3D_WRITE(V3D_CTNEA(thread), end);
296}
297
298int
299vc4_wait_for_seqno(struct drm_device *dev, uint64_t seqno, uint64_t timeout_ns,
300 bool interruptible)
301{
302 struct vc4_dev *vc4 = to_vc4_dev(dev);
303 int ret = 0;
304 unsigned long timeout_expire;
305 DEFINE_WAIT(wait);
306
307 if (vc4->finished_seqno >= seqno)
308 return 0;
309
310 if (timeout_ns == 0)
311 return -ETIME;
312
313 timeout_expire = jiffies + nsecs_to_jiffies(timeout_ns);
314
315 trace_vc4_wait_for_seqno_begin(dev, seqno, timeout_ns);
316 for (;;) {
317 prepare_to_wait(&vc4->job_wait_queue, &wait,
318 interruptible ? TASK_INTERRUPTIBLE :
319 TASK_UNINTERRUPTIBLE);
320
321 if (interruptible && signal_pending(current)) {
322 ret = -ERESTARTSYS;
323 break;
324 }
325
326 if (vc4->finished_seqno >= seqno)
327 break;
328
329 if (timeout_ns != ~0ull) {
330 if (time_after_eq(jiffies, timeout_expire)) {
331 ret = -ETIME;
332 break;
333 }
334 schedule_timeout(timeout_expire - jiffies);
335 } else {
336 schedule();
337 }
338 }
339
340 finish_wait(&vc4->job_wait_queue, &wait);
341 trace_vc4_wait_for_seqno_end(dev, seqno);
342
Eric Anholt13cf8902016-01-25 14:32:41 -0800343 return ret;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800344}
345
346static void
347vc4_flush_caches(struct drm_device *dev)
348{
349 struct vc4_dev *vc4 = to_vc4_dev(dev);
350
351 /* Flush the GPU L2 caches. These caches sit on top of system
352 * L3 (the 128kb or so shared with the CPU), and are
353 * non-allocating in the L3.
354 */
355 V3D_WRITE(V3D_L2CACTL,
356 V3D_L2CACTL_L2CCLR);
357
358 V3D_WRITE(V3D_SLCACTL,
359 VC4_SET_FIELD(0xf, V3D_SLCACTL_T1CC) |
360 VC4_SET_FIELD(0xf, V3D_SLCACTL_T0CC) |
361 VC4_SET_FIELD(0xf, V3D_SLCACTL_UCC) |
362 VC4_SET_FIELD(0xf, V3D_SLCACTL_ICC));
363}
364
365/* Sets the registers for the next job to be actually be executed in
366 * the hardware.
367 *
368 * The job_lock should be held during this.
369 */
370void
371vc4_submit_next_job(struct drm_device *dev)
372{
373 struct vc4_dev *vc4 = to_vc4_dev(dev);
374 struct vc4_exec_info *exec = vc4_first_job(vc4);
375
376 if (!exec)
377 return;
378
379 vc4_flush_caches(dev);
380
381 /* Disable the binner's pre-loaded overflow memory address */
382 V3D_WRITE(V3D_BPOA, 0);
383 V3D_WRITE(V3D_BPOS, 0);
384
385 if (exec->ct0ca != exec->ct0ea)
386 submit_cl(dev, 0, exec->ct0ca, exec->ct0ea);
387 submit_cl(dev, 1, exec->ct1ca, exec->ct1ea);
388}
389
390static void
391vc4_update_bo_seqnos(struct vc4_exec_info *exec, uint64_t seqno)
392{
393 struct vc4_bo *bo;
394 unsigned i;
395
396 for (i = 0; i < exec->bo_count; i++) {
397 bo = to_vc4_bo(&exec->bo[i]->base);
398 bo->seqno = seqno;
399 }
400
401 list_for_each_entry(bo, &exec->unref_list, unref_head) {
402 bo->seqno = seqno;
403 }
404}
405
406/* Queues a struct vc4_exec_info for execution. If no job is
407 * currently executing, then submits it.
408 *
409 * Unlike most GPUs, our hardware only handles one command list at a
410 * time. To queue multiple jobs at once, we'd need to edit the
411 * previous command list to have a jump to the new one at the end, and
412 * then bump the end address. That's a change for a later date,
413 * though.
414 */
415static void
416vc4_queue_submit(struct drm_device *dev, struct vc4_exec_info *exec)
417{
418 struct vc4_dev *vc4 = to_vc4_dev(dev);
419 uint64_t seqno;
420 unsigned long irqflags;
421
422 spin_lock_irqsave(&vc4->job_lock, irqflags);
423
424 seqno = ++vc4->emit_seqno;
425 exec->seqno = seqno;
426 vc4_update_bo_seqnos(exec, seqno);
427
428 list_add_tail(&exec->head, &vc4->job_list);
429
430 /* If no job was executing, kick ours off. Otherwise, it'll
431 * get started when the previous job's frame done interrupt
432 * occurs.
433 */
434 if (vc4_first_job(vc4) == exec) {
435 vc4_submit_next_job(dev);
436 vc4_queue_hangcheck(dev);
437 }
438
439 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
440}
441
442/**
443 * Looks up a bunch of GEM handles for BOs and stores the array for
444 * use in the command validator that actually writes relocated
445 * addresses pointing to them.
446 */
447static int
448vc4_cl_lookup_bos(struct drm_device *dev,
449 struct drm_file *file_priv,
450 struct vc4_exec_info *exec)
451{
452 struct drm_vc4_submit_cl *args = exec->args;
453 uint32_t *handles;
454 int ret = 0;
455 int i;
456
457 exec->bo_count = args->bo_handle_count;
458
459 if (!exec->bo_count) {
460 /* See comment on bo_index for why we have to check
461 * this.
462 */
463 DRM_ERROR("Rendering requires BOs to validate\n");
464 return -EINVAL;
465 }
466
467 exec->bo = kcalloc(exec->bo_count, sizeof(struct drm_gem_cma_object *),
468 GFP_KERNEL);
469 if (!exec->bo) {
470 DRM_ERROR("Failed to allocate validated BO pointers\n");
471 return -ENOMEM;
472 }
473
474 handles = drm_malloc_ab(exec->bo_count, sizeof(uint32_t));
475 if (!handles) {
476 DRM_ERROR("Failed to allocate incoming GEM handles\n");
477 goto fail;
478 }
479
480 ret = copy_from_user(handles,
481 (void __user *)(uintptr_t)args->bo_handles,
482 exec->bo_count * sizeof(uint32_t));
483 if (ret) {
484 DRM_ERROR("Failed to copy in GEM handles\n");
485 goto fail;
486 }
487
488 spin_lock(&file_priv->table_lock);
489 for (i = 0; i < exec->bo_count; i++) {
490 struct drm_gem_object *bo = idr_find(&file_priv->object_idr,
491 handles[i]);
492 if (!bo) {
493 DRM_ERROR("Failed to look up GEM BO %d: %d\n",
494 i, handles[i]);
495 ret = -EINVAL;
496 spin_unlock(&file_priv->table_lock);
497 goto fail;
498 }
499 drm_gem_object_reference(bo);
500 exec->bo[i] = (struct drm_gem_cma_object *)bo;
501 }
502 spin_unlock(&file_priv->table_lock);
503
504fail:
505 kfree(handles);
506 return 0;
507}
508
509static int
510vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec)
511{
512 struct drm_vc4_submit_cl *args = exec->args;
513 void *temp = NULL;
514 void *bin;
515 int ret = 0;
516 uint32_t bin_offset = 0;
517 uint32_t shader_rec_offset = roundup(bin_offset + args->bin_cl_size,
518 16);
519 uint32_t uniforms_offset = shader_rec_offset + args->shader_rec_size;
520 uint32_t exec_size = uniforms_offset + args->uniforms_size;
521 uint32_t temp_size = exec_size + (sizeof(struct vc4_shader_state) *
522 args->shader_rec_count);
523 struct vc4_bo *bo;
524
525 if (uniforms_offset < shader_rec_offset ||
526 exec_size < uniforms_offset ||
527 args->shader_rec_count >= (UINT_MAX /
528 sizeof(struct vc4_shader_state)) ||
529 temp_size < exec_size) {
530 DRM_ERROR("overflow in exec arguments\n");
531 goto fail;
532 }
533
534 /* Allocate space where we'll store the copied in user command lists
535 * and shader records.
536 *
537 * We don't just copy directly into the BOs because we need to
538 * read the contents back for validation, and I think the
539 * bo->vaddr is uncached access.
540 */
541 temp = kmalloc(temp_size, GFP_KERNEL);
542 if (!temp) {
543 DRM_ERROR("Failed to allocate storage for copying "
544 "in bin/render CLs.\n");
545 ret = -ENOMEM;
546 goto fail;
547 }
548 bin = temp + bin_offset;
549 exec->shader_rec_u = temp + shader_rec_offset;
550 exec->uniforms_u = temp + uniforms_offset;
551 exec->shader_state = temp + exec_size;
552 exec->shader_state_size = args->shader_rec_count;
553
Dan Carpenter65c47772015-12-17 15:36:28 +0300554 if (copy_from_user(bin,
555 (void __user *)(uintptr_t)args->bin_cl,
556 args->bin_cl_size)) {
557 ret = -EFAULT;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800558 goto fail;
559 }
560
Dan Carpenter65c47772015-12-17 15:36:28 +0300561 if (copy_from_user(exec->shader_rec_u,
562 (void __user *)(uintptr_t)args->shader_rec,
563 args->shader_rec_size)) {
564 ret = -EFAULT;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800565 goto fail;
566 }
567
Dan Carpenter65c47772015-12-17 15:36:28 +0300568 if (copy_from_user(exec->uniforms_u,
569 (void __user *)(uintptr_t)args->uniforms,
570 args->uniforms_size)) {
571 ret = -EFAULT;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800572 goto fail;
573 }
574
575 bo = vc4_bo_create(dev, exec_size, true);
Eric Anholt2c68f1f2016-01-25 14:13:12 -0800576 if (IS_ERR(bo)) {
Eric Anholtd5b1a782015-11-30 12:13:37 -0800577 DRM_ERROR("Couldn't allocate BO for binning\n");
Eric Anholt2c68f1f2016-01-25 14:13:12 -0800578 ret = PTR_ERR(bo);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800579 goto fail;
580 }
581 exec->exec_bo = &bo->base;
582
583 list_add_tail(&to_vc4_bo(&exec->exec_bo->base)->unref_head,
584 &exec->unref_list);
585
586 exec->ct0ca = exec->exec_bo->paddr + bin_offset;
587
588 exec->bin_u = bin;
589
590 exec->shader_rec_v = exec->exec_bo->vaddr + shader_rec_offset;
591 exec->shader_rec_p = exec->exec_bo->paddr + shader_rec_offset;
592 exec->shader_rec_size = args->shader_rec_size;
593
594 exec->uniforms_v = exec->exec_bo->vaddr + uniforms_offset;
595 exec->uniforms_p = exec->exec_bo->paddr + uniforms_offset;
596 exec->uniforms_size = args->uniforms_size;
597
598 ret = vc4_validate_bin_cl(dev,
599 exec->exec_bo->vaddr + bin_offset,
600 bin,
601 exec);
602 if (ret)
603 goto fail;
604
605 ret = vc4_validate_shader_recs(dev, exec);
606
607fail:
608 kfree(temp);
609 return ret;
610}
611
612static void
613vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec)
614{
615 unsigned i;
616
617 /* Need the struct lock for drm_gem_object_unreference(). */
618 mutex_lock(&dev->struct_mutex);
619 if (exec->bo) {
620 for (i = 0; i < exec->bo_count; i++)
621 drm_gem_object_unreference(&exec->bo[i]->base);
622 kfree(exec->bo);
623 }
624
625 while (!list_empty(&exec->unref_list)) {
626 struct vc4_bo *bo = list_first_entry(&exec->unref_list,
627 struct vc4_bo, unref_head);
628 list_del(&bo->unref_head);
629 drm_gem_object_unreference(&bo->base.base);
630 }
631 mutex_unlock(&dev->struct_mutex);
632
633 kfree(exec);
634}
635
636void
637vc4_job_handle_completed(struct vc4_dev *vc4)
638{
639 unsigned long irqflags;
Eric Anholtb501bac2015-11-30 12:34:01 -0800640 struct vc4_seqno_cb *cb, *cb_temp;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800641
642 spin_lock_irqsave(&vc4->job_lock, irqflags);
643 while (!list_empty(&vc4->job_done_list)) {
644 struct vc4_exec_info *exec =
645 list_first_entry(&vc4->job_done_list,
646 struct vc4_exec_info, head);
647 list_del(&exec->head);
648
649 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
650 vc4_complete_exec(vc4->dev, exec);
651 spin_lock_irqsave(&vc4->job_lock, irqflags);
652 }
Eric Anholtb501bac2015-11-30 12:34:01 -0800653
654 list_for_each_entry_safe(cb, cb_temp, &vc4->seqno_cb_list, work.entry) {
655 if (cb->seqno <= vc4->finished_seqno) {
656 list_del_init(&cb->work.entry);
657 schedule_work(&cb->work);
658 }
659 }
660
Eric Anholtd5b1a782015-11-30 12:13:37 -0800661 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
662}
663
Eric Anholtb501bac2015-11-30 12:34:01 -0800664static void vc4_seqno_cb_work(struct work_struct *work)
665{
666 struct vc4_seqno_cb *cb = container_of(work, struct vc4_seqno_cb, work);
667
668 cb->func(cb);
669}
670
671int vc4_queue_seqno_cb(struct drm_device *dev,
672 struct vc4_seqno_cb *cb, uint64_t seqno,
673 void (*func)(struct vc4_seqno_cb *cb))
674{
675 struct vc4_dev *vc4 = to_vc4_dev(dev);
676 int ret = 0;
677 unsigned long irqflags;
678
679 cb->func = func;
680 INIT_WORK(&cb->work, vc4_seqno_cb_work);
681
682 spin_lock_irqsave(&vc4->job_lock, irqflags);
683 if (seqno > vc4->finished_seqno) {
684 cb->seqno = seqno;
685 list_add_tail(&cb->work.entry, &vc4->seqno_cb_list);
686 } else {
687 schedule_work(&cb->work);
688 }
689 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
690
691 return ret;
692}
693
Eric Anholtd5b1a782015-11-30 12:13:37 -0800694/* Scheduled when any job has been completed, this walks the list of
695 * jobs that had completed and unrefs their BOs and frees their exec
696 * structs.
697 */
698static void
699vc4_job_done_work(struct work_struct *work)
700{
701 struct vc4_dev *vc4 =
702 container_of(work, struct vc4_dev, job_done_work);
703
704 vc4_job_handle_completed(vc4);
705}
706
707static int
708vc4_wait_for_seqno_ioctl_helper(struct drm_device *dev,
709 uint64_t seqno,
710 uint64_t *timeout_ns)
711{
712 unsigned long start = jiffies;
713 int ret = vc4_wait_for_seqno(dev, seqno, *timeout_ns, true);
714
715 if ((ret == -EINTR || ret == -ERESTARTSYS) && *timeout_ns != ~0ull) {
716 uint64_t delta = jiffies_to_nsecs(jiffies - start);
717
718 if (*timeout_ns >= delta)
719 *timeout_ns -= delta;
720 }
721
722 return ret;
723}
724
725int
726vc4_wait_seqno_ioctl(struct drm_device *dev, void *data,
727 struct drm_file *file_priv)
728{
729 struct drm_vc4_wait_seqno *args = data;
730
731 return vc4_wait_for_seqno_ioctl_helper(dev, args->seqno,
732 &args->timeout_ns);
733}
734
735int
736vc4_wait_bo_ioctl(struct drm_device *dev, void *data,
737 struct drm_file *file_priv)
738{
739 int ret;
740 struct drm_vc4_wait_bo *args = data;
741 struct drm_gem_object *gem_obj;
742 struct vc4_bo *bo;
743
Eric Anholte0015232016-01-25 13:05:00 -0800744 if (args->pad != 0)
745 return -EINVAL;
746
Eric Anholtd5b1a782015-11-30 12:13:37 -0800747 gem_obj = drm_gem_object_lookup(dev, file_priv, args->handle);
748 if (!gem_obj) {
749 DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
750 return -EINVAL;
751 }
752 bo = to_vc4_bo(gem_obj);
753
754 ret = vc4_wait_for_seqno_ioctl_helper(dev, bo->seqno,
755 &args->timeout_ns);
756
757 drm_gem_object_unreference_unlocked(gem_obj);
758 return ret;
759}
760
761/**
762 * Submits a command list to the VC4.
763 *
764 * This is what is called batchbuffer emitting on other hardware.
765 */
766int
767vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
768 struct drm_file *file_priv)
769{
770 struct vc4_dev *vc4 = to_vc4_dev(dev);
771 struct drm_vc4_submit_cl *args = data;
772 struct vc4_exec_info *exec;
773 int ret;
774
775 if ((args->flags & ~VC4_SUBMIT_CL_USE_CLEAR_COLOR) != 0) {
776 DRM_ERROR("Unknown flags: 0x%02x\n", args->flags);
777 return -EINVAL;
778 }
779
780 exec = kcalloc(1, sizeof(*exec), GFP_KERNEL);
781 if (!exec) {
782 DRM_ERROR("malloc failure on exec struct\n");
783 return -ENOMEM;
784 }
785
786 exec->args = args;
787 INIT_LIST_HEAD(&exec->unref_list);
788
789 ret = vc4_cl_lookup_bos(dev, file_priv, exec);
790 if (ret)
791 goto fail;
792
793 if (exec->args->bin_cl_size != 0) {
794 ret = vc4_get_bcl(dev, exec);
795 if (ret)
796 goto fail;
797 } else {
798 exec->ct0ca = 0;
799 exec->ct0ea = 0;
800 }
801
802 ret = vc4_get_rcl(dev, exec);
803 if (ret)
804 goto fail;
805
806 /* Clear this out of the struct we'll be putting in the queue,
807 * since it's part of our stack.
808 */
809 exec->args = NULL;
810
811 vc4_queue_submit(dev, exec);
812
813 /* Return the seqno for our job. */
814 args->seqno = vc4->emit_seqno;
815
816 return 0;
817
818fail:
819 vc4_complete_exec(vc4->dev, exec);
820
821 return ret;
822}
823
824void
825vc4_gem_init(struct drm_device *dev)
826{
827 struct vc4_dev *vc4 = to_vc4_dev(dev);
828
829 INIT_LIST_HEAD(&vc4->job_list);
830 INIT_LIST_HEAD(&vc4->job_done_list);
Eric Anholtb501bac2015-11-30 12:34:01 -0800831 INIT_LIST_HEAD(&vc4->seqno_cb_list);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800832 spin_lock_init(&vc4->job_lock);
833
834 INIT_WORK(&vc4->hangcheck.reset_work, vc4_reset_work);
835 setup_timer(&vc4->hangcheck.timer,
836 vc4_hangcheck_elapsed,
837 (unsigned long)dev);
838
839 INIT_WORK(&vc4->job_done_work, vc4_job_done_work);
840}
841
842void
843vc4_gem_destroy(struct drm_device *dev)
844{
845 struct vc4_dev *vc4 = to_vc4_dev(dev);
846
847 /* Waiting for exec to finish would need to be done before
848 * unregistering V3D.
849 */
850 WARN_ON(vc4->emit_seqno != vc4->finished_seqno);
851
852 /* V3D should already have disabled its interrupt and cleared
853 * the overflow allocation registers. Now free the object.
854 */
855 if (vc4->overflow_mem) {
856 drm_gem_object_unreference_unlocked(&vc4->overflow_mem->base.base);
857 vc4->overflow_mem = NULL;
858 }
859
860 vc4_bo_cache_destroy(dev);
Eric Anholt21461362015-10-30 10:09:02 -0700861
862 if (vc4->hang_state)
863 vc4_free_hang_state(dev, vc4->hang_state);
Eric Anholtd5b1a782015-11-30 12:13:37 -0800864}