summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/v3d/v3d_drv.h5
-rw-r--r--drivers/gpu/drm/v3d/v3d_submit.c92
2 files changed, 72 insertions, 25 deletions
diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h
index 1b88b3dff757..8c46ed09f5c4 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.h
+++ b/drivers/gpu/drm/v3d/v3d_drv.h
@@ -375,6 +375,11 @@ struct v3d_job {
void (*free)(struct kref *ref);
bool has_pm_ref;
+
+ /* Whether the job needs implicit dependencies, i.e. must wait for
+ * other contexts still writing its BOs.
+ */
+ bool has_implicit_dep;
};
struct v3d_bin_job {
diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c
index 5c05f1ea24bc..623df9d5bbee 100644
--- a/drivers/gpu/drm/v3d/v3d_submit.c
+++ b/drivers/gpu/drm/v3d/v3d_submit.c
@@ -46,6 +46,9 @@ v3d_submit_lock_reservations(struct v3d_submit *submit)
for (i = 0; i < submit->job_count; i++) {
struct v3d_job *job = submit->jobs[i];
+ if (!job->has_implicit_dep)
+ continue;
+
for (j = 0; j < job->bo_count; j++) {
ret = drm_sched_job_add_implicit_dependencies(&job->base,
job->bo[j],
@@ -71,7 +74,6 @@ v3d_submit_unlock_reservations(struct v3d_submit *submit)
/**
* v3d_lookup_bos() - Sets up job->bo[] with the GEM objects
* referenced by the job.
- * @dev: DRM device
* @file_priv: DRM file for this fd
* @job: V3D job being set up
* @bo_handles: GEM handles
@@ -85,23 +87,44 @@ v3d_submit_unlock_reservations(struct v3d_submit *submit)
* failure, because that will happen at `v3d_job_free()`.
*/
static int
-v3d_lookup_bos(struct v3d_submit *submit, u64 bo_handles, u32 bo_count)
+v3d_lookup_bos(struct drm_file *file_priv, struct v3d_job *job,
+ u64 bo_handles, u32 bo_count)
{
- struct v3d_job *last_job = submit->jobs[submit->job_count - 1];
-
- last_job->bo_count = bo_count;
-
- if (!last_job->bo_count) {
- /* See comment on bo_index for why we have to check
- * this.
- */
- drm_warn(&submit->v3d->drm, "Rendering requires BOs\n");
+ if (!bo_count) {
+ drm_warn(&job->v3d->drm, "Rendering requires BOs\n");
return -EINVAL;
}
- return drm_gem_objects_lookup(submit->file_priv,
+ job->bo_count = bo_count;
+
+ return drm_gem_objects_lookup(file_priv,
(void __user *)(uintptr_t)bo_handles,
- last_job->bo_count, &last_job->bo);
+ job->bo_count, &job->bo);
+}
+
+/**
+ * v3d_job_reference_bos() - Share another job's BOs with @dst
+ * @dst: job that acquires references to the BOs
+ * @src: job whose already-resolved BO list is shared
+ *
+ * For submissions with multiple jobs that use the same BOs, a trailing job
+ * shouldn't look the handles up again, as it could cause inconsistencies.
+ * Instead, it should reference the previous job's BOs.
+ */
+static int
+v3d_job_reference_bos(struct v3d_job *dst, struct v3d_job *src)
+{
+ dst->bo = kvmalloc_objs(*dst->bo, src->bo_count);
+ if (!dst->bo)
+ return -ENOMEM;
+
+ dst->bo_count = src->bo_count;
+ for (int i = 0; i < dst->bo_count; i++) {
+ dst->bo[i] = src->bo[i];
+ drm_gem_object_get(dst->bo[i]);
+ }
+
+ return 0;
}
static void
@@ -223,13 +246,14 @@ v3d_job_add_syncobjs(struct v3d_job *job, struct drm_file *file_priv,
static const struct {
size_t size;
void (*free)(struct kref *ref);
+ bool has_implicit_dep;
} v3d_job_types[] = {
- [V3D_BIN] = { sizeof(struct v3d_bin_job), v3d_job_free },
- [V3D_RENDER] = { sizeof(struct v3d_render_job), v3d_render_job_free },
- [V3D_TFU] = { sizeof(struct v3d_tfu_job), v3d_job_free },
- [V3D_CSD] = { sizeof(struct v3d_csd_job), v3d_job_free },
- [V3D_CACHE_CLEAN] = { sizeof(struct v3d_job), v3d_job_free },
- [V3D_CPU] = { sizeof(struct v3d_cpu_job), v3d_cpu_job_free },
+ [V3D_BIN] = { sizeof(struct v3d_bin_job), v3d_job_free, false },
+ [V3D_RENDER] = { sizeof(struct v3d_render_job), v3d_render_job_free, true },
+ [V3D_TFU] = { sizeof(struct v3d_tfu_job), v3d_job_free, true },
+ [V3D_CSD] = { sizeof(struct v3d_csd_job), v3d_job_free, true },
+ [V3D_CACHE_CLEAN] = { sizeof(struct v3d_job), v3d_job_free, false },
+ [V3D_CPU] = { sizeof(struct v3d_cpu_job), v3d_cpu_job_free, true },
};
static struct v3d_job *
@@ -251,6 +275,7 @@ v3d_submit_add_job(struct v3d_submit *submit, enum v3d_queue queue)
job->queue = queue;
job->file_priv = v3d_priv;
job->free = v3d_job_types[queue].free;
+ job->has_implicit_dep = v3d_job_types[queue].has_implicit_dep;
ret = drm_sched_job_init(&job->base, &v3d_priv->sched_entity[queue],
1, v3d_priv, submit->file_priv->client_id);
@@ -518,13 +543,18 @@ v3d_setup_csd_jobs_and_bos(struct v3d_submit *submit,
if (ret)
return ret;
+ ret = v3d_lookup_bos(submit->file_priv, &job->base, args->bo_handles,
+ args->bo_handle_count);
+ if (ret)
+ return ret;
+
job->args = *args;
clean_job = v3d_submit_add_job(submit, V3D_CACHE_CLEAN);
if (IS_ERR(clean_job))
return PTR_ERR(clean_job);
- return v3d_lookup_bos(submit, args->bo_handles, args->bo_handle_count);
+ return v3d_job_reference_bos(clean_job, &job->base);
}
static void
@@ -1163,22 +1193,33 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
if (ret)
goto fail;
+ /*
+ * We don't associate the BOs with the BIN job. Fences are only
+ * attached to the last job in the submission chain, and BIN jobs
+ * don't need implicit dependencies since depending on results from
+ * another context is not a realistic scenario for binning.
+ */
+ ret = v3d_lookup_bos(submit.file_priv, &render->base,
+ args->bo_handles, args->bo_handle_count);
+ if (ret)
+ goto fail;
+
if (args->flags & DRM_V3D_SUBMIT_CL_FLUSH_CACHE) {
clean_job = v3d_submit_add_job(&submit, V3D_CACHE_CLEAN);
if (IS_ERR(clean_job)) {
ret = PTR_ERR(clean_job);
goto fail;
}
+
+ ret = v3d_job_reference_bos(clean_job, &render->base);
+ if (ret)
+ goto fail;
}
ret = v3d_attach_perfmon_to_jobs(&submit, args->perfmon_id);
if (ret)
goto fail;
- ret = v3d_lookup_bos(&submit, args->bo_handles, args->bo_handle_count);
- if (ret)
- goto fail;
-
ret = v3d_submit_lock_reservations(&submit);
if (ret)
goto fail;
@@ -1557,7 +1598,8 @@ v3d_submit_cpu_ioctl(struct drm_device *dev, void *data,
* the CSD and clean jobs in the case of indirect CSD job.
*/
if (args->bo_handle_count) {
- ret = v3d_lookup_bos(&submit, args->bo_handles, args->bo_handle_count);
+ ret = v3d_lookup_bos(submit.file_priv, &cpu_job->base,
+ args->bo_handles, args->bo_handle_count);
if (ret)
goto fail;