History

drm/v3d: clean caches at the end of render jobs on request from user space

Extends the user space ioctl for CL submissions so it can include a request to flush the cache once the CL execution has completed. Fixes memory write violation messages reported by the kernel in workloads involving shader memory writes (SSBOs, shader images, scratch, etc) which sometimes also lead to GPU resets during Piglit and CTS workloads. v2: if v3d_job_init() fails we need to kfree() the job instead of v3d_job_put() it (Eric Anholt). v3 (Eric Anholt): - Drop _FLAG suffix from the new flag name. - Add a new param so userspace can tell whether cache flushing is implemented in the kernel.

Iago Toral Quiroga committed 7 years ago

Commit 455d56c1 parent 978f6b03 files · +54 −11Browse files

Unified · Split

3 files
  1. drivers/gpu/drm/v3d/v3d_drv.c +3 −0
  2. drivers/gpu/drm/v3d/v3d_gem.c +46 −8
  3. include/uapi/drm/v3d_drm.h +5 −3
drivers/gpu/drm/v3d/v3d_drv.c+3−0
@@ -126,6 +126,9 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data, · 125 unmodified lines
126 case DRM_V3D_PARAM_SUPPORTS_CSD:126 case DRM_V3D_PARAM_SUPPORTS_CSD:
127 args->value = v3d_has_csd(v3d);127 args->value = v3d_has_csd(v3d);
128 return 0;128 return 0;
129 case DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH:
130 args->value = 1;
131 return 0;
129 default:132 default:
130 DRM_DEBUG("Unknown parameter %d\n", args->param);133 DRM_DEBUG("Unknown parameter %d\n", args->param);
131 return -EINVAL;134 return -EINVAL;
drivers/gpu/drm/v3d/v3d_gem.c+46−8
@@ -530,13 +530,16 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, · 529 unmodified lines
530 struct drm_v3d_submit_cl *args = data;530 struct drm_v3d_submit_cl *args = data;
531 struct v3d_bin_job *bin = NULL;531 struct v3d_bin_job *bin = NULL;
532 struct v3d_render_job *render;532 struct v3d_render_job *render;
533 struct v3d_job *clean_job = NULL;
534 struct v3d_job *last_job;
533 struct ww_acquire_ctx acquire_ctx;535 struct ww_acquire_ctx acquire_ctx;
534 int ret = 0;536 int ret = 0;
535 537
536 trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);538 trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
537 539
538 if (args->pad != 0) {540 if (args->flags != 0 &&
539 DRM_INFO("pad must be zero: %d\n", args->pad);541 args->flags != DRM_V3D_SUBMIT_CL_FLUSH_CACHE) {
542 DRM_INFO("invalid flags: %d\n", args->flags);
540 return -EINVAL;543 return -EINVAL;
541 }544 }
542 545
@@ -576,12 +579,31 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, · 33 unmodified lines
576 bin->render = render;579 bin->render = render;
577 }580 }
578 581
579 ret = v3d_lookup_bos(dev, file_priv, &render->base,582 if (args->flags & DRM_V3D_SUBMIT_CL_FLUSH_CACHE) {
583 clean_job = kcalloc(1, sizeof(*clean_job), GFP_KERNEL);
584 if (!clean_job) {
585 ret = -ENOMEM;
586 goto fail;
587 }
588
589 ret = v3d_job_init(v3d, file_priv, clean_job, v3d_job_free, 0);
590 if (ret) {
591 kfree(clean_job);
592 clean_job = NULL;
593 goto fail;
594 }
595
596 last_job = clean_job;
597 } else {
598 last_job = &render->base;
599 }
600
601 ret = v3d_lookup_bos(dev, file_priv, last_job,
580 args->bo_handles, args->bo_handle_count);602 args->bo_handles, args->bo_handle_count);
581 if (ret)603 if (ret)
582 goto fail;604 goto fail;
583 605
584 ret = v3d_lock_bo_reservations(&render->base, &acquire_ctx);606 ret = v3d_lock_bo_reservations(last_job, &acquire_ctx);
585 if (ret)607 if (ret)
586 goto fail;608 goto fail;
587 609
@@ -600,28 +622,44 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, · 12 unmodified lines
600 ret = v3d_push_job(v3d_priv, &render->base, V3D_RENDER);622 ret = v3d_push_job(v3d_priv, &render->base, V3D_RENDER);
601 if (ret)623 if (ret)
602 goto fail_unreserve;624 goto fail_unreserve;
625
626 if (clean_job) {
627 struct dma_fence *render_fence =
628 dma_fence_get(render->base.done_fence);
629 ret = drm_gem_fence_array_add(&clean_job->deps, render_fence);
630 if (ret)
631 goto fail_unreserve;
632 ret = v3d_push_job(v3d_priv, clean_job, V3D_CACHE_CLEAN);
633 if (ret)
634 goto fail_unreserve;
635 }
636
603 mutex_unlock(&v3d->sched_lock);637 mutex_unlock(&v3d->sched_lock);
604 638
605 v3d_attach_fences_and_unlock_reservation(file_priv,639 v3d_attach_fences_and_unlock_reservation(file_priv,
606 &render->base,640 last_job,
607 &acquire_ctx,641 &acquire_ctx,
608 args->out_sync,642 args->out_sync,
609 render->base.done_fence);643 last_job->done_fence);
610 644
611 if (bin)645 if (bin)
612 v3d_job_put(&bin->base);646 v3d_job_put(&bin->base);
613 v3d_job_put(&render->base);647 v3d_job_put(&render->base);
648 if (clean_job)
649 v3d_job_put(clean_job);
614 650
615 return 0;651 return 0;
616 652
617fail_unreserve:653fail_unreserve:
618 mutex_unlock(&v3d->sched_lock);654 mutex_unlock(&v3d->sched_lock);
619 drm_gem_unlock_reservations(render->base.bo,655 drm_gem_unlock_reservations(last_job->bo,
620 render->base.bo_count, &acquire_ctx);656 last_job->bo_count, &acquire_ctx);
621fail:657fail:
622 if (bin)658 if (bin)
623 v3d_job_put(&bin->base);659 v3d_job_put(&bin->base);
624 v3d_job_put(&render->base);660 v3d_job_put(&render->base);
661 if (clean_job)
662 v3d_job_put(clean_job);
625 663
626 return ret;664 return ret;
627}665}
include/uapi/drm/v3d_drm.h+5−3
@@ -48,6 +48,8 @@ extern "C" { · 47 unmodified lines
48#define DRM_IOCTL_V3D_SUBMIT_TFU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)48#define DRM_IOCTL_V3D_SUBMIT_TFU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
49#define DRM_IOCTL_V3D_SUBMIT_CSD DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CSD, struct drm_v3d_submit_csd)49#define DRM_IOCTL_V3D_SUBMIT_CSD DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CSD, struct drm_v3d_submit_csd)
50 50
51#define DRM_V3D_SUBMIT_CL_FLUSH_CACHE 0x01
52
51/**53/**
52 * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D54 * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
53 * engine.55 * engine.
@@ -61,7 +63,7 @@ extern "C" { · 7 unmodified lines
61 * flushed by the time the render done IRQ happens, which is the63 * flushed by the time the render done IRQ happens, which is the
62 * trigger for out_sync. Any dirtying of cachelines by the job (only64 * trigger for out_sync. Any dirtying of cachelines by the job (only
63 * possible using TMU writes) must be flushed by the caller using the65 * possible using TMU writes) must be flushed by the caller using the
64 * CL's cache flush commands.66 * DRM_V3D_SUBMIT_CL_FLUSH_CACHE_FLAG flag.
65 */67 */
66struct drm_v3d_submit_cl {68struct drm_v3d_submit_cl {
67 /* Pointer to the binner command list.69 /* Pointer to the binner command list.
@@ -124,8 +126,7 @@ struct drm_v3d_submit_cl { · 56 unmodified lines
124 /* Number of BO handles passed in (size is that times 4). */126 /* Number of BO handles passed in (size is that times 4). */
125 __u32 bo_handle_count;127 __u32 bo_handle_count;
126 128
127 /* Pad, must be zero-filled. */129 __u32 flags;
128 __u32 pad;
129};130};
130 131
131/**132/**
@@ -193,6 +194,7 @@ enum drm_v3d_param { · 61 unmodified lines
193 DRM_V3D_PARAM_V3D_CORE0_IDENT2,194 DRM_V3D_PARAM_V3D_CORE0_IDENT2,
194 DRM_V3D_PARAM_SUPPORTS_TFU,195 DRM_V3D_PARAM_SUPPORTS_TFU,
195 DRM_V3D_PARAM_SUPPORTS_CSD,196 DRM_V3D_PARAM_SUPPORTS_CSD,
197 DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH,
196};198};
197 199
198struct drm_v3d_get_param {200struct drm_v3d_get_param {