Commit dd6b4718 authored by Ashutosh Dixit's avatar Ashutosh Dixit

drm/xe/oa/uapi: Query OA unit properties

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: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: default avatarUmesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
Signed-off-by: default avatarAshutosh Dixit <ashutosh.dixit@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240618014609.3233427-13-ashutosh.dixit@intel.com
parent 14e077f8
......@@ -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;
......
......@@ -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)
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment