History

drm/v3d: Add DRM_IOCTL_V3D_PERFMON_SET_GLOBAL

Add a new ioctl, DRM_IOCTL_V3D_PERFMON_SET_GLOBAL, to allow configuration of a global performance monitor (perfmon). Use the global perfmon for all jobs to ensure consistent performance tracking across submissions. This feature is needed to implement a Perfetto datasources in user-space.

Christian Gmeiner committed 1 year ago

Commit c6eabba1 parent f3c03be6 files · +85 −3Browse files

Unified · Split

6 files
  1. drivers/gpu/drm/v3d/v3d_drv.c +1 −0
  2. drivers/gpu/drm/v3d/v3d_drv.h +8 −0
  3. drivers/gpu/drm/v3d/v3d_perfmon.c +37 −0
  4. drivers/gpu/drm/v3d/v3d_sched.c +11 −3
  5. drivers/gpu/drm/v3d/v3d_submit.c +10 −0
  6. include/uapi/drm/v3d_drm.h +18 −0
drivers/gpu/drm/v3d/v3d_drv.c+1−0
@@ -224,6 +224,7 @@ static const struct drm_ioctl_desc v3d_drm_ioctls[] = { · 223 unmodified lines
224 DRM_IOCTL_DEF_DRV(V3D_PERFMON_GET_VALUES, v3d_perfmon_get_values_ioctl, DRM_RENDER_ALLOW),224 DRM_IOCTL_DEF_DRV(V3D_PERFMON_GET_VALUES, v3d_perfmon_get_values_ioctl, DRM_RENDER_ALLOW),
225 DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CPU, v3d_submit_cpu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),225 DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CPU, v3d_submit_cpu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
226 DRM_IOCTL_DEF_DRV(V3D_PERFMON_GET_COUNTER, v3d_perfmon_get_counter_ioctl, DRM_RENDER_ALLOW),226 DRM_IOCTL_DEF_DRV(V3D_PERFMON_GET_COUNTER, v3d_perfmon_get_counter_ioctl, DRM_RENDER_ALLOW),
227 DRM_IOCTL_DEF_DRV(V3D_PERFMON_SET_GLOBAL, v3d_perfmon_set_global_ioctl, DRM_RENDER_ALLOW),
227};228};
228 229
229static const struct drm_driver v3d_drm_driver = {230static const struct drm_driver v3d_drm_driver = {
drivers/gpu/drm/v3d/v3d_drv.h+8−0
@@ -183,6 +183,12 @@ struct v3d_dev { · 182 unmodified lines
183 u32 num_allocated;183 u32 num_allocated;
184 u32 pages_allocated;184 u32 pages_allocated;
185 } bo_stats;185 } bo_stats;
186
187 /* To support a performance analysis tool in user space, we require
188 * a single, globally configured performance monitor (perfmon) for
189 * all jobs.
190 */
191 struct v3d_perfmon *global_perfmon;
186};192};
187 193
188static inline struct v3d_dev *194static inline struct v3d_dev *
@@ -594,6 +600,8 @@ int v3d_perfmon_get_values_ioctl(struct drm_device *dev, void *data, · 405 unmodified lines
594 struct drm_file *file_priv);600 struct drm_file *file_priv);
595int v3d_perfmon_get_counter_ioctl(struct drm_device *dev, void *data,601int v3d_perfmon_get_counter_ioctl(struct drm_device *dev, void *data,
596 struct drm_file *file_priv);602 struct drm_file *file_priv);
603int v3d_perfmon_set_global_ioctl(struct drm_device *dev, void *data,
604 struct drm_file *file_priv);
597 605
598/* v3d_sysfs.c */606/* v3d_sysfs.c */
599int v3d_sysfs_init(struct device *dev);607int v3d_sysfs_init(struct device *dev);
drivers/gpu/drm/v3d/v3d_perfmon.c+37−0
@@ -313,6 +313,9 @@ static int v3d_perfmon_idr_del(int id, void *elem, void *data) · 312 unmodified lines
313 if (perfmon == v3d->active_perfmon)313 if (perfmon == v3d->active_perfmon)
314 v3d_perfmon_stop(v3d, perfmon, false);314 v3d_perfmon_stop(v3d, perfmon, false);
315 315
316 /* If the global perfmon is being destroyed, set it to NULL */
317 cmpxchg(&v3d->global_perfmon, perfmon, NULL);
318
316 v3d_perfmon_put(perfmon);319 v3d_perfmon_put(perfmon);
317 320
318 return 0;321 return 0;
@@ -398,6 +401,9 @@ int v3d_perfmon_destroy_ioctl(struct drm_device *dev, void *data, · 79 unmodified lines
398 if (perfmon == v3d->active_perfmon)401 if (perfmon == v3d->active_perfmon)
399 v3d_perfmon_stop(v3d, perfmon, false);402 v3d_perfmon_stop(v3d, perfmon, false);
400 403
404 /* If the global perfmon is being destroyed, set it to NULL */
405 cmpxchg(&v3d->global_perfmon, perfmon, NULL);
406
401 v3d_perfmon_put(perfmon);407 v3d_perfmon_put(perfmon);
402 408
403 return 0;409 return 0;
@@ -457,3 +463,34 @@ int v3d_perfmon_get_counter_ioctl(struct drm_device *dev, void *data, · 53 unmodified lines
457 463
458 return 0;464 return 0;
459}465}
466
467int v3d_perfmon_set_global_ioctl(struct drm_device *dev, void *data,
468 struct drm_file *file_priv)
469{
470 struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
471 struct drm_v3d_perfmon_set_global *req = data;
472 struct v3d_dev *v3d = to_v3d_dev(dev);
473 struct v3d_perfmon *perfmon;
474
475 if (req->flags & ~DRM_V3D_PERFMON_CLEAR_GLOBAL)
476 return -EINVAL;
477
478 perfmon = v3d_perfmon_find(v3d_priv, req->id);
479 if (!perfmon)
480 return -EINVAL;
481
482 /* If the request is to clear the global performance monitor */
483 if (req->flags & DRM_V3D_PERFMON_CLEAR_GLOBAL) {
484 if (!v3d->global_perfmon)
485 return -EINVAL;
486
487 xchg(&v3d->global_perfmon, NULL);
488
489 return 0;
490 }
491
492 if (cmpxchg(&v3d->global_perfmon, NULL, perfmon))
493 return -EBUSY;
494
495 return 0;
496}
drivers/gpu/drm/v3d/v3d_sched.c+11−3
@@ -120,11 +120,19 @@ v3d_cpu_job_free(struct drm_sched_job *sched_job) · 119 unmodified lines
120static void120static void
121v3d_switch_perfmon(struct v3d_dev *v3d, struct v3d_job *job)121v3d_switch_perfmon(struct v3d_dev *v3d, struct v3d_job *job)
122{122{
123 if (job->perfmon != v3d->active_perfmon)123 struct v3d_perfmon *perfmon = v3d->global_perfmon;
124
125 if (!perfmon)
126 perfmon = job->perfmon;
127
128 if (perfmon == v3d->active_perfmon)
129 return;
130
131 if (perfmon != v3d->active_perfmon)
124 v3d_perfmon_stop(v3d, v3d->active_perfmon, true);132 v3d_perfmon_stop(v3d, v3d->active_perfmon, true);
125 133
126 if (job->perfmon && v3d->active_perfmon != job->perfmon)134 if (perfmon && v3d->active_perfmon != perfmon)
127 v3d_perfmon_start(v3d, job->perfmon);135 v3d_perfmon_start(v3d, perfmon);
128}136}
129 137
130static void138static void
drivers/gpu/drm/v3d/v3d_submit.c+10−0
@@ -981,6 +981,11 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, · 980 unmodified lines
981 goto fail;981 goto fail;
982 982
983 if (args->perfmon_id) {983 if (args->perfmon_id) {
984 if (v3d->global_perfmon) {
985 ret = -EAGAIN;
986 goto fail_perfmon;
987 }
988
984 render->base.perfmon = v3d_perfmon_find(v3d_priv,989 render->base.perfmon = v3d_perfmon_find(v3d_priv,
985 args->perfmon_id);990 args->perfmon_id);
986 991
@@ -1196,6 +1201,11 @@ v3d_submit_csd_ioctl(struct drm_device *dev, void *data, · 209 unmodified lines
1196 goto fail;1201 goto fail;
1197 1202
1198 if (args->perfmon_id) {1203 if (args->perfmon_id) {
1204 if (v3d->global_perfmon) {
1205 ret = -EAGAIN;
1206 goto fail_perfmon;
1207 }
1208
1199 job->base.perfmon = v3d_perfmon_find(v3d_priv,1209 job->base.perfmon = v3d_perfmon_find(v3d_priv,
1200 args->perfmon_id);1210 args->perfmon_id);
1201 if (!job->base.perfmon) {1211 if (!job->base.perfmon) {
include/uapi/drm/v3d_drm.h+18−0
@@ -43,6 +43,7 @@ extern "C" { · 42 unmodified lines
43#define DRM_V3D_PERFMON_GET_VALUES 0x0a43#define DRM_V3D_PERFMON_GET_VALUES 0x0a
44#define DRM_V3D_SUBMIT_CPU 0x0b44#define DRM_V3D_SUBMIT_CPU 0x0b
45#define DRM_V3D_PERFMON_GET_COUNTER 0x0c45#define DRM_V3D_PERFMON_GET_COUNTER 0x0c
46#define DRM_V3D_PERFMON_SET_GLOBAL 0x0d
46 47
47#define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)48#define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
48#define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)49#define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
@@ -61,6 +62,8 @@ extern "C" { · 12 unmodified lines
61#define DRM_IOCTL_V3D_SUBMIT_CPU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CPU, struct drm_v3d_submit_cpu)62#define DRM_IOCTL_V3D_SUBMIT_CPU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CPU, struct drm_v3d_submit_cpu)
62#define DRM_IOCTL_V3D_PERFMON_GET_COUNTER DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_PERFMON_GET_COUNTER, \63#define DRM_IOCTL_V3D_PERFMON_GET_COUNTER DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_PERFMON_GET_COUNTER, \
63 struct drm_v3d_perfmon_get_counter)64 struct drm_v3d_perfmon_get_counter)
65#define DRM_IOCTL_V3D_PERFMON_SET_GLOBAL DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_PERFMON_SET_GLOBAL, \
66 struct drm_v3d_perfmon_set_global)
64 67
65#define DRM_V3D_SUBMIT_CL_FLUSH_CACHE 0x0168#define DRM_V3D_SUBMIT_CL_FLUSH_CACHE 0x01
66#define DRM_V3D_SUBMIT_EXTENSION 0x0269#define DRM_V3D_SUBMIT_EXTENSION 0x02
@@ -766,6 +769,21 @@ struct drm_v3d_perfmon_get_counter { · 699 unmodified lines
766 __u8 reserved[7];769 __u8 reserved[7];
767};770};
768 771
772#define DRM_V3D_PERFMON_CLEAR_GLOBAL 0x0001
773
774/**
775 * struct drm_v3d_perfmon_set_global - ioctl to define a global performance
776 * monitor
777 *
778 * The global performance monitor will be used for all jobs. If a global
779 * performance monitor is defined, jobs with a self-defined performance
780 * monitor won't be allowed.
781 */
782struct drm_v3d_perfmon_set_global {
783 __u32 flags;
784 __u32 id;
785};
786
769#if defined(__cplusplus)787#if defined(__cplusplus)
770}788}
771#endif789#endif