Commit dd6b4718 authored by Ashutosh Dixit's avatar Ashutosh Dixit
Browse files

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
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -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;
+77 −0
Original line number Diff line number Diff line
@@ -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)
+85 −0
Original line number Diff line number Diff line
@@ -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