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
126126 case DRM_V3D_PARAM_SUPPORTS_CSD:
127127 args->value = v3d_has_csd(v3d);
128128 return 0;
129+ case DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH:
130+ args->value = 1;
131+ return 0;
129132 default:
130133 DRM_DEBUG("Unknown parameter %d\n", args->param);
131134 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
530530 struct drm_v3d_submit_cl *args = data;
531531 struct v3d_bin_job *bin = NULL;
532532 struct v3d_render_job *render;
533+ struct v3d_job *clean_job = NULL;
534+ struct v3d_job *last_job;
533535 struct ww_acquire_ctx acquire_ctx;
534536 int ret = 0;
535537
536538 trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
537539
538− if (args->pad != 0) {
539− DRM_INFO("pad must be zero: %d\n", args->pad);
540+ if (args->flags != 0 &&
541+ args->flags != DRM_V3D_SUBMIT_CL_FLUSH_CACHE) {
542+ DRM_INFO("invalid flags: %d\n", args->flags);
540543 return -EINVAL;
541544 }
542545
@@ -576,12 +579,31 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, · 33 unmodified lines
576579 bin->render = render;
577580 }
578581
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,
580602 args->bo_handles, args->bo_handle_count);
581603 if (ret)
582604 goto fail;
583605
584− ret = v3d_lock_bo_reservations(&render->base, &acquire_ctx);
606+ ret = v3d_lock_bo_reservations(last_job, &acquire_ctx);
585607 if (ret)
586608 goto fail;
587609
@@ -600,28 +622,44 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, · 12 unmodified lines
600622 ret = v3d_push_job(v3d_priv, &render->base, V3D_RENDER);
601623 if (ret)
602624 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+
603637 mutex_unlock(&v3d->sched_lock);
604638
605639 v3d_attach_fences_and_unlock_reservation(file_priv,
606− &render->base,
640+ last_job,
607641 &acquire_ctx,
608642 args->out_sync,
609− render->base.done_fence);
643+ last_job->done_fence);
610644
611645 if (bin)
612646 v3d_job_put(&bin->base);
613647 v3d_job_put(&render->base);
648+ if (clean_job)
649+ v3d_job_put(clean_job);
614650
615651 return 0;
616652
617653 fail_unreserve:
618654 mutex_unlock(&v3d->sched_lock);
619− drm_gem_unlock_reservations(render->base.bo,
620− render->base.bo_count, &acquire_ctx);
655+ drm_gem_unlock_reservations(last_job->bo,
656+ last_job->bo_count, &acquire_ctx);
621657 fail:
622658 if (bin)
623659 v3d_job_put(&bin->base);
624660 v3d_job_put(&render->base);
661+ if (clean_job)
662+ v3d_job_put(clean_job);
625663
626664 return ret;
627665 }
include/uapi/drm/v3d_drm.h+5−3
@@ -48,6 +48,8 @@ extern "C" { · 47 unmodified lines
4848 #define DRM_IOCTL_V3D_SUBMIT_TFU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
4949 #define DRM_IOCTL_V3D_SUBMIT_CSD DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CSD, struct drm_v3d_submit_csd)
5050
51+#define DRM_V3D_SUBMIT_CL_FLUSH_CACHE 0x01
52+
5153 /**
5254 * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
5355 * engine.
@@ -61,7 +63,7 @@ extern "C" { · 7 unmodified lines
6163 * flushed by the time the render done IRQ happens, which is the
6264 * trigger for out_sync. Any dirtying of cachelines by the job (only
6365 * 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.
6567 */
6668 struct drm_v3d_submit_cl {
6769 /* Pointer to the binner command list.
@@ -124,8 +126,7 @@ struct drm_v3d_submit_cl { · 56 unmodified lines
124126 /* Number of BO handles passed in (size is that times 4). */
125127 __u32 bo_handle_count;
126128
127− /* Pad, must be zero-filled. */
128− __u32 pad;
129+ __u32 flags;
129130 };
130131
131132 /**
@@ -193,6 +194,7 @@ enum drm_v3d_param { · 61 unmodified lines
193194 DRM_V3D_PARAM_V3D_CORE0_IDENT2,
194195 DRM_V3D_PARAM_SUPPORTS_TFU,
195196 DRM_V3D_PARAM_SUPPORTS_CSD,
197+ DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH,
196198 };
197199
198200 struct drm_v3d_get_param {