]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
drm/xe/oa/uapi: Query OA unit properties
authorAshutosh Dixit <ashutosh.dixit@intel.com>
Tue, 18 Jun 2024 01:46:04 +0000 (18:46 -0700)
committerAshutosh Dixit <ashutosh.dixit@intel.com>
Tue, 18 Jun 2024 19:40:40 +0000 (12:40 -0700)
Implement query for properties of OA units present on a device.

v2: Clean up reserved/pad fields (Umesh)
    Follow the same scheme as other query structs
v3: Skip reporting reserved engines attached to OA units
v4: Expose oa_buf_size via DRM_XE_PERF_IOCTL_INFO (Umesh)
v5: Don't expose capabilities as OR of properties (Umesh)
v6: Add extensions to query output structs: drm_xe_oa_unit,
    drm_xe_query_oa_units and drm_xe_oa_stream_info
v7: Change oa_units[] array to __u64 type

Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240618014609.3233427-13-ashutosh.dixit@intel.com
drivers/gpu/drm/xe/xe_oa.c
drivers/gpu/drm/xe/xe_query.c
include/uapi/drm/xe_drm.h

index 42b0ba014e358021d4d9a8d82ef2173c29fbced6..038caeb7c9e7e9e6dfa63fe23fc4ce7c19f07b53 100644 (file)
@@ -1050,6 +1050,17 @@ static long xe_oa_status_locked(struct xe_oa_stream *stream, unsigned long arg)
        return 0;
 }
 
+static long xe_oa_info_locked(struct xe_oa_stream *stream, unsigned long arg)
+{
+       struct drm_xe_oa_stream_info info = { .oa_buf_size = XE_OA_BUFFER_SIZE, };
+       void __user *uaddr = (void __user *)arg;
+
+       if (copy_to_user(uaddr, &info, sizeof(info)))
+               return -EFAULT;
+
+       return 0;
+}
+
 static long xe_oa_ioctl_locked(struct xe_oa_stream *stream,
                               unsigned int cmd,
                               unsigned long arg)
@@ -1065,6 +1076,8 @@ static long xe_oa_ioctl_locked(struct xe_oa_stream *stream,
                return xe_oa_config_locked(stream, arg);
        case DRM_XE_PERF_IOCTL_STATUS:
                return xe_oa_status_locked(stream, arg);
+       case DRM_XE_PERF_IOCTL_INFO:
+               return xe_oa_info_locked(stream, arg);
        }
 
        return -EINVAL;
index 995effcb904b04534c7f38ec7ca56cbf8f853e24..4e01df6b1b7a1d1fdecc8b59f4a8c7b0a18741c0 100644 (file)
@@ -602,6 +602,82 @@ query_uc_fw_version(struct xe_device *xe, struct drm_xe_device_query *query)
        return 0;
 }
 
