diff options
Diffstat (limited to 'drivers/gpu/drm/vc4/vc4_gem.c')
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_gem.c | 48 |
1 files changed, 43 insertions, 5 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index c94cce96544c..2107b0daf8ef 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c | |||
@@ -467,14 +467,30 @@ again: | |||
467 | 467 | ||
468 | vc4_flush_caches(dev); | 468 | vc4_flush_caches(dev); |
469 | 469 | ||
470 | /* Only start the perfmon if it was not already started by a previous | ||
471 | * job. | ||
472 | */ | ||
473 | if (exec->perfmon && vc4->active_perfmon != exec->perfmon) | ||
474 | vc4_perfmon_start(vc4, exec->perfmon); | ||
475 | |||
470 | /* Either put the job in the binner if it uses the binner, or | 476 | /* Either put the job in the binner if it uses the binner, or |
471 | * immediately move it to the to-be-rendered queue. | 477 | * immediately move it to the to-be-rendered queue. |
472 | */ | 478 | */ |
473 | if (exec->ct0ca != exec->ct0ea) { | 479 | if (exec->ct0ca != exec->ct0ea) { |
474 | submit_cl(dev, 0, exec->ct0ca, exec->ct0ea); | 480 | submit_cl(dev, 0, exec->ct0ca, exec->ct0ea); |
475 | } else { | 481 | } else { |
482 | struct vc4_exec_info *next; | ||
483 | |||
476 | vc4_move_job_to_render(dev, exec); | 484 | vc4_move_job_to_render(dev, exec); |
477 | goto again; | 485 | next = vc4_first_bin_job(vc4); |
486 | |||
487 | /* We can't start the next bin job if the previous job had a | ||
488 | * different perfmon instance attached to it. The same goes | ||
489 | * if one of them had a perfmon attached to it and the other | ||
490 | * one doesn't. | ||
491 | */ | ||
492 | if (next && next->perfmon == exec->perfmon) | ||
493 | goto again; | ||
478 | } | 494 | } |
479 | } | 495 | } |
480 | 496 | ||
@@ -642,6 +658,7 @@ vc4_queue_submit(struct drm_device *dev, struct vc4_exec_info *exec, | |||
642 | struct ww_acquire_ctx *acquire_ctx) | 658 | struct ww_acquire_ctx *acquire_ctx) |
643 | { | 659 | { |
644 | struct vc4_dev *vc4 = to_vc4_dev(dev); | 660 | struct vc4_dev *vc4 = to_vc4_dev(dev); |
661 | struct vc4_exec_info *renderjob; | ||
645 | uint64_t seqno; | 662 | uint64_t seqno; |
646 | unsigned long irqflags; | 663 | unsigned long irqflags; |
647 | struct vc4_fence *fence; | 664 | struct vc4_fence *fence; |
@@ -667,11 +684,14 @@ vc4_queue_submit(struct drm_device *dev, struct vc4_exec_info *exec, | |||
667 | 684 | ||
668 | list_add_tail(&exec->head, &vc4->bin_job_list); | 685 | list_add_tail(&exec->head, &vc4->bin_job_list); |
669 | 686 | ||
670 | /* If no job was executing, kick ours off. Otherwise, it'll | 687 | /* If no bin job was executing and if the render job (if any) has the |
671 | * get started when the previous job's flush done interrupt | 688 | * same perfmon as our job attached to it (or if both jobs don't have |
672 | * occurs. | 689 | * perfmon activated), then kick ours off. Otherwise, it'll get |
690 | * started when the previous job's flush/render done interrupt occurs. | ||
673 | */ | 691 | */ |
674 | if (vc4_first_bin_job(vc4) == exec) { | 692 | renderjob = vc4_first_render_job(vc4); |
693 | if (vc4_first_bin_job(vc4) == exec && | ||
694 | (!renderjob || renderjob->perfmon == exec->perfmon)) { | ||
675 | vc4_submit_next_bin_job(dev); | 695 | vc4_submit_next_bin_job(dev); |
676 | vc4_queue_hangcheck(dev); | 696 | vc4_queue_hangcheck(dev); |
677 | } | 697 | } |
@@ -936,6 +956,9 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec) | |||
936 | vc4->bin_alloc_used &= ~exec->bin_slots; | 956 | vc4->bin_alloc_used &= ~exec->bin_slots; |
937 | spin_unlock_irqrestore(&vc4->job_lock, irqflags); | 957 | spin_unlock_irqrestore(&vc4->job_lock, irqflags); |
938 | 958 | ||
959 | /* Release the reference we had on the perf monitor. */ | ||
960 | vc4_perfmon_put(exec->perfmon); | ||
961 | |||
939 | mutex_lock(&vc4->power_lock); | 962 | mutex_lock(&vc4->power_lock); |
940 | if (--vc4->power_refcount == 0) { | 963 | if (--vc4->power_refcount == 0) { |
941 | pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); | 964 | pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); |
@@ -1088,6 +1111,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, | |||
1088 | struct drm_file *file_priv) | 1111 | struct drm_file *file_priv) |
1089 | { | 1112 | { |
1090 | struct vc4_dev *vc4 = to_vc4_dev(dev); | 1113 | struct vc4_dev *vc4 = to_vc4_dev(dev); |
1114 | struct vc4_file *vc4file = file_priv->driver_priv; | ||
1091 | struct drm_vc4_submit_cl *args = data; | 1115 | struct drm_vc4_submit_cl *args = data; |
1092 | struct vc4_exec_info *exec; | 1116 | struct vc4_exec_info *exec; |
1093 | struct ww_acquire_ctx acquire_ctx; | 1117 | struct ww_acquire_ctx acquire_ctx; |
@@ -1101,6 +1125,11 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, | |||
1101 | return -EINVAL; | 1125 | return -EINVAL; |
1102 | } | 1126 | } |
1103 | 1127 | ||
1128 | if (args->pad2 != 0) { | ||
1129 | DRM_DEBUG("->pad2 must be set to zero\n"); | ||
1130 | return -EINVAL; | ||
1131 | } | ||
1132 | |||
1104 | exec = kcalloc(1, sizeof(*exec), GFP_KERNEL); | 1133 | exec = kcalloc(1, sizeof(*exec), GFP_KERNEL); |
1105 | if (!exec) { | 1134 | if (!exec) { |
1106 | DRM_ERROR("malloc failure on exec struct\n"); | 1135 | DRM_ERROR("malloc failure on exec struct\n"); |
@@ -1126,6 +1155,15 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, | |||
1126 | if (ret) | 1155 | if (ret) |
1127 | goto fail; | 1156 | goto fail; |
1128 | 1157 | ||
1158 | if (args->perfmonid) { | ||
1159 | exec->perfmon = vc4_perfmon_find(vc4file, | ||
1160 | args->perfmonid); | ||
1161 | if (!exec->perfmon) { | ||
1162 | ret = -ENOENT; | ||
1163 | goto fail; | ||
1164 | } | ||
1165 | } | ||
1166 | |||
1129 | if (exec->args->bin_cl_size != 0) { | 1167 | if (exec->args->bin_cl_size != 0) { |
1130 | ret = vc4_get_bcl(dev, exec); | 1168 | ret = vc4_get_bcl(dev, exec); |
1131 | if (ret) | 1169 | if (ret) |