Lines Matching +full:required +full:- +full:for +full:- +full:hardware +full:- +full:jobs
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
30 #include <linux/dma-fence-array.h>
45 mod_timer(&vc4->hangcheck.timer, in vc4_queue_hangcheck()
61 for (i = 0; i < state->user_state.bo_count; i++) in vc4_free_hang_state()
62 drm_gem_object_put(state->bo[i]); in vc4_free_hang_state()
80 if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) in vc4_get_hang_state_ioctl()
81 return -ENODEV; in vc4_get_hang_state_ioctl()
83 if (!vc4->v3d) { in vc4_get_hang_state_ioctl()
85 return -ENODEV; in vc4_get_hang_state_ioctl()
88 spin_lock_irqsave(&vc4->job_lock, irqflags); in vc4_get_hang_state_ioctl()
89 kernel_state = vc4->hang_state; in vc4_get_hang_state_ioctl()
91 spin_unlock_irqrestore(&vc4->job_lock, irqflags); in vc4_get_hang_state_ioctl()
92 return -ENOENT; in vc4_get_hang_state_ioctl()
94 state = &kernel_state->user_state; in vc4_get_hang_state_ioctl()
97 * required array size. in vc4_get_hang_state_ioctl()
99 if (get_state->bo_count < state->bo_count) { in vc4_get_hang_state_ioctl()
100 get_state->bo_count = state->bo_count; in vc4_get_hang_state_ioctl()
101 spin_unlock_irqrestore(&vc4->job_lock, irqflags); in vc4_get_hang_state_ioctl()
105 vc4->hang_state = NULL; in vc4_get_hang_state_ioctl()
106 spin_unlock_irqrestore(&vc4->job_lock, irqflags); in vc4_get_hang_state_ioctl()
109 state->bo = get_state->bo; in vc4_get_hang_state_ioctl()
112 bo_state = kcalloc(state->bo_count, sizeof(*bo_state), GFP_KERNEL); in vc4_get_hang_state_ioctl()
114 ret = -ENOMEM; in vc4_get_hang_state_ioctl()
118 for (i = 0; i < state->bo_count; i++) { in vc4_get_hang_state_ioctl()
119 struct vc4_bo *vc4_bo = to_vc4_bo(kernel_state->bo[i]); in vc4_get_hang_state_ioctl()
122 ret = drm_gem_handle_create(file_priv, kernel_state->bo[i], in vc4_get_hang_state_ioctl()
126 state->bo_count = i; in vc4_get_hang_state_ioctl()
130 bo_state[i].paddr = vc4_bo->base.dma_addr; in vc4_get_hang_state_ioctl()
131 bo_state[i].size = vc4_bo->base.base.size; in vc4_get_hang_state_ioctl()
134 if (copy_to_user(u64_to_user_ptr(get_state->bo), in vc4_get_hang_state_ioctl()
136 state->bo_count * sizeof(*bo_state))) in vc4_get_hang_state_ioctl()
137 ret = -EFAULT; in vc4_get_hang_state_ioctl()
141 for (i = 0; i < state->bo_count; i++) in vc4_get_hang_state_ioctl()
167 state = &kernel_state->user_state; in vc4_save_hang_state()
169 spin_lock_irqsave(&vc4->job_lock, irqflags); in vc4_save_hang_state()
173 spin_unlock_irqrestore(&vc4->job_lock, irqflags); in vc4_save_hang_state()
178 state->bo_count = 0; in vc4_save_hang_state()
179 for (i = 0; i < 2; i++) { in vc4_save_hang_state()
184 list_for_each_entry(bo, &exec[i]->unref_list, unref_head) in vc4_save_hang_state()
186 state->bo_count += exec[i]->bo_count + unref_list_count; in vc4_save_hang_state()
189 kernel_state->bo = kcalloc(state->bo_count, in vc4_save_hang_state()
190 sizeof(*kernel_state->bo), GFP_ATOMIC); in vc4_save_hang_state()
192 if (!kernel_state->bo) { in vc4_save_hang_state()
193 spin_unlock_irqrestore(&vc4->job_lock, irqflags); in vc4_save_hang_state()
198 for (i = 0; i < 2; i++) { in vc4_save_hang_state()
202 for (j = 0; j < exec[i]->bo_count; j++) { in vc4_save_hang_state()
203 bo = to_vc4_bo(exec[i]->bo[j]); in vc4_save_hang_state()
209 WARN_ON(!refcount_read(&bo->usecnt)); in vc4_save_hang_state()
210 refcount_inc(&bo->usecnt); in vc4_save_hang_state()
211 drm_gem_object_get(exec[i]->bo[j]); in vc4_save_hang_state()
212 kernel_state->bo[k++] = exec[i]->bo[j]; in vc4_save_hang_state()
215 list_for_each_entry(bo, &exec[i]->unref_list, unref_head) { in vc4_save_hang_state()
216 /* No need to retain BOs coming from the ->unref_list in vc4_save_hang_state()
219 drm_gem_object_get(&bo->base.base); in vc4_save_hang_state()
220 kernel_state->bo[k++] = &bo->base.base; in vc4_save_hang_state()
224 WARN_ON_ONCE(k != state->bo_count); in vc4_save_hang_state()
227 state->start_bin = exec[0]->ct0ca; in vc4_save_hang_state()
229 state->start_render = exec[1]->ct1ca; in vc4_save_hang_state()
231 spin_unlock_irqrestore(&vc4->job_lock, irqflags); in vc4_save_hang_state()
233 state->ct0ca = V3D_READ(V3D_CTNCA(0)); in vc4_save_hang_state()
234 state->ct0ea = V3D_READ(V3D_CTNEA(0)); in vc4_save_hang_state()
236 state->ct1ca = V3D_READ(V3D_CTNCA(1)); in vc4_save_hang_state()
237 state->ct1ea = V3D_READ(V3D_CTNEA(1)); in vc4_save_hang_state()
239 state->ct0cs = V3D_READ(V3D_CTNCS(0)); in vc4_save_hang_state()
240 state->ct1cs = V3D_READ(V3D_CTNCS(1)); in vc4_save_hang_state()
242 state->ct0ra0 = V3D_READ(V3D_CT00RA0); in vc4_save_hang_state()
243 state->ct1ra0 = V3D_READ(V3D_CT01RA0); in vc4_save_hang_state()
245 state->bpca = V3D_READ(V3D_BPCA); in vc4_save_hang_state()
246 state->bpcs = V3D_READ(V3D_BPCS); in vc4_save_hang_state()
247 state->bpoa = V3D_READ(V3D_BPOA); in vc4_save_hang_state()
248 state->bpos = V3D_READ(V3D_BPOS); in vc4_save_hang_state()
250 state->vpmbase = V3D_READ(V3D_VPMBASE); in vc4_save_hang_state()
252 state->dbge = V3D_READ(V3D_DBGE); in vc4_save_hang_state()
253 state->fdbgo = V3D_READ(V3D_FDBGO); in vc4_save_hang_state()
254 state->fdbgb = V3D_READ(V3D_FDBGB); in vc4_save_hang_state()
255 state->fdbgr = V3D_READ(V3D_FDBGR); in vc4_save_hang_state()
256 state->fdbgs = V3D_READ(V3D_FDBGS); in vc4_save_hang_state()
257 state->errstat = V3D_READ(V3D_ERRSTAT); in vc4_save_hang_state()
262 * Note that BO consistency at dump time cannot be guaranteed. For in vc4_save_hang_state()
263 * example, if the owner of these BOs decides to re-use them or mark in vc4_save_hang_state()
266 for (i = 0; i < kernel_state->user_state.bo_count; i++) { in vc4_save_hang_state()
267 struct vc4_bo *bo = to_vc4_bo(kernel_state->bo[i]); in vc4_save_hang_state()
269 if (bo->madv == __VC4_MADV_NOTSUPP) in vc4_save_hang_state()
272 mutex_lock(&bo->madv_lock); in vc4_save_hang_state()
273 if (!WARN_ON(bo->madv == __VC4_MADV_PURGED)) in vc4_save_hang_state()
274 bo->madv = VC4_MADV_WILLNEED; in vc4_save_hang_state()
275 refcount_dec(&bo->usecnt); in vc4_save_hang_state()
276 mutex_unlock(&bo->madv_lock); in vc4_save_hang_state()
279 spin_lock_irqsave(&vc4->job_lock, irqflags); in vc4_save_hang_state()
280 if (vc4->hang_state) { in vc4_save_hang_state()
281 spin_unlock_irqrestore(&vc4->job_lock, irqflags); in vc4_save_hang_state()
284 vc4->hang_state = kernel_state; in vc4_save_hang_state()
285 spin_unlock_irqrestore(&vc4->job_lock, irqflags); in vc4_save_hang_state()
296 mutex_lock(&vc4->power_lock); in vc4_reset()
297 if (vc4->power_refcount) { in vc4_reset()
301 pm_runtime_put_sync_suspend(&vc4->v3d->pdev->dev); in vc4_reset()
302 pm_runtime_get_sync(&vc4->v3d->pdev->dev); in vc4_reset()
304 mutex_unlock(&vc4->power_lock); in vc4_reset()
308 /* Rearm the hangcheck -- another job might have been waiting in vc4_reset()
309 * for our hung one to get kicked off, and vc4_irq_reset() in vc4_reset()
321 vc4_save_hang_state(&vc4->base); in vc4_reset_work()
323 vc4_reset(&vc4->base); in vc4_reset_work()
330 struct drm_device *dev = &vc4->base; in vc4_hangcheck_elapsed()
335 spin_lock_irqsave(&vc4->job_lock, irqflags); in vc4_hangcheck_elapsed()
340 /* If idle, we can stop watching for hangs. */ in vc4_hangcheck_elapsed()
342 spin_unlock_irqrestore(&vc4->job_lock, irqflags); in vc4_hangcheck_elapsed()
352 if ((bin_exec && ct0ca != bin_exec->last_ct0ca) || in vc4_hangcheck_elapsed()
353 (render_exec && ct1ca != render_exec->last_ct1ca)) { in vc4_hangcheck_elapsed()
355 bin_exec->last_ct0ca = ct0ca; in vc4_hangcheck_elapsed()
357 render_exec->last_ct1ca = ct1ca; in vc4_hangcheck_elapsed()
358 spin_unlock_irqrestore(&vc4->job_lock, irqflags); in vc4_hangcheck_elapsed()
363 spin_unlock_irqrestore(&vc4->job_lock, irqflags); in vc4_hangcheck_elapsed()
369 schedule_work(&vc4->hangcheck.reset_work); in vc4_hangcheck_elapsed()
393 if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) in vc4_wait_for_seqno()
394 return -ENODEV; in vc4_wait_for_seqno()
396 if (vc4->finished_seqno >= seqno) in vc4_wait_for_seqno()
400 return -ETIME; in vc4_wait_for_seqno()
405 for (;;) { in vc4_wait_for_seqno()
406 prepare_to_wait(&vc4->job_wait_queue, &wait, in vc4_wait_for_seqno()
411 ret = -ERESTARTSYS; in vc4_wait_for_seqno()
415 if (vc4->finished_seqno >= seqno) in vc4_wait_for_seqno()
420 ret = -ETIME; in vc4_wait_for_seqno()
423 schedule_timeout(timeout_expire - jiffies); in vc4_wait_for_seqno()
429 finish_wait(&vc4->job_wait_queue, &wait); in vc4_wait_for_seqno()
442 * non-allocating in the L3. in vc4_flush_caches()
467 /* Sets the registers for the next job to be actually be executed in
468 * the hardware.
478 if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) in vc4_submit_next_bin_job()
491 if (exec->perfmon && vc4->active_perfmon != exec->perfmon) in vc4_submit_next_bin_job()
492 vc4_perfmon_start(vc4, exec->perfmon); in vc4_submit_next_bin_job()
495 * immediately move it to the to-be-rendered queue. in vc4_submit_next_bin_job()
497 if (exec->ct0ca != exec->ct0ea) { in vc4_submit_next_bin_job()
498 trace_vc4_submit_cl(dev, false, exec->seqno, exec->ct0ca, in vc4_submit_next_bin_job()
499 exec->ct0ea); in vc4_submit_next_bin_job()
500 submit_cl(dev, 0, exec->ct0ca, exec->ct0ea); in vc4_submit_next_bin_job()
512 if (next && next->perfmon == exec->perfmon) in vc4_submit_next_bin_job()
526 if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) in vc4_submit_next_render_job()
537 trace_vc4_submit_cl(dev, true, exec->seqno, exec->ct1ca, exec->ct1ea); in vc4_submit_next_render_job()
538 submit_cl(dev, 1, exec->ct1ca, exec->ct1ea); in vc4_submit_next_render_job()
545 bool was_empty = list_empty(&vc4->render_job_list); in vc4_move_job_to_render()
547 if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) in vc4_move_job_to_render()
550 list_move_tail(&exec->head, &vc4->render_job_list); in vc4_move_job_to_render()
561 for (i = 0; i < exec->bo_count; i++) { in vc4_attach_fences()
562 bo = to_vc4_bo(exec->bo[i]); in vc4_attach_fences()
563 dma_resv_add_fence(bo->base.base.resv, exec->fence, in vc4_attach_fences()
567 for (i = 0; i < exec->rcl_write_bo_count; i++) { in vc4_attach_fences()
568 bo = to_vc4_bo(&exec->rcl_write_bo[i]->base); in vc4_attach_fences()
569 dma_resv_add_fence(bo->base.base.resv, exec->fence, in vc4_attach_fences()
578 * (all of which are on exec->unref_list). They're entirely private
579 * to vc4, so we don't attach dma-buf fences to them.
587 /* Reserve space for our shared (read-only) fence references, in vc4_lock_bo_reservations()
588 * before we commit the CL to the hardware. in vc4_lock_bo_reservations()
590 drm_exec_init(exec_ctx, DRM_EXEC_INTERRUPTIBLE_WAIT, exec->bo_count); in vc4_lock_bo_reservations()
592 ret = drm_exec_prepare_array(exec_ctx, exec->bo, in vc4_lock_bo_reservations()
593 exec->bo_count, 1); in vc4_lock_bo_reservations()
604 /* Queues a struct vc4_exec_info for execution. If no job is
607 * Unlike most GPUs, our hardware only handles one command list at a
608 * time. To queue multiple jobs at once, we'd need to edit the
610 * then bump the end address. That's a change for a later date,
626 return -ENOMEM; in vc4_queue_submit()
627 fence->dev = dev; in vc4_queue_submit()
629 spin_lock_irqsave(&vc4->job_lock, irqflags); in vc4_queue_submit()
631 seqno = ++vc4->emit_seqno; in vc4_queue_submit()
632 exec->seqno = seqno; in vc4_queue_submit()
634 dma_fence_init(&fence->base, &vc4_fence_ops, &vc4->job_lock, in vc4_queue_submit()
635 vc4->dma_fence_context, exec->seqno); in vc4_queue_submit()
636 fence->seqno = exec->seqno; in vc4_queue_submit()
637 exec->fence = &fence->base; in vc4_queue_submit()
640 drm_syncobj_replace_fence(out_sync, exec->fence); in vc4_queue_submit()
646 list_add_tail(&exec->head, &vc4->bin_job_list); in vc4_queue_submit()
649 * same perfmon as our job attached to it (or if both jobs don't have in vc4_queue_submit()
655 (!renderjob || renderjob->perfmon == exec->perfmon)) { in vc4_queue_submit()
660 spin_unlock_irqrestore(&vc4->job_lock, irqflags); in vc4_queue_submit()
666 * vc4_cl_lookup_bos() - Sets up exec->bo[] with the GEM objects
669 * @file_priv: DRM file for this fd
674 * BO list and reference counting for the lifetime of the job.
681 struct drm_vc4_submit_cl *args = exec->args; in vc4_cl_lookup_bos()
685 exec->bo_count = args->bo_handle_count; in vc4_cl_lookup_bos()
687 if (!exec->bo_count) { in vc4_cl_lookup_bos()
688 /* See comment on bo_index for why we have to check in vc4_cl_lookup_bos()
692 return -EINVAL; in vc4_cl_lookup_bos()
695 ret = drm_gem_objects_lookup(file_priv, u64_to_user_ptr(args->bo_handles), in vc4_cl_lookup_bos()
696 exec->bo_count, &exec->bo); in vc4_cl_lookup_bos()
701 for (i = 0; i < exec->bo_count; i++) { in vc4_cl_lookup_bos()
702 ret = vc4_bo_inc_usecnt(to_vc4_bo(exec->bo[i])); in vc4_cl_lookup_bos()
713 * had its ->usecnt incremented. in vc4_cl_lookup_bos()
715 * exec->bo to NULL so that vc4_complete_exec() skips the 'BO release' in vc4_cl_lookup_bos()
718 for (i-- ; i >= 0; i--) in vc4_cl_lookup_bos()
719 vc4_bo_dec_usecnt(to_vc4_bo(exec->bo[i])); in vc4_cl_lookup_bos()
723 for (i = 0; i < exec->bo_count && exec->bo[i]; i++) in vc4_cl_lookup_bos()
724 drm_gem_object_put(exec->bo[i]); in vc4_cl_lookup_bos()
726 kvfree(exec->bo); in vc4_cl_lookup_bos()
727 exec->bo = NULL; in vc4_cl_lookup_bos()
734 struct drm_vc4_submit_cl *args = exec->args; in vc4_get_bcl()
740 uint32_t shader_rec_offset = roundup(bin_offset + args->bin_cl_size, in vc4_get_bcl()
742 uint32_t uniforms_offset = shader_rec_offset + args->shader_rec_size; in vc4_get_bcl()
743 uint32_t exec_size = uniforms_offset + args->uniforms_size; in vc4_get_bcl()
745 args->shader_rec_count); in vc4_get_bcl()
748 if (shader_rec_offset < args->bin_cl_size || in vc4_get_bcl()
751 args->shader_rec_count >= (UINT_MAX / in vc4_get_bcl()
755 ret = -EINVAL; in vc4_get_bcl()
763 * read the contents back for validation, and I think the in vc4_get_bcl()
764 * bo->vaddr is uncached access. in vc4_get_bcl()
768 drm_err(dev, "Failed to allocate storage for copying " in vc4_get_bcl()
770 ret = -ENOMEM; in vc4_get_bcl()
774 exec->shader_rec_u = temp + shader_rec_offset; in vc4_get_bcl()
775 exec->uniforms_u = temp + uniforms_offset; in vc4_get_bcl()
776 exec->shader_state = temp + exec_size; in vc4_get_bcl()
777 exec->shader_state_size = args->shader_rec_count; in vc4_get_bcl()
780 u64_to_user_ptr(args->bin_cl), in vc4_get_bcl()
781 args->bin_cl_size)) { in vc4_get_bcl()
782 ret = -EFAULT; in vc4_get_bcl()
786 if (copy_from_user(exec->shader_rec_u, in vc4_get_bcl()
787 u64_to_user_ptr(args->shader_rec), in vc4_get_bcl()
788 args->shader_rec_size)) { in vc4_get_bcl()
789 ret = -EFAULT; in vc4_get_bcl()
793 if (copy_from_user(exec->uniforms_u, in vc4_get_bcl()
794 u64_to_user_ptr(args->uniforms), in vc4_get_bcl()
795 args->uniforms_size)) { in vc4_get_bcl()
796 ret = -EFAULT; in vc4_get_bcl()
802 drm_err(dev, "Couldn't allocate BO for binning\n"); in vc4_get_bcl()
806 exec->exec_bo = &bo->base; in vc4_get_bcl()
808 list_add_tail(&to_vc4_bo(&exec->exec_bo->base)->unref_head, in vc4_get_bcl()
809 &exec->unref_list); in vc4_get_bcl()
811 exec->ct0ca = exec->exec_bo->dma_addr + bin_offset; in vc4_get_bcl()
813 exec->bin_u = bin; in vc4_get_bcl()
815 exec->shader_rec_v = exec->exec_bo->vaddr + shader_rec_offset; in vc4_get_bcl()
816 exec->shader_rec_p = exec->exec_bo->dma_addr + shader_rec_offset; in vc4_get_bcl()
817 exec->shader_rec_size = args->shader_rec_size; in vc4_get_bcl()
819 exec->uniforms_v = exec->exec_bo->vaddr + uniforms_offset; in vc4_get_bcl()
820 exec->uniforms_p = exec->exec_bo->dma_addr + uniforms_offset; in vc4_get_bcl()
821 exec->uniforms_size = args->uniforms_size; in vc4_get_bcl()
824 exec->exec_bo->vaddr + bin_offset, in vc4_get_bcl()
834 if (exec->found_tile_binning_mode_config_packet) { in vc4_get_bcl()
835 ret = vc4_v3d_bin_bo_get(vc4, &exec->bin_bo_used); in vc4_get_bcl()
852 /* If we got force-completed because of GPU reset rather than in vc4_complete_exec()
855 if (exec->fence) { in vc4_complete_exec()
856 dma_fence_signal(exec->fence); in vc4_complete_exec()
857 dma_fence_put(exec->fence); in vc4_complete_exec()
860 if (exec->bo) { in vc4_complete_exec()
861 for (i = 0; i < exec->bo_count; i++) { in vc4_complete_exec()
862 struct vc4_bo *bo = to_vc4_bo(exec->bo[i]); in vc4_complete_exec()
865 drm_gem_object_put(exec->bo[i]); in vc4_complete_exec()
867 kvfree(exec->bo); in vc4_complete_exec()
870 while (!list_empty(&exec->unref_list)) { in vc4_complete_exec()
871 struct vc4_bo *bo = list_first_entry(&exec->unref_list, in vc4_complete_exec()
873 list_del(&bo->unref_head); in vc4_complete_exec()
874 drm_gem_object_put(&bo->base.base); in vc4_complete_exec()
878 spin_lock_irqsave(&vc4->job_lock, irqflags); in vc4_complete_exec()
879 vc4->bin_alloc_used &= ~exec->bin_slots; in vc4_complete_exec()
880 spin_unlock_irqrestore(&vc4->job_lock, irqflags); in vc4_complete_exec()
883 if (exec->bin_bo_used) in vc4_complete_exec()
887 vc4_perfmon_put(exec->perfmon); in vc4_complete_exec()
899 if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) in vc4_job_handle_completed()
902 spin_lock_irqsave(&vc4->job_lock, irqflags); in vc4_job_handle_completed()
903 while (!list_empty(&vc4->job_done_list)) { in vc4_job_handle_completed()
905 list_first_entry(&vc4->job_done_list, in vc4_job_handle_completed()
907 list_del(&exec->head); in vc4_job_handle_completed()
909 spin_unlock_irqrestore(&vc4->job_lock, irqflags); in vc4_job_handle_completed()
910 vc4_complete_exec(&vc4->base, exec); in vc4_job_handle_completed()
911 spin_lock_irqsave(&vc4->job_lock, irqflags); in vc4_job_handle_completed()
914 spin_unlock_irqrestore(&vc4->job_lock, irqflags); in vc4_job_handle_completed()
918 * jobs that had completed and unrefs their BOs and frees their exec
938 if ((ret == -EINTR || ret == -ERESTARTSYS) && *timeout_ns != ~0ull) { in vc4_wait_for_seqno_ioctl_helper()
939 uint64_t delta = jiffies_to_nsecs(jiffies - start); in vc4_wait_for_seqno_ioctl_helper()
942 *timeout_ns -= delta; in vc4_wait_for_seqno_ioctl_helper()
955 if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) in vc4_wait_seqno_ioctl()
956 return -ENODEV; in vc4_wait_seqno_ioctl()
958 return vc4_wait_for_seqno_ioctl_helper(dev, args->seqno, in vc4_wait_seqno_ioctl()
959 &args->timeout_ns); in vc4_wait_seqno_ioctl()
970 usecs_to_jiffies(div_u64(args->timeout_ns, 1000)); in vc4_wait_bo_ioctl()
974 if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) in vc4_wait_bo_ioctl()
975 return -ENODEV; in vc4_wait_bo_ioctl()
977 if (args->pad != 0) in vc4_wait_bo_ioctl()
978 return -EINVAL; in vc4_wait_bo_ioctl()
980 ret = drm_gem_dma_resv_wait(file_priv, args->handle, in vc4_wait_bo_ioctl()
987 if (delta_ns < args->timeout_ns) in vc4_wait_bo_ioctl()
988 args->timeout_ns -= delta_ns; in vc4_wait_bo_ioctl()
990 args->timeout_ns = 0; in vc4_wait_bo_ioctl()
996 * vc4_submit_cl_ioctl() - Submits a job (frame) to the VC4.
999 * @file_priv: DRM file for this fd
1001 * This is the main entrypoint for userspace to submit a 3D frame to
1012 struct vc4_file *vc4file = file_priv->driver_priv; in vc4_submit_cl_ioctl()
1020 trace_vc4_submit_cl_ioctl(dev, args->bin_cl_size, in vc4_submit_cl_ioctl()
1021 args->shader_rec_size, in vc4_submit_cl_ioctl()
1022 args->bo_handle_count); in vc4_submit_cl_ioctl()
1024 if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) in vc4_submit_cl_ioctl()
1025 return -ENODEV; in vc4_submit_cl_ioctl()
1027 if (!vc4->v3d) { in vc4_submit_cl_ioctl()
1029 return -ENODEV; in vc4_submit_cl_ioctl()
1032 if ((args->flags & ~(VC4_SUBMIT_CL_USE_CLEAR_COLOR | in vc4_submit_cl_ioctl()
1036 DRM_DEBUG("Unknown flags: 0x%02x\n", args->flags); in vc4_submit_cl_ioctl()
1037 return -EINVAL; in vc4_submit_cl_ioctl()
1040 if (args->pad2 != 0) { in vc4_submit_cl_ioctl()
1041 DRM_DEBUG("Invalid pad: 0x%08x\n", args->pad2); in vc4_submit_cl_ioctl()
1042 return -EINVAL; in vc4_submit_cl_ioctl()
1047 return -ENOMEM; in vc4_submit_cl_ioctl()
1049 exec->dev = vc4; in vc4_submit_cl_ioctl()
1057 exec->args = args; in vc4_submit_cl_ioctl()
1058 INIT_LIST_HEAD(&exec->unref_list); in vc4_submit_cl_ioctl()
1064 if (args->perfmonid) { in vc4_submit_cl_ioctl()
1065 exec->perfmon = vc4_perfmon_find(vc4file, in vc4_submit_cl_ioctl()
1066 args->perfmonid); in vc4_submit_cl_ioctl()
1067 if (!exec->perfmon) { in vc4_submit_cl_ioctl()
1068 ret = -ENOENT; in vc4_submit_cl_ioctl()
1073 if (args->in_sync) { in vc4_submit_cl_ioctl()
1074 ret = drm_syncobj_find_fence(file_priv, args->in_sync, in vc4_submit_cl_ioctl()
1080 * context we can skip the wait since jobs are executed in in vc4_submit_cl_ioctl()
1085 vc4->dma_fence_context)) { in vc4_submit_cl_ioctl()
1096 if (exec->args->bin_cl_size != 0) { in vc4_submit_cl_ioctl()
1101 exec->ct0ca = 0; in vc4_submit_cl_ioctl()
1102 exec->ct0ea = 0; in vc4_submit_cl_ioctl()
1113 if (args->out_sync) { in vc4_submit_cl_ioctl()
1114 out_sync = drm_syncobj_find(file_priv, args->out_sync); in vc4_submit_cl_ioctl()
1116 ret = -EINVAL; in vc4_submit_cl_ioctl()
1130 exec->args = NULL; in vc4_submit_cl_ioctl()
1143 /* Return the seqno for our job. */ in vc4_submit_cl_ioctl()
1144 args->seqno = vc4->emit_seqno; in vc4_submit_cl_ioctl()
1151 vc4_complete_exec(&vc4->base, exec); in vc4_submit_cl_ioctl()
1162 if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) in vc4_gem_init()
1163 return -ENODEV; in vc4_gem_init()
1165 vc4->dma_fence_context = dma_fence_context_alloc(1); in vc4_gem_init()
1167 INIT_LIST_HEAD(&vc4->bin_job_list); in vc4_gem_init()
1168 INIT_LIST_HEAD(&vc4->render_job_list); in vc4_gem_init()
1169 INIT_LIST_HEAD(&vc4->job_done_list); in vc4_gem_init()
1170 spin_lock_init(&vc4->job_lock); in vc4_gem_init()
1172 INIT_WORK(&vc4->hangcheck.reset_work, vc4_reset_work); in vc4_gem_init()
1173 timer_setup(&vc4->hangcheck.timer, vc4_hangcheck_elapsed, 0); in vc4_gem_init()
1175 INIT_WORK(&vc4->job_done_work, vc4_job_done_work); in vc4_gem_init()
1177 ret = drmm_mutex_init(dev, &vc4->power_lock); in vc4_gem_init()
1181 INIT_LIST_HEAD(&vc4->purgeable.list); in vc4_gem_init()
1183 ret = drmm_mutex_init(dev, &vc4->purgeable.lock); in vc4_gem_init()
1194 /* Waiting for exec to finish would need to be done before in vc4_gem_destroy()
1197 WARN_ON(vc4->emit_seqno != vc4->finished_seqno); in vc4_gem_destroy()
1202 if (vc4->bin_bo) { in vc4_gem_destroy()
1203 drm_gem_object_put(&vc4->bin_bo->base.base); in vc4_gem_destroy()
1204 vc4->bin_bo = NULL; in vc4_gem_destroy()
1207 if (vc4->hang_state) in vc4_gem_destroy()
1208 vc4_free_hang_state(dev, vc4->hang_state); in vc4_gem_destroy()
1220 if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) in vc4_gem_madvise_ioctl()
1221 return -ENODEV; in vc4_gem_madvise_ioctl()
1223 switch (args->madv) { in vc4_gem_madvise_ioctl()
1228 return -EINVAL; in vc4_gem_madvise_ioctl()
1231 if (args->pad != 0) in vc4_gem_madvise_ioctl()
1232 return -EINVAL; in vc4_gem_madvise_ioctl()
1234 gem_obj = drm_gem_object_lookup(file_priv, args->handle); in vc4_gem_madvise_ioctl()
1236 DRM_DEBUG("Failed to look up GEM BO %d\n", args->handle); in vc4_gem_madvise_ioctl()
1237 return -ENOENT; in vc4_gem_madvise_ioctl()
1243 if (bo->madv == __VC4_MADV_NOTSUPP) { in vc4_gem_madvise_ioctl()
1245 ret = -EINVAL; in vc4_gem_madvise_ioctl()
1252 if (gem_obj->import_attach) { in vc4_gem_madvise_ioctl()
1254 ret = -EINVAL; in vc4_gem_madvise_ioctl()
1258 mutex_lock(&bo->madv_lock); in vc4_gem_madvise_ioctl()
1260 if (args->madv == VC4_MADV_DONTNEED && bo->madv == VC4_MADV_WILLNEED && in vc4_gem_madvise_ioctl()
1261 !refcount_read(&bo->usecnt)) { in vc4_gem_madvise_ioctl()
1267 } else if (args->madv == VC4_MADV_WILLNEED && in vc4_gem_madvise_ioctl()
1268 bo->madv == VC4_MADV_DONTNEED && in vc4_gem_madvise_ioctl()
1269 !refcount_read(&bo->usecnt)) { in vc4_gem_madvise_ioctl()
1277 args->retained = bo->madv != __VC4_MADV_PURGED; in vc4_gem_madvise_ioctl()
1280 if (bo->madv != __VC4_MADV_PURGED) in vc4_gem_madvise_ioctl()
1281 bo->madv = args->madv; in vc4_gem_madvise_ioctl()
1283 mutex_unlock(&bo->madv_lock); in vc4_gem_madvise_ioctl()