[Intel-xe] [PATCH v1 7/8] drm/xe/uapi: Align on a common way to return arrays (engines)

Souza, Jose jose.souza at intel.com
Thu Nov 16 20:42:12 UTC 2023


On Thu, 2023-11-16 at 14:43 +0000, Francois Dugast wrote:
> The uAPI provides queries which return arrays of elements. As of now
> the format used in the struct is different depending on which element
> is queried. Fix this for engines by applying the pattern below:
> 
>         struct drm_xe_query_X {
>            __u32 num_X;
>            struct drm_xe_X Xs[];
>            ...
>         }
> 
> Instead of directly returning an array of struct
> drm_xe_query_engine_info, a new struct drm_xe_query_engine is
> introduced. It contains itself an array of struct drm_xe_engine
> which holds the information about each engine.
> 
> Signed-off-by: Francois Dugast <francois.dugast at intel.com>
> ---
>  drivers/gpu/drm/xe/xe_query.c | 31 ++++++++------
>  include/uapi/drm/xe_drm.h     | 78 +++++++++++++++++++++--------------
>  2 files changed, 65 insertions(+), 44 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_query.c b/drivers/gpu/drm/xe/xe_query.c
> index 5756d8eaf972..87345ed99151 100644
> --- a/drivers/gpu/drm/xe/xe_query.c
> +++ b/drivers/gpu/drm/xe/xe_query.c
> @@ -53,7 +53,8 @@ static size_t calc_hw_engine_info_size(struct xe_device *xe)
>  			i++;
>  		}
>  
> -	return i * sizeof(struct drm_xe_query_engine_info);
> +	return sizeof(struct drm_xe_query_engine) +
> +		i * sizeof(struct drm_xe_engine);
>  }
>  
>  typedef u64 (*__ktime_func_t)(void);
> @@ -186,9 +187,9 @@ static int query_engines(struct xe_device *xe,
>  			 struct drm_xe_device_query *query)
>  {
>  	size_t size = calc_hw_engine_info_size(xe);
> -	struct drm_xe_query_engine_info __user *query_ptr =
> +	struct drm_xe_query_engine __user *query_ptr =
>  		u64_to_user_ptr(query->data);
> -	struct drm_xe_query_engine_info *hw_engine_info;
> +	struct drm_xe_query_engine *engines;
>  	struct xe_hw_engine *hwe;
>  	enum xe_hw_engine_id id;
>  	struct xe_gt *gt;
> @@ -202,8 +203,8 @@ static int query_engines(struct xe_device *xe,
>  		return -EINVAL;
>  	}
>  
> -	hw_engine_info = kmalloc(size, GFP_KERNEL);
> -	if (!hw_engine_info)
> +	engines = kmalloc(size, GFP_KERNEL);
> +	if (!engines)
>  		return -ENOMEM;
>  
>  	for_each_gt(gt, xe, gt_id)
> @@ -211,22 +212,26 @@ static int query_engines(struct xe_device *xe,
>  			if (xe_hw_engine_is_reserved(hwe))
>  				continue;
>  
> -			hw_engine_info[i].instance.engine_class =
> +			engines->engines[i].instance.engine_class =
>  				xe_to_user_engine_class[hwe->class];
> -			hw_engine_info[i].instance.engine_instance =
> +			engines->engines[i].instance.engine_instance =
>  				hwe->logical_instance;
> -			hw_engine_info[i].instance.gt_id = gt->info.id;
> -			hw_engine_info[i].instance.pad = 0;
> -			memset(hw_engine_info->reserved, 0, sizeof(hw_engine_info->reserved));
> +			engines->engines[i].instance.gt_id = gt->info.id;
> +			engines->engines[i].instance.pad = 0;
> +			memset(engines->engines[i].reserved, 0,
> +			       sizeof(engines->engines[i].reserved));
>  
>  			i++;
>  		}
>  
> -	if (copy_to_user(query_ptr, hw_engine_info, size)) {
> -		kfree(hw_engine_info);
> +	engines->pad = 0;
> +	engines->num_engines = i;
> +
> +	if (copy_to_user(query_ptr, engines, size)) {
> +		kfree(engines);
>  		return -EFAULT;
>  	}
> -	kfree(hw_engine_info);
> +	kfree(engines);
>  
>  	return 0;
>  }
> diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
> index fa4f554b5264..b6d3d4d52da9 100644
> --- a/include/uapi/drm/xe_drm.h
> +++ b/include/uapi/drm/xe_drm.h
> @@ -127,9 +127,9 @@ struct xe_user_extension {
>  /**
>   * struct drm_xe_engine_class_instance - instance of an engine class
>   *
> - * It is returned as part of the @drm_xe_query_engine_info, but it also is
> - * used as the input of engine selection for both @drm_xe_exec_queue_create
> - * and @drm_xe_query_engine_cycles
> + * It is returned as part of the @drm_xe_engine, but it also is used as
> + * the input of engine selection for both @drm_xe_exec_queue_create and
> + * @drm_xe_query_engine_cycles
>   *
>   */
>  struct drm_xe_engine_class_instance {
> @@ -153,13 +153,9 @@ struct drm_xe_engine_class_instance {
>  };
>  
>  /**
> - * struct drm_xe_query_engine_info - describe hardware engine
> - *
> - * If a query is made with a struct @drm_xe_device_query where .query
> - * is equal to %DRM_XE_DEVICE_QUERY_ENGINES, then the reply uses an array of
> - * struct @drm_xe_query_engine_info in .data.
> + * struct drm_xe_engine - describe hardware engine
>   */
> -struct drm_xe_query_engine_info {
> +struct drm_xe_engine {
>  	/** @instance: The @drm_xe_engine_class_instance */
>  	struct drm_xe_engine_class_instance instance;
>  
> @@ -167,6 +163,22 @@ struct drm_xe_query_engine_info {
>  	__u64 reserved[5];
>  };
>  
> +/**
> + * struct drm_xe_query_engine - describe engines
> + *
> + * If a query is made with a struct @drm_xe_device_query where .query
> + * is equal to %DRM_XE_DEVICE_QUERY_ENGINES, then the reply uses an array of
> + * struct @drm_xe_query_engine in .data.
> + */
> +struct drm_xe_query_engine {

drm_xe_query_engines.

> +	/** @num_engines: number of engines returned in @engines */
> +	__u32 num_engines;
> +	/** @pad: MBZ */
> +	__u32 pad;
> +	/** @engines: The returned engines for this device */
> +	struct drm_xe_engine engines[];
> +};
> +
>  /**
>   * enum drm_xe_memory_class - Supported memory classes.
>   */
> @@ -465,28 +477,32 @@ struct drm_xe_query_topology_mask {
>   *
>   * .. code-block:: C
>   *
> - *	struct drm_xe_engine_class_instance *hwe;
> - *	struct drm_xe_device_query query = {
> - *		.extensions = 0,
> - *		.query = DRM_XE_DEVICE_QUERY_ENGINES,
> - *		.size = 0,
> - *		.data = 0,
> - *	};
> - *	ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query);
> - *	hwe = malloc(query.size);
> - *	query.data = (uintptr_t)hwe;
> - *	ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query);
> - *	int num_engines = query.size / sizeof(*hwe);
> - *	for (int i = 0; i < num_engines; i++) {
> - *		printf("Engine %d: %s\n", i,
> - *			hwe[i].engine_class == DRM_XE_ENGINE_CLASS_RENDER ? "RENDER":
> - *			hwe[i].engine_class == DRM_XE_ENGINE_CLASS_COPY ? "COPY":
> - *			hwe[i].engine_class == DRM_XE_ENGINE_CLASS_VIDEO_DECODE ? "VIDEO_DECODE":
> - *			hwe[i].engine_class == DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE ? "VIDEO_ENHANCE":
> - *			hwe[i].engine_class == DRM_XE_ENGINE_CLASS_COMPUTE ? "COMPUTE":
> - *			"UNKNOWN");
> - *	}
> - *	free(hwe);
> + *     struct drm_xe_query_engine *engines;
> + *     struct drm_xe_device_query query = {
> + *         .extensions = 0,
> + *         .query = DRM_XE_DEVICE_QUERY_ENGINES,
> + *         .size = 0,
> + *         .data = 0,
> + *     };
> + *     ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query);
> + *     engines = malloc(query.size);
> + *     query.data = (uintptr_t)engines;
> + *     ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query);
> + *     for (int i = 0; i < engines->num_engines; i++) {
> + *         printf("Engine %d: %s\n", i,
> + *             engines->engines[i].instance.engine_class ==
> + *                 DRM_XE_ENGINE_CLASS_RENDER ? "RENDER":
> + *             engines->engines[i].instance.engine_class ==
> + *                 DRM_XE_ENGINE_CLASS_COPY ? "COPY":
> + *             engines->engines[i].instance.engine_class ==
> + *                 DRM_XE_ENGINE_CLASS_VIDEO_DECODE ? "VIDEO_DECODE":
> + *             engines->engines[i].instance.engine_class ==
> + *                 DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE ? "VIDEO_ENHANCE":
> + *             engines->engines[i].instance.engine_class ==
> + *                 DRM_XE_ENGINE_CLASS_COMPUTE ? "COMPUTE":
> + *             "UNKNOWN");
> + *     }
> + *     free(engines);
>   */
>  struct drm_xe_device_query {
>  	/** @extensions: Pointer to the first extension struct, if any */



More information about the Intel-xe mailing list