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
224224 DRM_IOCTL_DEF_DRV(V3D_PERFMON_GET_VALUES, v3d_perfmon_get_values_ioctl, DRM_RENDER_ALLOW),
225225 DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CPU, v3d_submit_cpu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
226226 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),
227228 };
228229
229230 static 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
183183 u32 num_allocated;
184184 u32 pages_allocated;
185185 } 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;
186192 };
187193
188194 static inline struct v3d_dev *
@@ -594,6 +600,8 @@ int v3d_perfmon_get_values_ioctl(struct drm_device *dev, void *data, · 405 unmodified lines
594600 struct drm_file *file_priv);
595601 int v3d_perfmon_get_counter_ioctl(struct drm_device *dev, void *data,
596602 struct drm_file *file_priv);
603+int v3d_perfmon_set_global_ioctl(struct drm_device *dev, void *data,
604+ struct drm_file *file_priv);
597605
598606 /* v3d_sysfs.c */
599607 int 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
313313 if (perfmon == v3d->active_perfmon)
314314 v3d_perfmon_stop(v3d, perfmon, false);
315315
316+ /* If the global perfmon is being destroyed, set it to NULL */
317+ cmpxchg(&v3d->global_perfmon, perfmon, NULL);
318+
316319 v3d_perfmon_put(perfmon);
317320
318321 return 0;
@@ -398,6 +401,9 @@ int v3d_perfmon_destroy_ioctl(struct drm_device *dev, void *data, · 79 unmodified lines
398401 if (perfmon == v3d->active_perfmon)
399402 v3d_perfmon_stop(v3d, perfmon, false);
400403
404+ /* If the global perfmon is being destroyed, set it to NULL */
405+ cmpxchg(&v3d->global_perfmon, perfmon, NULL);
406+
401407 v3d_perfmon_put(perfmon);
402408
403409 return 0;
@@ -457,3 +463,34 @@ int v3d_perfmon_get_counter_ioctl(struct drm_device *dev, void *data, · 53 unmodified lines
457463
458464 return 0;
459465 }
466+
467+int 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
120120 static void
121121 v3d_switch_perfmon(struct v3d_dev *v3d, struct v3d_job *job)
122122 {
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)
124132 v3d_perfmon_stop(v3d, v3d->active_perfmon, true);
125133
126− if (job->perfmon && v3d->active_perfmon != job->perfmon)
127− v3d_perfmon_start(v3d, job->perfmon);
134+ if (perfmon && v3d->active_perfmon != perfmon)
135+ v3d_perfmon_start(v3d, perfmon);
128136 }
129137
130138 static 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
981981 goto fail;
982982
983983 if (args->perfmon_id) {
984+ if (v3d->global_perfmon) {
985+ ret = -EAGAIN;
986+ goto fail_perfmon;
987+ }
988+
984989 render->base.perfmon = v3d_perfmon_find(v3d_priv,
985990 args->perfmon_id);
986991
@@ -1196,6 +1201,11 @@ v3d_submit_csd_ioctl(struct drm_device *dev, void *data, · 209 unmodified lines
11961201 goto fail;
11971202
11981203 if (args->perfmon_id) {
1204+ if (v3d->global_perfmon) {
1205+ ret = -EAGAIN;
1206+ goto fail_perfmon;
1207+ }
1208+
11991209 job->base.perfmon = v3d_perfmon_find(v3d_priv,
12001210 args->perfmon_id);
12011211 if (!job->base.perfmon) {
include/uapi/drm/v3d_drm.h+18−0
@@ -43,6 +43,7 @@ extern "C" { · 42 unmodified lines
4343 #define DRM_V3D_PERFMON_GET_VALUES 0x0a
4444 #define DRM_V3D_SUBMIT_CPU 0x0b
4545 #define DRM_V3D_PERFMON_GET_COUNTER 0x0c
46+#define DRM_V3D_PERFMON_SET_GLOBAL 0x0d
4647
4748 #define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
4849 #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
6162 #define DRM_IOCTL_V3D_SUBMIT_CPU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CPU, struct drm_v3d_submit_cpu)
6263 #define DRM_IOCTL_V3D_PERFMON_GET_COUNTER DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_PERFMON_GET_COUNTER, \
6364 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)
6467
6568 #define DRM_V3D_SUBMIT_CL_FLUSH_CACHE 0x01
6669 #define DRM_V3D_SUBMIT_EXTENSION 0x02
@@ -766,6 +769,21 @@ struct drm_v3d_perfmon_get_counter { · 699 unmodified lines
766769 __u8 reserved[7];
767770 };
768771
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+ */
782+struct drm_v3d_perfmon_set_global {
783+ __u32 flags;
784+ __u32 id;
785+};
786+
769787 #if defined(__cplusplus)
770788 }
771789 #endif