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
91 case DRM_V3D_PARAM_SUPPORTS_MULTISYNC_EXT:91 case DRM_V3D_PARAM_SUPPORTS_MULTISYNC_EXT:
92 args->value = 1;92 args->value = 1;
93 return 0;93 return 0;
94 case DRM_V3D_PARAM_SUPPORTS_CPU_QUEUE:
95 args->value = 1;
96 return 0;
94 default:97 default:
95 DRM_DEBUG("Unknown parameter %d\n", args->param);98 DRM_DEBUG("Unknown parameter %d\n", args->param);
96 return -EINVAL;99 return -EINVAL;
@@ -189,6 +192,7 @@ static const struct drm_ioctl_desc v3d_drm_ioctls[] = { · 92 unmodified lines
189 DRM_IOCTL_DEF_DRV(V3D_PERFMON_CREATE, v3d_perfmon_create_ioctl, DRM_RENDER_ALLOW),192 DRM_IOCTL_DEF_DRV(V3D_PERFMON_CREATE, v3d_perfmon_create_ioctl, DRM_RENDER_ALLOW),
190 DRM_IOCTL_DEF_DRV(V3D_PERFMON_DESTROY, v3d_perfmon_destroy_ioctl, DRM_RENDER_ALLOW),193 DRM_IOCTL_DEF_DRV(V3D_PERFMON_DESTROY, v3d_perfmon_destroy_ioctl, DRM_RENDER_ALLOW),
191 DRM_IOCTL_DEF_DRV(V3D_PERFMON_GET_VALUES, v3d_perfmon_get_values_ioctl, DRM_RENDER_ALLOW),194 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),
192};196};
193 197
194static const struct drm_driver v3d_drm_driver = {198static 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
19 19
20#define GMP_GRANULARITY (128 * 1024)20#define GMP_GRANULARITY (128 * 1024)
21 21
22#define V3D_MAX_QUEUES (V3D_CACHE_CLEAN + 1)22#define V3D_MAX_QUEUES (V3D_CPU + 1)
23 23
24static inline char *v3d_queue_to_string(enum v3d_queue queue)24static inline char *v3d_queue_to_string(enum v3d_queue queue)
25{25{
@@ -29,6 +29,7 @@ static inline char *v3d_queue_to_string(enum v3d_queue queue) · 3 unmodified lines
29 case V3D_TFU: return "tfu";29 case V3D_TFU: return "tfu";
30 case V3D_CSD: return "csd";30 case V3D_CSD: return "csd";
31 case V3D_CACHE_CLEAN: return "cache_clean";31 case V3D_CACHE_CLEAN: return "cache_clean";
32 case V3D_CPU: return "cpu";
32 }33 }
33 return "UNKNOWN";34 return "UNKNOWN";
34}35}
@@ -122,6 +123,7 @@ struct v3d_dev { · 87 unmodified lines
122 struct v3d_render_job *render_job;123 struct v3d_render_job *render_job;
123 struct v3d_tfu_job *tfu_job;124 struct v3d_tfu_job *tfu_job;
124 struct v3d_csd_job *csd_job;125 struct v3d_csd_job *csd_job;
126 struct v3d_cpu_job *cpu_job;
125 127
126 struct v3d_queue_state queue[V3D_MAX_QUEUES];128 struct v3d_queue_state queue[V3D_MAX_QUEUES];
127 129
@@ -312,6 +314,16 @@ struct v3d_csd_job { · 184 unmodified lines
312 struct drm_v3d_submit_csd args;314 struct drm_v3d_submit_csd args;
313};315};
314 316
317enum v3d_cpu_job_type {};
318
319struct v3d_cpu_job {
320 struct v3d_job base;
321
322 enum v3d_cpu_job_type job_type;
323};
324
325typedef void (*v3d_cpu_job_fn)(struct v3d_cpu_job *);
326
315struct v3d_submit_outsync {327struct v3d_submit_outsync {
316 struct drm_syncobj *syncobj;328 struct drm_syncobj *syncobj;
317};329};
@@ -414,6 +426,8 @@ int v3d_submit_tfu_ioctl(struct drm_device *dev, void *data, · 96 unmodified lines
414 struct drm_file *file_priv);426 struct drm_file *file_priv);
415int v3d_submit_csd_ioctl(struct drm_device *dev, void *data,427int v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
416 struct drm_file *file_priv);428 struct drm_file *file_priv);
429int v3d_submit_cpu_ioctl(struct drm_device *dev, void *data,
430 struct drm_file *file_priv);
417 431
418/* v3d_irq.c */432/* v3d_irq.c */
419int v3d_irq_init(struct v3d_dev *v3d);433int 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
55 return container_of(sched_job, struct v3d_csd_job, base.base);55 return container_of(sched_job, struct v3d_csd_job, base.base);
56}56}
57 57
58static struct v3d_cpu_job *
59to_cpu_job(struct drm_sched_job *sched_job)
60{
61 return container_of(sched_job, struct v3d_cpu_job, base.base);
62}
63
58static void64static void
59v3d_sched_job_free(struct drm_sched_job *sched_job)65v3d_sched_job_free(struct drm_sched_job *sched_job)
60{66{
@@ -262,6 +268,42 @@ v3d_csd_job_run(struct drm_sched_job *sched_job) · 201 unmodified lines
262 return fence;268 return fence;
263}269}
264 270
271static const v3d_cpu_job_fn cpu_job_function[] = { };
272
273static struct dma_fence *
274v3d_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
265static struct dma_fence *307static struct dma_fence *
266v3d_cache_clean_job_run(struct drm_sched_job *sched_job)308v3d_cache_clean_job_run(struct drm_sched_job *sched_job)
267{309{
@@ -416,6 +458,12 @@ static const struct drm_sched_backend_ops v3d_cache_clean_sched_ops = { · 148 unmodified lines
416 .free_job = v3d_sched_job_free458 .free_job = v3d_sched_job_free
417};459};
418 460
461static 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
419int467int
420v3d_sched_init(struct v3d_dev *v3d)468v3d_sched_init(struct v3d_dev *v3d)
421{469{
@@ -471,6 +519,15 @@ v3d_sched_init(struct v3d_dev *v3d) · 49 unmodified lines
471 goto fail;519 goto fail;
472 }520 }
473 521
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
474 return 0;531 return 0;
475 532
476fail:533fail:
drivers/gpu/drm/v3d/v3d_submit.c+86−0
@@ -772,3 +772,89 @@ fail: · 771 unmodified lines
772 772
773 return ret;773 return ret;
774}774}
775
776static 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 */
787int
788v3d_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
855fail:
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
41#define DRM_V3D_PERFMON_CREATE 0x0841#define DRM_V3D_PERFMON_CREATE 0x08
42#define DRM_V3D_PERFMON_DESTROY 0x0942#define DRM_V3D_PERFMON_DESTROY 0x09
43#define DRM_V3D_PERFMON_GET_VALUES 0x0a43#define DRM_V3D_PERFMON_GET_VALUES 0x0a
44#define DRM_V3D_SUBMIT_CPU 0x0b
44 45
45#define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)46#define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
46#define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)47#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
56 struct drm_v3d_perfmon_destroy)57 struct drm_v3d_perfmon_destroy)
57#define DRM_IOCTL_V3D_PERFMON_GET_VALUES DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_PERFMON_GET_VALUES, \58#define DRM_IOCTL_V3D_PERFMON_GET_VALUES DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_PERFMON_GET_VALUES, \
58 struct drm_v3d_perfmon_get_values)59 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)
59 61
60#define DRM_V3D_SUBMIT_CL_FLUSH_CACHE 0x0162#define DRM_V3D_SUBMIT_CL_FLUSH_CACHE 0x01
61#define DRM_V3D_SUBMIT_EXTENSION 0x0263#define DRM_V3D_SUBMIT_EXTENSION 0x02
@@ -93,6 +95,7 @@ enum v3d_queue { · 31 unmodified lines
93 V3D_TFU,95 V3D_TFU,
94 V3D_CSD,96 V3D_CSD,
95 V3D_CACHE_CLEAN,97 V3D_CACHE_CLEAN,
98 V3D_CPU,
96};99};
97 100
98/**101/**
@@ -276,6 +279,7 @@ enum drm_v3d_param { · 177 unmodified lines
276 DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH,279 DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH,
277 DRM_V3D_PARAM_SUPPORTS_PERFMON,280 DRM_V3D_PARAM_SUPPORTS_PERFMON,
278 DRM_V3D_PARAM_SUPPORTS_MULTISYNC_EXT,281 DRM_V3D_PARAM_SUPPORTS_MULTISYNC_EXT,
282 DRM_V3D_PARAM_SUPPORTS_CPU_QUEUE,
279};283};
280 284
281struct drm_v3d_get_param {285struct drm_v3d_get_param {
@@ -361,6 +365,19 @@ struct drm_v3d_submit_csd { · 79 unmodified lines
361 __u32 pad;365 __u32 pad;
362};366};
363 367
368struct 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
364enum {381enum {
365 V3D_PERFCNT_FEP_VALID_PRIMTS_NO_PIXELS,382 V3D_PERFCNT_FEP_VALID_PRIMTS_NO_PIXELS,
366 V3D_PERFCNT_FEP_VALID_PRIMS,383 V3D_PERFCNT_FEP_VALID_PRIMS,