History

drm/v3d: Add a CPU job submission

Create a new type of job, a CPU job. A CPU job is a type of job that performs operations that requires CPU intervention. The overall idea is to use user extensions to enable different types of CPU job, allowing the CPU job to perform different operations according to the type of user extension. The user extension ID identify the type of CPU job that must be dealt. Having a CPU job is interesting for synchronization purposes as a CPU job has a queue like any other V3D job and can be synchoronized by the multisync extension.

Melissa Wen committed 2 years ago

Commit aafc1a21 parent 464c61e5 files · +179 −1Browse files

Unified · Split

5 files
  1. drivers/gpu/drm/v3d/v3d_drv.c +4 −0
  2. drivers/gpu/drm/v3d/v3d_drv.h +15 −1
  3. drivers/gpu/drm/v3d/v3d_sched.c +57 −0
  4. drivers/gpu/drm/v3d/v3d_submit.c +86 −0
  5. include/uapi/drm/v3d_drm.h +17 −0
drivers/gpu/drm/v3d/v3d_drv.c+4−0
@@ -91,6 +91,9 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data, · 90 unmodified lines
9191 case DRM_V3D_PARAM_SUPPORTS_MULTISYNC_EXT:
9292 args->value = 1;
9393 return 0;
94+ case DRM_V3D_PARAM_SUPPORTS_CPU_QUEUE:
95+ args->value = 1;
96+ return 0;
9497 default:
9598 DRM_DEBUG("Unknown parameter %d\n", args->param);
9699 return -EINVAL;
@@ -189,6 +192,7 @@ static const struct drm_ioctl_desc v3d_drm_ioctls[] = { · 92 unmodified lines
189192 DRM_IOCTL_DEF_DRV(V3D_PERFMON_CREATE, v3d_perfmon_create_ioctl, DRM_RENDER_ALLOW),
190193 DRM_IOCTL_DEF_DRV(V3D_PERFMON_DESTROY, v3d_perfmon_destroy_ioctl, DRM_RENDER_ALLOW),
191194 DRM_IOCTL_DEF_DRV(V3D_PERFMON_GET_VALUES, v3d_perfmon_get_values_ioctl, DRM_RENDER_ALLOW),
195+ DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CPU, v3d_submit_cpu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
192196 };
193197
194198 static const struct drm_driver v3d_drm_driver = {
drivers/gpu/drm/v3d/v3d_drv.h+15−1
@@ -19,7 +19,7 @@ struct reset_control; · 18 unmodified lines
1919
2020 #define GMP_GRANULARITY (128 * 1024)
2121
22−#define V3D_MAX_QUEUES (V3D_CACHE_CLEAN + 1)
22+#define V3D_MAX_QUEUES (V3D_CPU + 1)
2323
2424 static inline char *v3d_queue_to_string(enum v3d_queue queue)
2525 {
@@ -29,6 +29,7 @@ static inline char *v3d_queue_to_string(enum v3d_queue queue) · 3 unmodified lines
2929 case V3D_TFU: return "tfu";
3030 case V3D_CSD: return "csd";
3131 case V3D_CACHE_CLEAN: return "cache_clean";
32+ case V3D_CPU: return "cpu";
3233 }
3334 return "UNKNOWN";
3435 }
@@ -122,6 +123,7 @@ struct v3d_dev { · 87 unmodified lines
122123 struct v3d_render_job *render_job;
123124 struct v3d_tfu_job *tfu_job;
124125 struct v3d_csd_job *csd_job;
126+ struct v3d_cpu_job *cpu_job;
125127
126128 struct v3d_queue_state queue[V3D_MAX_QUEUES];
127129
@@ -312,6 +314,16 @@ struct v3d_csd_job { · 184 unmodified lines
312314 struct drm_v3d_submit_csd args;
313315 };
314316
317+enum v3d_cpu_job_type {};
318+
319+struct v3d_cpu_job {
320+ struct v3d_job base;
321+
322+ enum v3d_cpu_job_type job_type;
323+};
324+
325+typedef void (*v3d_cpu_job_fn)(struct v3d_cpu_job *);
326+
315327 struct v3d_submit_outsync {
316328 struct drm_syncobj *syncobj;
317329 };
@@ -414,6 +426,8 @@ int v3d_submit_tfu_ioctl(struct drm_device *dev, void *data, · 96 unmodified lines
414426 struct drm_file *file_priv);
415427 int v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
416428 struct drm_file *file_priv);
429+int v3d_submit_cpu_ioctl(struct drm_device *dev, void *data,
430+ struct drm_file *file_priv);
417431
418432 /* v3d_irq.c */
419433 int v3d_irq_init(struct v3d_dev *v3d);
drivers/gpu/drm/v3d/v3d_sched.c+57−0
@@ -55,6 +55,12 @@ to_csd_job(struct drm_sched_job *sched_job) · 54 unmodified lines
5555 return container_of(sched_job, struct v3d_csd_job, base.base);
5656 }
5757
58+static struct v3d_cpu_job *
59+to_cpu_job(struct drm_sched_job *sched_job)
60+{
61+ return container_of(sched_job, struct v3d_cpu_job, base.base);
62+}
63+
5864 static void
5965 v3d_sched_job_free(struct drm_sched_job *sched_job)
6066 {
@@ -262,6 +268,42 @@ v3d_csd_job_run(struct drm_sched_job *sched_job) · 201 unmodified lines
262268 return fence;
263269 }
264270
271+static const v3d_cpu_job_fn cpu_job_function[] = { };
272+
273+static struct dma_fence *
274+v3d_cpu_job_run(struct drm_sched_job *sched_job)
275+{
276+ struct v3d_cpu_job *job = to_cpu_job(sched_job);
277+ struct v3d_dev *v3d = job->base.v3d;
278+ struct v3d_file_priv *file = job->base.file->driver_priv;
279+ u64 runtime;
280+
281+ v3d->cpu_job = job;
282+
283+ if (job->job_type >= ARRAY_SIZE(cpu_job_function)) {
284+ DRM_DEBUG_DRIVER("Unknown CPU job: %d\n", job->job_type);
285+ return NULL;
286+ }
287+
288+ file->start_ns[V3D_CPU] = local_clock();
289+ v3d->queue[V3D_CPU].start_ns = file->start_ns[V3D_CPU];
290+
291+ cpu_job_function[job->job_type](job);
292+
293+ runtime = local_clock() - file->start_ns[V3D_CPU];
294+
295+ file->enabled_ns[V3D_CPU] += runtime;
296+ v3d->queue[V3D_CPU].enabled_ns += runtime;
297+
298+ file->jobs_sent[V3D_CPU]++;
299+ v3d->queue[V3D_CPU].jobs_sent++;
300+
301+ file->start_ns[V3D_CPU] = 0;
302+ v3d->queue[V3D_CPU].start_ns = 0;
303+
304+ return NULL;
305+}
306+
265307 static struct dma_fence *
266308 v3d_cache_clean_job_run(struct drm_sched_job *sched_job)
267309 {
@@ -416,6 +458,12 @@ static const struct drm_sched_backend_ops v3d_cache_clean_sched_ops = { · 148 unmodified lines
416458 .free_job = v3d_sched_job_free
417459 };
418460
461+static const struct drm_sched_backend_ops v3d_cpu_sched_ops = {
462+ .run_job = v3d_cpu_job_run,
463+ .timedout_job = v3d_generic_job_timedout,
464+ .free_job = v3d_sched_job_free
465+};
466+
419467 int
420468 v3d_sched_init(struct v3d_dev *v3d)
421469 {
@@ -471,6 +519,15 @@ v3d_sched_init(struct v3d_dev *v3d) · 49 unmodified lines
471519 goto fail;
472520 }
473521
522+ ret = drm_sched_init(&v3d->queue[V3D_CPU].sched,
523+ &v3d_cpu_sched_ops, NULL,
524+ DRM_SCHED_PRIORITY_COUNT,
525+ 1, job_hang_limit,
526+ msecs_to_jiffies(hang_limit_ms), NULL,
527+ NULL, "v3d_cpu", v3d->drm.dev);
528+ if (ret)
529+ goto fail;
530+
474531 return 0;
475532
476533 fail:
drivers/gpu/drm/v3d/v3d_submit.c+86−0
@@ -772,3 +772,89 @@ fail: · 771 unmodified lines
772772
773773 return ret;
774774 }
775+
776+static const unsigned int cpu_job_bo_handle_count[] = { };
777+
778+/**
779+ * v3d_submit_cpu_ioctl() - Submits a CPU job to the V3D.
780+ * @dev: DRM device
781+ * @data: ioctl argument
782+ * @file_priv: DRM file for this fd
783+ *
784+ * Userspace specifies the CPU job type and data required to perform its
785+ * operations through the drm_v3d_extension struct.
786+ */
787+int
788+v3d_submit_cpu_ioctl(struct drm_device *dev, void *data,
789+ struct drm_file *file_priv)
790+{
791+ struct v3d_dev *v3d = to_v3d_dev(dev);
792+ struct drm_v3d_submit_cpu *args = data;
793+ struct v3d_submit_ext se = {0};
794+ struct v3d_cpu_job *cpu_job = NULL;
795+ struct ww_acquire_ctx acquire_ctx;
796+ int ret;
797+
798+ if (args->flags && !(args->flags & DRM_V3D_SUBMIT_EXTENSION)) {
799+ DRM_INFO("Invalid flags: %d\n", args->flags);
800+ return -EINVAL;
801+ }
802+
803+ ret = v3d_job_allocate((void *)&cpu_job, sizeof(*cpu_job));
804+ if (ret)
805+ return ret;
806+
807+ if (args->flags & DRM_V3D_SUBMIT_EXTENSION) {
808+ ret = v3d_get_extensions(file_priv, args->extensions, &se);
809+ if (ret) {
810+ DRM_DEBUG("Failed to get extensions.\n");
811+ goto fail;
812+ }
813+ }
814+
815+ /* Every CPU job must have a CPU job user extension */
816+ if (!cpu_job->job_type) {
817+ DRM_DEBUG("CPU job must have a CPU job user extension.\n");
818+ goto fail;
819+ }
820+
821+ if (args->bo_handle_count != cpu_job_bo_handle_count[cpu_job->job_type]) {
822+ DRM_DEBUG("This CPU job was not submitted with the proper number of BOs.\n");
823+ goto fail;
824+ }
825+
826+ ret = v3d_job_init(v3d, file_priv, &cpu_job->base,
827+ v3d_job_free, 0, &se, V3D_CPU);
828+ if (ret)
829+ goto fail;
830+
831+ if (args->bo_handle_count) {
832+ ret = v3d_lookup_bos(dev, file_priv, &cpu_job->base,
833+ args->bo_handles, args->bo_handle_count);
834+ if (ret)
835+ goto fail;
836+
837+ ret = v3d_lock_bo_reservations(&cpu_job->base, &acquire_ctx);
838+ if (ret)
839+ goto fail;
840+ }
841+
842+ mutex_lock(&v3d->sched_lock);
843+ v3d_push_job(&cpu_job->base);
844+ mutex_unlock(&v3d->sched_lock);
845+
846+ v3d_attach_fences_and_unlock_reservation(file_priv,
847+ &cpu_job->base,
848+ &acquire_ctx, 0,
849+ NULL, cpu_job->base.done_fence);
850+
851+ v3d_job_put(&cpu_job->base);
852+
853+ return 0;
854+
855+fail:
856+ v3d_job_cleanup((void *)cpu_job);
857+ v3d_put_multisync_post_deps(&se);
858+
859+ return ret;
860+}
include/uapi/drm/v3d_drm.h+17−0
@@ -41,6 +41,7 @@ extern "C" { · 40 unmodified lines
4141 #define DRM_V3D_PERFMON_CREATE 0x08
4242 #define DRM_V3D_PERFMON_DESTROY 0x09
4343 #define DRM_V3D_PERFMON_GET_VALUES 0x0a
44+#define DRM_V3D_SUBMIT_CPU 0x0b
4445
4546 #define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
4647 #define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
@@ -56,6 +57,7 @@ extern "C" { · 9 unmodified lines
5657 struct drm_v3d_perfmon_destroy)
5758 #define DRM_IOCTL_V3D_PERFMON_GET_VALUES DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_PERFMON_GET_VALUES, \
5859 struct drm_v3d_perfmon_get_values)
60+#define DRM_IOCTL_V3D_SUBMIT_CPU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CPU, struct drm_v3d_submit_cpu)
5961
6062 #define DRM_V3D_SUBMIT_CL_FLUSH_CACHE 0x01
6163 #define DRM_V3D_SUBMIT_EXTENSION 0x02
@@ -93,6 +95,7 @@ enum v3d_queue { · 31 unmodified lines
9395 V3D_TFU,
9496 V3D_CSD,
9597 V3D_CACHE_CLEAN,
98+ V3D_CPU,
9699 };
97100
98101 /**
@@ -276,6 +279,7 @@ enum drm_v3d_param { · 177 unmodified lines
276279 DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH,
277280 DRM_V3D_PARAM_SUPPORTS_PERFMON,
278281 DRM_V3D_PARAM_SUPPORTS_MULTISYNC_EXT,
282+ DRM_V3D_PARAM_SUPPORTS_CPU_QUEUE,
279283 };
280284
281285 struct drm_v3d_get_param {
@@ -361,6 +365,19 @@ struct drm_v3d_submit_csd { · 79 unmodified lines
361365 __u32 pad;
362366 };
363367
368+struct drm_v3d_submit_cpu {
369+ /* Pointer to a u32 array of the BOs that are referenced by the job. */
370+ __u64 bo_handles;
371+
372+ /* Number of BO handles passed in (size is that times 4). */
373+ __u32 bo_handle_count;
374+
375+ __u32 flags;
376+
377+ /* Pointer to an array of ioctl extensions*/
378+ __u64 extensions;
379+};
380+
364381 enum {
365382 V3D_PERFCNT_FEP_VALID_PRIMTS_NO_PIXELS,
366383 V3D_PERFCNT_FEP_VALID_PRIMS,