+static size_t calc_oa_unit_query_size(struct xe_device *xe)
+{
+       size_t size = sizeof(struct drm_xe_query_oa_units);
+       struct xe_gt *gt;
+       int i, id;
+
+       for_each_gt(gt, xe, id) {
+               for (i = 0; i < gt->oa.num_oa_units; i++) {
+                       size += sizeof(struct drm_xe_oa_unit);
+                       size += gt->oa.oa_unit[i].num_engines *
+                               sizeof(struct drm_xe_engine_class_instance);
+               }
+       }
+
+       return size;
+}
+
+static int query_oa_units(struct xe_device *xe,
+                         struct drm_xe_device_query *query)
+{
+       void __user *query_ptr = u64_to_user_ptr(query->data);
+       size_t size = calc_oa_unit_query_size(xe);
+       struct drm_xe_query_oa_units *qoa;
+       enum xe_hw_engine_id hwe_id;
+       struct drm_xe_oa_unit *du;
+       struct xe_hw_engine *hwe;
+       struct xe_oa_unit *u;
+       int gt_id, i, j, ret;
+       struct xe_gt *gt;
+       u8 *pdu;
+
+       if (query->size == 0) {
+               query->size = size;
+               return 0;
+       } else if (XE_IOCTL_DBG(xe, query->size != size)) {
+               return -EINVAL;
+       }
+
+       qoa = kzalloc(size, GFP_KERNEL);
+       if (!qoa)
+               return -ENOMEM;
+
+       pdu = (u8 *)&qoa->oa_units[0];
+       for_each_gt(gt, xe, gt_id) {
+               for (i = 0; i < gt->oa.num_oa_units; i++) {
+                       u = &gt->oa.oa_unit[i];
+                       du = (struct drm_xe_oa_unit *)pdu;
+
+                       du->oa_unit_id = u->oa_unit_id;
+                       du->oa_unit_type = u->type;
+                       du->oa_timestamp_freq = xe_oa_timestamp_frequency(gt);
+                       du->capabilities = DRM_XE_OA_CAPS_BASE;
+
+                       j = 0;
+                       for_each_hw_engine(hwe, gt, hwe_id) {
+                               if (!xe_hw_engine_is_reserved(hwe) &&
+                                   xe_oa_unit_id(hwe) == u->oa_unit_id) {
+                                       du->eci[j].engine_class =
+                                               xe_to_user_engine_class[hwe->class];
+                                       du->eci[j].engine_instance = hwe->logical_instance;
+                                       du->eci[j].gt_id = gt->info.id;
+                                       j++;
+                               }
+                       }
+                       du->num_engines = j;
+                       pdu += sizeof(*du) + j * sizeof(du->eci[0]);
+                       qoa->num_oa_units++;
+               }
+       }
+
+       ret = copy_to_user(query_ptr, qoa, size);
+       kfree(qoa);
+
+       return ret ? -EFAULT : 0;
+}
+
 static int (* const xe_query_funcs[])(struct xe_device *xe,
                                      struct drm_xe_device_query *query) = {
        query_engines,
@@ -612,6 +688,7 @@ static int (* const xe_query_funcs[])(struct xe_device *xe,
        query_gt_topology,
        query_engine_cycles,
        query_uc_fw_version,
+       query_oa_units,
 };
 
 int xe_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
index 03a6e479227a520e77866e03d35554d65e3144f6..93e00be44b2d8ee368813c8f82b0867d7e020e21 100644 (file)
@@ -689,6 +689,7 @@ struct drm_xe_device_query {
 #define DRM_XE_DEVICE_QUERY_GT_TOPOLOGY                5
 #define DRM_XE_DEVICE_QUERY_ENGINE_CYCLES      6
 #define DRM_XE_DEVICE_QUERY_UC_FW_VERSION      7
+#define DRM_XE_DEVICE_QUERY_OA_UNITS           8
        /** @query: The type of data to query */
        __u32 query;
 
@@ -1451,6 +1452,75 @@ enum drm_xe_oa_unit_type {
        DRM_XE_OA_UNIT_TYPE_OAM,
 };
 
+/**
+ * struct drm_xe_oa_unit - describe OA unit
+ */
+struct drm_xe_oa_unit {
+       /** @extensions: Pointer to the first extension struct, if any */
+       __u64 extensions;
+
+       /** @oa_unit_id: OA unit ID */
+       __u32 oa_unit_id;
+
+       /** @oa_unit_type: OA unit type of @drm_xe_oa_unit_type */
+       __u32 oa_unit_type;
+
+       /** @capabilities: OA capabilities bit-mask */
+       __u64 capabilities;
+#define DRM_XE_OA_CAPS_BASE            (1 << 0)
+
+       /** @oa_timestamp_freq: OA timestamp freq */
+       __u64 oa_timestamp_freq;
+
+       /** @reserved: MBZ */
+       __u64 reserved[4];
+
+       /** @num_engines: number of engines in @eci array */
+       __u64 num_engines;
+
+       /** @eci: engines attached to this OA unit */
+       struct drm_xe_engine_class_instance eci[];
+};
+
+/**
+ * struct drm_xe_query_oa_units - describe OA units
+ *
+ * If a query is made with a struct drm_xe_device_query where .query
+ * is equal to DRM_XE_DEVICE_QUERY_OA_UNITS, then the reply uses struct
+ * drm_xe_query_oa_units in .data.
+ *
+ * OA unit properties for all OA units can be accessed using a code block
+ * such as the one below:
+ *
+ * .. code-block:: C
+ *
+ *     struct drm_xe_query_oa_units *qoa;
+ *     struct drm_xe_oa_unit *oau;
+ *     u8 *poau;
+ *
+ *     // malloc qoa and issue DRM_XE_DEVICE_QUERY_OA_UNITS. Then:
+ *     poau = (u8 *)&qoa->oa_units[0];
+ *     for (int i = 0; i < qoa->num_oa_units; i++) {
+ *             oau = (struct drm_xe_oa_unit *)poau;
+ *             // Access 'struct drm_xe_oa_unit' fields here
+ *             poau += sizeof(*oau) + oau->num_engines * sizeof(oau->eci[0]);
+ *     }
+ */
+struct drm_xe_query_oa_units {
+       /** @extensions: Pointer to the first extension struct, if any */
+       __u64 extensions;
+       /** @num_oa_units: number of OA units returned in oau[] */
+       __u32 num_oa_units;
+       /** @pad: MBZ */
+       __u32 pad;
+       /**
+        * @oa_units: struct @drm_xe_oa_unit array returned for this device.
+        * Written below as a u64 array to avoid problems with nested flexible
+        * arrays with some compilers
+        */
+       __u64 oa_units[];
+};
+
 /**
  * enum drm_xe_oa_format_type - OA format types as specified in PRM/Bspec
  * 52198/60942
@@ -1590,6 +1660,21 @@ struct drm_xe_oa_stream_status {
        __u64 reserved[3];
 };
 
+/**
+ * struct drm_xe_oa_stream_info - OA stream info returned from
+ * @DRM_XE_PERF_IOCTL_INFO perf fd ioctl
+ */
+struct drm_xe_oa_stream_info {
+       /** @extensions: Pointer to the first extension struct, if any */
+       __u64 extensions;
+
+       /** @oa_buf_size: OA buffer size */
+       __u64 oa_buf_size;
+
+       /** @reserved: reserved for future use */
+       __u64 reserved[3];
+};
+
 #if defined(__cplusplus)
 }
 #endif