Commit da3208e8 authored by Daniel Vetter's avatar Daniel Vetter

drm/v3d: Use scheduler dependency handling

With the prep work out of the way this isn't tricky anymore.

Aside: The chaining of the various jobs is a bit awkward, with the
possibility of failure in bad places. I think with the
drm_sched_job_init/arm split and maybe preloading the
job->dependencies xarray this should be fixable.

v2: Rebase over renamed function names for adding dependencies.

Reviewed-by: Melissa Wen <mwen@igalia.com> (v1)
Acked-by: default avatarEmma Anholt <emma@anholt.net>
Cc: Melissa Wen <melissa.srw@gmail.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@intel.com>
Cc: Emma Anholt <emma@anholt.net>
Link: https://patchwork.freedesktop.org/patch/msgid/20210805104705.862416-11-daniel.vetter@ffwll.ch
parent 916044fa
...@@ -234,11 +234,6 @@ struct v3d_job { ...@@ -234,11 +234,6 @@ struct v3d_job {
struct drm_gem_object **bo; struct drm_gem_object **bo;
u32 bo_count; u32 bo_count;
/* Array of struct dma_fence * to block on before submitting this job.
*/
struct xarray deps;
unsigned long last_dep;
/* v3d fence to be signaled by IRQ handler when the job is complete. */ /* v3d fence to be signaled by IRQ handler when the job is complete. */
struct dma_fence *irq_fence; struct dma_fence *irq_fence;
......
...@@ -259,8 +259,8 @@ v3d_lock_bo_reservations(struct v3d_job *job, ...@@ -259,8 +259,8 @@ v3d_lock_bo_reservations(struct v3d_job *job,
return ret; return ret;
for (i = 0; i < job->bo_count; i++) { for (i = 0; i < job->bo_count; i++) {
ret = drm_gem_fence_array_add_implicit(&job->deps, ret = drm_sched_job_add_implicit_dependencies(&job->base,
job->bo[i], true); job->bo[i], true);
if (ret) { if (ret) {
drm_gem_unlock_reservations(job->bo, job->bo_count, drm_gem_unlock_reservations(job->bo, job->bo_count,
acquire_ctx); acquire_ctx);
...@@ -356,8 +356,6 @@ static void ...@@ -356,8 +356,6 @@ static void
v3d_job_free(struct kref *ref) v3d_job_free(struct kref *ref)
{ {
struct v3d_job *job = container_of(ref, struct v3d_job, refcount); struct v3d_job *job = container_of(ref, struct v3d_job, refcount);
unsigned long index;
struct dma_fence *fence;
int i; int i;
for (i = 0; i < job->bo_count; i++) { for (i = 0; i < job->bo_count; i++) {
...@@ -366,11 +364,6 @@ v3d_job_free(struct kref *ref) ...@@ -366,11 +364,6 @@ v3d_job_free(struct kref *ref)
} }
kvfree(job->bo); kvfree(job->bo);
xa_for_each(&job->deps, index, fence) {
dma_fence_put(fence);
}
xa_destroy(&job->deps);
dma_fence_put(job->irq_fence); dma_fence_put(job->irq_fence);
dma_fence_put(job->done_fence); dma_fence_put(job->done_fence);
...@@ -457,7 +450,6 @@ v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv, ...@@ -457,7 +450,6 @@ v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv,
if (ret < 0) if (ret < 0)
return ret; return ret;
xa_init_flags(&job->deps, XA_FLAGS_ALLOC);
ret = drm_sched_job_init(&job->base, &v3d_priv->sched_entity[queue], ret = drm_sched_job_init(&job->base, &v3d_priv->sched_entity[queue],
v3d_priv); v3d_priv);
if (ret) if (ret)
...@@ -467,7 +459,7 @@ v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv, ...@@ -467,7 +459,7 @@ v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv,
if (ret == -EINVAL) if (ret == -EINVAL)
goto fail_job; goto fail_job;
ret = drm_gem_fence_array_add(&job->deps, in_fence); ret = drm_sched_job_add_dependency(&job->base, in_fence);
if (ret) if (ret)
goto fail_job; goto fail_job;
...@@ -477,7 +469,6 @@ v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv, ...@@ -477,7 +469,6 @@ v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv,
fail_job: fail_job:
drm_sched_job_cleanup(&job->base); drm_sched_job_cleanup(&job->base);
fail: fail:
xa_destroy(&job->deps);
pm_runtime_put_autosuspend(v3d->drm.dev); pm_runtime_put_autosuspend(v3d->drm.dev);
return ret; return ret;
} }
...@@ -640,8 +631,8 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, ...@@ -640,8 +631,8 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
v3d_perfmon_get(bin->base.perfmon); v3d_perfmon_get(bin->base.perfmon);
v3d_push_job(&bin->base); v3d_push_job(&bin->base);
ret = drm_gem_fence_array_add(&render->base.deps, ret = drm_sched_job_add_dependency(&render->base.base,
dma_fence_get(bin->base.done_fence)); dma_fence_get(bin->base.done_fence));
if (ret) if (ret)
goto fail_unreserve; goto fail_unreserve;
} }
...@@ -651,7 +642,8 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, ...@@ -651,7 +642,8 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
if (clean_job) { if (clean_job) {
struct dma_fence *render_fence = struct dma_fence *render_fence =
dma_fence_get(render->base.done_fence); dma_fence_get(render->base.done_fence);
ret = drm_gem_fence_array_add(&clean_job->deps, render_fence); ret = drm_sched_job_add_dependency(&clean_job->base,
render_fence);
if (ret) if (ret)
goto fail_unreserve; goto fail_unreserve;
clean_job->perfmon = render->base.perfmon; clean_job->perfmon = render->base.perfmon;
...@@ -853,8 +845,8 @@ v3d_submit_csd_ioctl(struct drm_device *dev, void *data, ...@@ -853,8 +845,8 @@ v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
mutex_lock(&v3d->sched_lock); mutex_lock(&v3d->sched_lock);
v3d_push_job(&job->base); v3d_push_job(&job->base);
ret = drm_gem_fence_array_add(&clean_job->deps, ret = drm_sched_job_add_dependency(&clean_job->base,
dma_fence_get(job->base.done_fence)); dma_fence_get(job->base.done_fence));
if (ret) if (ret)
goto fail_unreserve; goto fail_unreserve;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* jobs when bulk background jobs are queued up, we submit a new job * jobs when bulk background jobs are queued up, we submit a new job
* to the HW only when it has completed the last one, instead of * to the HW only when it has completed the last one, instead of
* filling up the CT[01]Q FIFOs with jobs. Similarly, we use * filling up the CT[01]Q FIFOs with jobs. Similarly, we use
* v3d_job_dependency() to manage the dependency between bin and * drm_sched_job_add_dependency() to manage the dependency between bin and
* render, instead of having the clients submit jobs using the HW's * render, instead of having the clients submit jobs using the HW's
* semaphores to interlock between them. * semaphores to interlock between them.
*/ */
...@@ -72,28 +72,6 @@ v3d_switch_perfmon(struct v3d_dev *v3d, struct v3d_job *job) ...@@ -72,28 +72,6 @@ v3d_switch_perfmon(struct v3d_dev *v3d, struct v3d_job *job)
v3d_perfmon_start(v3d, job->perfmon); v3d_perfmon_start(v3d, job->perfmon);
} }
/*
* Returns the fences that the job depends on, one by one.
*
* If placed in the scheduler's .dependency method, the corresponding
* .run_job won't be called until all of them have been signaled.
*/
static struct dma_fence *
v3d_job_dependency(struct drm_sched_job *sched_job,
struct drm_sched_entity *s_entity)
{
struct v3d_job *job = to_v3d_job(sched_job);
/* XXX: Wait on a fence for switching the GMP if necessary,
* and then do so.
*/
if (!xa_empty(&job->deps))
return xa_erase(&job->deps, job->last_dep++);
return NULL;
}
static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job) static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
{ {
struct v3d_bin_job *job = to_bin_job(sched_job); struct v3d_bin_job *job = to_bin_job(sched_job);
...@@ -372,35 +350,30 @@ v3d_csd_job_timedout(struct drm_sched_job *sched_job) ...@@ -372,35 +350,30 @@ v3d_csd_job_timedout(struct drm_sched_job *sched_job)
} }
static const struct drm_sched_backend_ops v3d_bin_sched_ops = { static const struct drm_sched_backend_ops v3d_bin_sched_ops = {
.dependency = v3d_job_dependency,
.run_job = v3d_bin_job_run, .run_job = v3d_bin_job_run,
.timedout_job = v3d_bin_job_timedout, .timedout_job = v3d_bin_job_timedout,
.free_job = v3d_sched_job_free, .free_job = v3d_sched_job_free,
}; };
static const struct drm_sched_backend_ops v3d_render_sched_ops = { static const struct drm_sched_backend_ops v3d_render_sched_ops = {
.dependency = v3d_job_dependency,
.run_job = v3d_render_job_run, .run_job = v3d_render_job_run,
.timedout_job = v3d_render_job_timedout, .timedout_job = v3d_render_job_timedout,
.free_job = v3d_sched_job_free, .free_job = v3d_sched_job_free,
}; };
static const struct drm_sched_backend_ops v3d_tfu_sched_ops = { static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {
.dependency = v3d_job_dependency,
.run_job = v3d_tfu_job_run, .run_job = v3d_tfu_job_run,
.timedout_job = v3d_generic_job_timedout, .timedout_job = v3d_generic_job_timedout,
.free_job = v3d_sched_job_free, .free_job = v3d_sched_job_free,
}; };
static const struct drm_sched_backend_ops v3d_csd_sched_ops = { static const struct drm_sched_backend_ops v3d_csd_sched_ops = {
.dependency = v3d_job_dependency,
.run_job = v3d_csd_job_run, .run_job = v3d_csd_job_run,
.timedout_job = v3d_csd_job_timedout, .timedout_job = v3d_csd_job_timedout,
.free_job = v3d_sched_job_free .free_job = v3d_sched_job_free
}; };
static const struct drm_sched_backend_ops v3d_cache_clean_sched_ops = { static const struct drm_sched_backend_ops v3d_cache_clean_sched_ops = {
.dependency = v3d_job_dependency,
.run_job = v3d_cache_clean_job_run, .run_job = v3d_cache_clean_job_run,
.timedout_job = v3d_generic_job_timedout, .timedout_job = v3d_generic_job_timedout,
.free_job = v3d_sched_job_free .free_job = v3d_sched_job_free
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment