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: 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
This commit is contained in:
@@ -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 = >->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
|
||||
|
||||
Reference in New Issue
Block a user