diff mbox series

[v4,RFC] drm/i915/uapi: Add DRM_I915_QUERY_GEOMETRY_SUBSLICES

Message ID 20220330215311.21849-1-matthew.s.atwood@intel.com (mailing list archive)
State New, archived
Headers show
Series [v4,RFC] drm/i915/uapi: Add DRM_I915_QUERY_GEOMETRY_SUBSLICES | expand

Commit Message

Matt Atwood March 30, 2022, 9:53 p.m. UTC
Newer platforms have DSS that aren't necessarily available for both
geometry and compute, two queries will need to exist. This introduces
the first, when passing a valid engine class and engine instance in the
flags returns a topology describing geometry.

v2: fix white space errors
v3: change flags from hosting 2 8 bit numbers to holding a
i915_engine_class_instance struct
v4: add error if non rcs engine passed.

Cc: Ashutosh Dixit <ashutosh.dixit@intel.com>
Cc: Matt Roper <matthew.d.roper@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
UMD (mesa): https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14143

Signed-off-by: Matt Atwood <matthew.s.atwood@intel.com>
---
 drivers/gpu/drm/i915/i915_query.c | 71 ++++++++++++++++++++++---------
 include/uapi/drm/i915_drm.h       | 26 +++++++----
 2 files changed, 69 insertions(+), 28 deletions(-)

Comments

Daniel Vetter March 31, 2022, 7:05 p.m. UTC | #1
On Wed, Mar 30, 2022 at 02:53:11PM -0700, Matt Atwood wrote:
> Newer platforms have DSS that aren't necessarily available for both
> geometry and compute, two queries will need to exist. This introduces
> the first, when passing a valid engine class and engine instance in the
> flags returns a topology describing geometry.
> 
> v2: fix white space errors
> v3: change flags from hosting 2 8 bit numbers to holding a
> i915_engine_class_instance struct
> v4: add error if non rcs engine passed.
> 
> Cc: Ashutosh Dixit <ashutosh.dixit@intel.com>
> Cc: Matt Roper <matthew.d.roper@intel.com>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> UMD (mesa): https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14143
> 
> Signed-off-by: Matt Atwood <matthew.s.atwood@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_query.c | 71 ++++++++++++++++++++++---------
>  include/uapi/drm/i915_drm.h       | 26 +++++++----
>  2 files changed, 69 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
> index b5ca00cb6cf6..32be84c95956 100644
> --- a/drivers/gpu/drm/i915/i915_query.c
> +++ b/drivers/gpu/drm/i915/i915_query.c
> @@ -9,6 +9,7 @@
>  #include "i915_drv.h"
>  #include "i915_perf.h"
>  #include "i915_query.h"
> +#include "gt/intel_engine_user.h"
>  #include <uapi/drm/i915_drm.h>
>  
>  static int copy_query_item(void *query_hdr, size_t query_sz,
> @@ -28,36 +29,30 @@ static int copy_query_item(void *query_hdr, size_t query_sz,
>  	return 0;
>  }
>  
> -static int query_topology_info(struct drm_i915_private *dev_priv,
> -			       struct drm_i915_query_item *query_item)
> +static int fill_topology_info(const struct sseu_dev_info *sseu,
> +			      struct drm_i915_query_item *query_item,
> +			      const u8 *subslice_mask)
>  {
> -	const struct sseu_dev_info *sseu = &to_gt(dev_priv)->info.sseu;
>  	struct drm_i915_query_topology_info topo;
>  	u32 slice_length, subslice_length, eu_length, total_length;
>  	int ret;
>  
> -	if (query_item->flags != 0)
> -		return -EINVAL;
> +	BUILD_BUG_ON(sizeof(u8) != sizeof(sseu->slice_mask));
>  
>  	if (sseu->max_slices == 0)
>  		return -ENODEV;
>  
> -	BUILD_BUG_ON(sizeof(u8) != sizeof(sseu->slice_mask));
> -
>  	slice_length = sizeof(sseu->slice_mask);
>  	subslice_length = sseu->max_slices * sseu->ss_stride;
>  	eu_length = sseu->max_slices * sseu->max_subslices * sseu->eu_stride;
>  	total_length = sizeof(topo) + slice_length + subslice_length +
>  		       eu_length;
>  
> -	ret = copy_query_item(&topo, sizeof(topo), total_length,
> -			      query_item);
> +	ret = copy_query_item(&topo, sizeof(topo), total_length, query_item);
> +
>  	if (ret != 0)
>  		return ret;
>  
> -	if (topo.flags != 0)
> -		return -EINVAL;
> -
>  	memset(&topo, 0, sizeof(topo));
>  	topo.max_slices = sseu->max_slices;
>  	topo.max_subslices = sseu->max_subslices;
> @@ -69,27 +64,64 @@ static int query_topology_info(struct drm_i915_private *dev_priv,
>  	topo.eu_stride = sseu->eu_stride;
>  
>  	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr),
> -			   &topo, sizeof(topo)))
> +			 &topo, sizeof(topo)))
>  		return -EFAULT;
>  
>  	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr + sizeof(topo)),
> -			   &sseu->slice_mask, slice_length))
> +			 &sseu->slice_mask, slice_length))
>  		return -EFAULT;
>  
>  	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr +
> -					   sizeof(topo) + slice_length),
> -			   sseu->subslice_mask, subslice_length))
> +					 sizeof(topo) + slice_length),
> +			 subslice_mask, subslice_length))
>  		return -EFAULT;
>  
>  	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr +
> -					   sizeof(topo) +
> -					   slice_length + subslice_length),
> -			   sseu->eu_mask, eu_length))
> +					 sizeof(topo) +
> +					 slice_length + subslice_length),
> +			 sseu->eu_mask, eu_length))
>  		return -EFAULT;
>  
>  	return total_length;
>  }
>  
> +static int query_topology_info(struct drm_i915_private *dev_priv,
> +			       struct drm_i915_query_item *query_item)
> +{
> +	const struct sseu_dev_info *sseu = &to_gt(dev_priv)->info.sseu;
> +
> +	if (query_item->flags != 0)
> +		return -EINVAL;
> +
> +	return fill_topology_info(sseu, query_item, sseu->subslice_mask);
> +}
> +
> +static int query_geometry_subslices(struct drm_i915_private *i915,
> +				    struct drm_i915_query_item *query_item)
> +{
> +	const struct sseu_dev_info *sseu;
> +	struct intel_engine_cs *engine;
> +	struct i915_engine_class_instance classinstance;
> +
> +	if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 50))
> +		return -ENODEV;
> +
> +	classinstance = *((struct i915_engine_class_instance *)&query_item->flags);
> +
> +	engine = intel_engine_lookup_user(i915, (u8) classinstance.engine_class,
> +					  (u8) classinstance.engine_instance);
> +
> +	if (!engine)
> +		return -EINVAL;
> +
> +	if (engine->class != RENDER_CLASS)
> +		return -EINVAL;
> +
> +	sseu = &engine->gt->info.sseu;
> +
> +	return fill_topology_info(sseu, query_item, sseu->geometry_subslice_mask);
> +}
> +
>  static int
>  query_engine_info(struct drm_i915_private *i915,
>  		  struct drm_i915_query_item *query_item)
> @@ -508,6 +540,7 @@ static int (* const i915_query_funcs[])(struct drm_i915_private *dev_priv,
>  	query_perf_config,
>  	query_memregion_info,
>  	query_hwconfig_blob,
> +	query_geometry_subslices,
>  };
>  
>  int i915_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
> diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
> index 9ab021c4d632..c2a18afcf791 100644
> --- a/include/uapi/drm/i915_drm.h
> +++ b/include/uapi/drm/i915_drm.h
> @@ -2690,11 +2690,12 @@ struct drm_i915_perf_oa_config {
>  struct drm_i915_query_item {
>  	/** @query_id: The id for this query */
>  	__u64 query_id;
> -#define DRM_I915_QUERY_TOPOLOGY_INFO    1
> -#define DRM_I915_QUERY_ENGINE_INFO	2
> -#define DRM_I915_QUERY_PERF_CONFIG      3
> -#define DRM_I915_QUERY_MEMORY_REGIONS   4
> -#define DRM_I915_QUERY_HWCONFIG_BLOB	5
> +#define DRM_I915_QUERY_TOPOLOGY_INFO		1
> +#define DRM_I915_QUERY_ENGINE_INFO		2
> +#define DRM_I915_QUERY_PERF_CONFIG		3
> +#define DRM_I915_QUERY_MEMORY_REGIONS		4
> +#define DRM_I915_QUERY_HWCONFIG_BLOB		5
> +#define DRM_I915_QUERY_GEOMETRY_SUBSLICES	6
>  /* Must be kept compact -- no holes and well documented */
>  
>  	/**
> @@ -2718,6 +2719,9 @@ struct drm_i915_query_item {
>  	 *	- DRM_I915_QUERY_PERF_CONFIG_LIST
>  	 *      - DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID
>  	 *      - DRM_I915_QUERY_PERF_CONFIG_FOR_UUID
> +	 *
> +	 * When query_id == DRM_I915_QUERY_GEOMETRY_SUBSLICES must have a valid
> +	 * i915_engine_class_instance struct.
>  	 */
>  	__u32 flags;
>  #define DRM_I915_QUERY_PERF_CONFIG_LIST          1
> @@ -2776,16 +2780,20 @@ struct drm_i915_query {
>  };
>  
>  /*

Can we please include this in the kerneldoc, and also make sure that the
queries are nicely all listed somewhere and link to each respective
information structure?

Most of the doc for queries is there now, but the presentation and linking
lacks still a lot.
-Daniel

> - * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO :
> + * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO,
> + * DRM_I915_QUERY_GEOMETRY_SUBSLICE:
>   *
>   * data: contains the 3 pieces of information :
>   *
> - * - the slice mask with one bit per slice telling whether a slice is
> - *   available. The availability of slice X can be queried with the following
> - *   formula :
> + * - For DRM_I915_QUERY_TOPOLOGY_INFO the slice mask with one bit per slice
> + *   telling whether a slice is available. The availability of slice X can be
> + *   queried with the following formula :
>   *
>   *           (data[X / 8] >> (X % 8)) & 1
>   *
> + * - For DRM_I915_QUERY_GEOMETRY_SUBSLICES Slices are equal to 1 and this field
> + *   is not used.
> + *
>   * - the subslice mask for each slice with one bit per subslice telling
>   *   whether a subslice is available. Gen12 has dual-subslices, which are
>   *   similar to two gen11 subslices. For gen12, this array represents dual-
> -- 
> 2.21.3
>
Francisco Jerez April 1, 2022, 10:19 p.m. UTC | #2
Daniel Vetter <daniel@ffwll.ch> writes:

> On Wed, Mar 30, 2022 at 02:53:11PM -0700, Matt Atwood wrote:
>> Newer platforms have DSS that aren't necessarily available for both
>> geometry and compute, two queries will need to exist. This introduces
>> the first, when passing a valid engine class and engine instance in the
>> flags returns a topology describing geometry.
>> 
>> v2: fix white space errors
>> v3: change flags from hosting 2 8 bit numbers to holding a
>> i915_engine_class_instance struct
>> v4: add error if non rcs engine passed.
>> 
>> Cc: Ashutosh Dixit <ashutosh.dixit@intel.com>
>> Cc: Matt Roper <matthew.d.roper@intel.com>
>> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
>> UMD (mesa): https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14143
>> 
>> Signed-off-by: Matt Atwood <matthew.s.atwood@intel.com>
>> ---
>>  drivers/gpu/drm/i915/i915_query.c | 71 ++++++++++++++++++++++---------
>>  include/uapi/drm/i915_drm.h       | 26 +++++++----
>>  2 files changed, 69 insertions(+), 28 deletions(-)
>> 
>> diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
>> index b5ca00cb6cf6..32be84c95956 100644
>> --- a/drivers/gpu/drm/i915/i915_query.c
>> +++ b/drivers/gpu/drm/i915/i915_query.c
>> @@ -9,6 +9,7 @@
>>  #include "i915_drv.h"
>>  #include "i915_perf.h"
>>  #include "i915_query.h"
>> +#include "gt/intel_engine_user.h"
>>  #include <uapi/drm/i915_drm.h>
>>  
>>  static int copy_query_item(void *query_hdr, size_t query_sz,
>> @@ -28,36 +29,30 @@ static int copy_query_item(void *query_hdr, size_t query_sz,
>>  	return 0;
>>  }
>>  
>> -static int query_topology_info(struct drm_i915_private *dev_priv,
>> -			       struct drm_i915_query_item *query_item)
>> +static int fill_topology_info(const struct sseu_dev_info *sseu,
>> +			      struct drm_i915_query_item *query_item,
>> +			      const u8 *subslice_mask)
>>  {
>> -	const struct sseu_dev_info *sseu = &to_gt(dev_priv)->info.sseu;
>>  	struct drm_i915_query_topology_info topo;
>>  	u32 slice_length, subslice_length, eu_length, total_length;
>>  	int ret;
>>  
>> -	if (query_item->flags != 0)
>> -		return -EINVAL;
>> +	BUILD_BUG_ON(sizeof(u8) != sizeof(sseu->slice_mask));
>>  
>>  	if (sseu->max_slices == 0)
>>  		return -ENODEV;
>>  
>> -	BUILD_BUG_ON(sizeof(u8) != sizeof(sseu->slice_mask));
>> -
>>  	slice_length = sizeof(sseu->slice_mask);
>>  	subslice_length = sseu->max_slices * sseu->ss_stride;
>>  	eu_length = sseu->max_slices * sseu->max_subslices * sseu->eu_stride;
>>  	total_length = sizeof(topo) + slice_length + subslice_length +
>>  		       eu_length;
>>  
>> -	ret = copy_query_item(&topo, sizeof(topo), total_length,
>> -			      query_item);
>> +	ret = copy_query_item(&topo, sizeof(topo), total_length, query_item);
>> +
>>  	if (ret != 0)
>>  		return ret;
>>  
>> -	if (topo.flags != 0)
>> -		return -EINVAL;
>> -
>>  	memset(&topo, 0, sizeof(topo));
>>  	topo.max_slices = sseu->max_slices;
>>  	topo.max_subslices = sseu->max_subslices;
>> @@ -69,27 +64,64 @@ static int query_topology_info(struct drm_i915_private *dev_priv,
>>  	topo.eu_stride = sseu->eu_stride;
>>  
>>  	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr),
>> -			   &topo, sizeof(topo)))
>> +			 &topo, sizeof(topo)))
>>  		return -EFAULT;
>>  
>>  	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr + sizeof(topo)),
>> -			   &sseu->slice_mask, slice_length))
>> +			 &sseu->slice_mask, slice_length))
>>  		return -EFAULT;
>>  
>>  	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr +
>> -					   sizeof(topo) + slice_length),
>> -			   sseu->subslice_mask, subslice_length))
>> +					 sizeof(topo) + slice_length),
>> +			 subslice_mask, subslice_length))
>>  		return -EFAULT;
>>  
>>  	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr +
>> -					   sizeof(topo) +
>> -					   slice_length + subslice_length),
>> -			   sseu->eu_mask, eu_length))
>> +					 sizeof(topo) +
>> +					 slice_length + subslice_length),
>> +			 sseu->eu_mask, eu_length))
>>  		return -EFAULT;
>>  
>>  	return total_length;
>>  }
>>  
>> +static int query_topology_info(struct drm_i915_private *dev_priv,
>> +			       struct drm_i915_query_item *query_item)
>> +{
>> +	const struct sseu_dev_info *sseu = &to_gt(dev_priv)->info.sseu;
>> +
>> +	if (query_item->flags != 0)
>> +		return -EINVAL;
>> +
>> +	return fill_topology_info(sseu, query_item, sseu->subslice_mask);
>> +}
>> +
>> +static int query_geometry_subslices(struct drm_i915_private *i915,
>> +				    struct drm_i915_query_item *query_item)
>> +{
>> +	const struct sseu_dev_info *sseu;
>> +	struct intel_engine_cs *engine;
>> +	struct i915_engine_class_instance classinstance;
>> +
>> +	if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 50))
>> +		return -ENODEV;
>> +
>> +	classinstance = *((struct i915_engine_class_instance *)&query_item->flags);
>> +
>> +	engine = intel_engine_lookup_user(i915, (u8) classinstance.engine_class,
>> +					  (u8) classinstance.engine_instance);
>> +
>> +	if (!engine)
>> +		return -EINVAL;
>> +
>> +	if (engine->class != RENDER_CLASS)
>> +		return -EINVAL;
>> +
>> +	sseu = &engine->gt->info.sseu;
>> +
>> +	return fill_topology_info(sseu, query_item, sseu->geometry_subslice_mask);
>> +}
>> +
>>  static int
>>  query_engine_info(struct drm_i915_private *i915,
>>  		  struct drm_i915_query_item *query_item)
>> @@ -508,6 +540,7 @@ static int (* const i915_query_funcs[])(struct drm_i915_private *dev_priv,
>>  	query_perf_config,
>>  	query_memregion_info,
>>  	query_hwconfig_blob,
>> +	query_geometry_subslices,
>>  };
>>  
>>  int i915_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
>> diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
>> index 9ab021c4d632..c2a18afcf791 100644
>> --- a/include/uapi/drm/i915_drm.h
>> +++ b/include/uapi/drm/i915_drm.h
>> @@ -2690,11 +2690,12 @@ struct drm_i915_perf_oa_config {
>>  struct drm_i915_query_item {
>>  	/** @query_id: The id for this query */
>>  	__u64 query_id;
>> -#define DRM_I915_QUERY_TOPOLOGY_INFO    1
>> -#define DRM_I915_QUERY_ENGINE_INFO	2
>> -#define DRM_I915_QUERY_PERF_CONFIG      3
>> -#define DRM_I915_QUERY_MEMORY_REGIONS   4
>> -#define DRM_I915_QUERY_HWCONFIG_BLOB	5
>> +#define DRM_I915_QUERY_TOPOLOGY_INFO		1
>> +#define DRM_I915_QUERY_ENGINE_INFO		2
>> +#define DRM_I915_QUERY_PERF_CONFIG		3
>> +#define DRM_I915_QUERY_MEMORY_REGIONS		4
>> +#define DRM_I915_QUERY_HWCONFIG_BLOB		5
>> +#define DRM_I915_QUERY_GEOMETRY_SUBSLICES	6
>>  /* Must be kept compact -- no holes and well documented */
>>  
>>  	/**
>> @@ -2718,6 +2719,9 @@ struct drm_i915_query_item {
>>  	 *	- DRM_I915_QUERY_PERF_CONFIG_LIST
>>  	 *      - DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID
>>  	 *      - DRM_I915_QUERY_PERF_CONFIG_FOR_UUID
>> +	 *
>> +	 * When query_id == DRM_I915_QUERY_GEOMETRY_SUBSLICES must have a valid
>> +	 * i915_engine_class_instance struct.

It would also be worth adding to the documentation that the specified engine
must be a render engine instance.

>>  	 */
>>  	__u32 flags;
>>  #define DRM_I915_QUERY_PERF_CONFIG_LIST          1
>> @@ -2776,16 +2780,20 @@ struct drm_i915_query {
>>  };
>>  
>>  /*
>
> Can we please include this in the kerneldoc, and also make sure that the
> queries are nicely all listed somewhere and link to each respective
> information structure?
>
> Most of the doc for queries is there now, but the presentation and linking
> lacks still a lot.
> -Daniel
>
>> - * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO :
>> + * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO,
>> + * DRM_I915_QUERY_GEOMETRY_SUBSLICE:
>>   *
>>   * data: contains the 3 pieces of information :
>>   *
>> - * - the slice mask with one bit per slice telling whether a slice is
>> - *   available. The availability of slice X can be queried with the following
>> - *   formula :
>> + * - For DRM_I915_QUERY_TOPOLOGY_INFO the slice mask with one bit per slice
>> + *   telling whether a slice is available. The availability of slice X can be
>> + *   queried with the following formula :
>>   *
>>   *           (data[X / 8] >> (X % 8)) & 1
>>   *
>> + * - For DRM_I915_QUERY_GEOMETRY_SUBSLICES Slices are equal to 1 and this field
>> + *   is not used.
>> + *
>>   * - the subslice mask for each slice with one bit per subslice telling
>>   *   whether a subslice is available. Gen12 has dual-subslices, which are
>>   *   similar to two gen11 subslices. For gen12, this array represents dual-
>> -- 
>> 2.21.3
>> 
>
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch
Matt Roper April 12, 2022, 12:13 a.m. UTC | #3
On Fri, Apr 01, 2022 at 03:19:26PM -0700, Francisco Jerez wrote:
> Daniel Vetter <daniel@ffwll.ch> writes:
> 
> > On Wed, Mar 30, 2022 at 02:53:11PM -0700, Matt Atwood wrote:
...
> >> @@ -2718,6 +2719,9 @@ struct drm_i915_query_item {
> >>  	 *	- DRM_I915_QUERY_PERF_CONFIG_LIST
> >>  	 *      - DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID
> >>  	 *      - DRM_I915_QUERY_PERF_CONFIG_FOR_UUID
> >> +	 *
> >> +	 * When query_id == DRM_I915_QUERY_GEOMETRY_SUBSLICES must have a valid
> >> +	 * i915_engine_class_instance struct.
> 
> It would also be worth adding to the documentation that the specified engine
> must be a render engine instance.
> 
> >>  	 */
> >>  	__u32 flags;
> >>  #define DRM_I915_QUERY_PERF_CONFIG_LIST          1
> >> @@ -2776,16 +2780,20 @@ struct drm_i915_query {
> >>  };
> >>  
> >>  /*
> >
> > Can we please include this in the kerneldoc, and also make sure that the
> > queries are nicely all listed somewhere and link to each respective
> > information structure?
> >
> > Most of the doc for queries is there now, but the presentation and linking
> > lacks still a lot.
> > -Daniel

MattA is out at the moment, so I've picked this up in his absence; I
sent a new series here that includes various kerneldoc updates in
addition to his patch:

   https://patchwork.freedesktop.org/series/102553/

Let me know if that's more along the lines of what you guys were looking
for.


Matt

> >
> >> - * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO :
> >> + * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO,
> >> + * DRM_I915_QUERY_GEOMETRY_SUBSLICE:
> >>   *
> >>   * data: contains the 3 pieces of information :
> >>   *
> >> - * - the slice mask with one bit per slice telling whether a slice is
> >> - *   available. The availability of slice X can be queried with the following
> >> - *   formula :
> >> + * - For DRM_I915_QUERY_TOPOLOGY_INFO the slice mask with one bit per slice
> >> + *   telling whether a slice is available. The availability of slice X can be
> >> + *   queried with the following formula :
> >>   *
> >>   *           (data[X / 8] >> (X % 8)) & 1
> >>   *
> >> + * - For DRM_I915_QUERY_GEOMETRY_SUBSLICES Slices are equal to 1 and this field
> >> + *   is not used.
> >> + *
> >>   * - the subslice mask for each slice with one bit per subslice telling
> >>   *   whether a subslice is available. Gen12 has dual-subslices, which are
> >>   *   similar to two gen11 subslices. For gen12, this array represents dual-
> >> -- 
> >> 2.21.3
> >> 
> >
> > -- 
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > http://blog.ffwll.ch
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
index b5ca00cb6cf6..32be84c95956 100644
--- a/drivers/gpu/drm/i915/i915_query.c
+++ b/drivers/gpu/drm/i915/i915_query.c
@@ -9,6 +9,7 @@ 
 #include "i915_drv.h"
 #include "i915_perf.h"
 #include "i915_query.h"
+#include "gt/intel_engine_user.h"
 #include <uapi/drm/i915_drm.h>
 
 static int copy_query_item(void *query_hdr, size_t query_sz,
@@ -28,36 +29,30 @@  static int copy_query_item(void *query_hdr, size_t query_sz,
 	return 0;
 }
 
-static int query_topology_info(struct drm_i915_private *dev_priv,
-			       struct drm_i915_query_item *query_item)
+static int fill_topology_info(const struct sseu_dev_info *sseu,
+			      struct drm_i915_query_item *query_item,
+			      const u8 *subslice_mask)
 {
-	const struct sseu_dev_info *sseu = &to_gt(dev_priv)->info.sseu;
 	struct drm_i915_query_topology_info topo;
 	u32 slice_length, subslice_length, eu_length, total_length;
 	int ret;
 
-	if (query_item->flags != 0)
-		return -EINVAL;
+	BUILD_BUG_ON(sizeof(u8) != sizeof(sseu->slice_mask));
 
 	if (sseu->max_slices == 0)
 		return -ENODEV;
 
-	BUILD_BUG_ON(sizeof(u8) != sizeof(sseu->slice_mask));
-
 	slice_length = sizeof(sseu->slice_mask);
 	subslice_length = sseu->max_slices * sseu->ss_stride;
 	eu_length = sseu->max_slices * sseu->max_subslices * sseu->eu_stride;
 	total_length = sizeof(topo) + slice_length + subslice_length +
 		       eu_length;
 
-	ret = copy_query_item(&topo, sizeof(topo), total_length,
-			      query_item);
+	ret = copy_query_item(&topo, sizeof(topo), total_length, query_item);
+
 	if (ret != 0)
 		return ret;
 
-	if (topo.flags != 0)
-		return -EINVAL;
-
 	memset(&topo, 0, sizeof(topo));
 	topo.max_slices = sseu->max_slices;
 	topo.max_subslices = sseu->max_subslices;
@@ -69,27 +64,64 @@  static int query_topology_info(struct drm_i915_private *dev_priv,
 	topo.eu_stride = sseu->eu_stride;
 
 	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr),
-			   &topo, sizeof(topo)))
+			 &topo, sizeof(topo)))
 		return -EFAULT;
 
 	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr + sizeof(topo)),
-			   &sseu->slice_mask, slice_length))
+			 &sseu->slice_mask, slice_length))
 		return -EFAULT;
 
 	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr +
-					   sizeof(topo) + slice_length),
-			   sseu->subslice_mask, subslice_length))
+					 sizeof(topo) + slice_length),
+			 subslice_mask, subslice_length))
 		return -EFAULT;
 
 	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr +
-					   sizeof(topo) +
-					   slice_length + subslice_length),
-			   sseu->eu_mask, eu_length))
+					 sizeof(topo) +
+					 slice_length + subslice_length),
+			 sseu->eu_mask, eu_length))
 		return -EFAULT;
 
 	return total_length;
 }
 
+static int query_topology_info(struct drm_i915_private *dev_priv,
+			       struct drm_i915_query_item *query_item)
+{
+	const struct sseu_dev_info *sseu = &to_gt(dev_priv)->info.sseu;
+
+	if (query_item->flags != 0)
+		return -EINVAL;
+
+	return fill_topology_info(sseu, query_item, sseu->subslice_mask);
+}
+
+static int query_geometry_subslices(struct drm_i915_private *i915,
+				    struct drm_i915_query_item *query_item)
+{
+	const struct sseu_dev_info *sseu;
+	struct intel_engine_cs *engine;
+	struct i915_engine_class_instance classinstance;
+
+	if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 50))
+		return -ENODEV;
+
+	classinstance = *((struct i915_engine_class_instance *)&query_item->flags);
+
+	engine = intel_engine_lookup_user(i915, (u8) classinstance.engine_class,
+					  (u8) classinstance.engine_instance);
+
+	if (!engine)
+		return -EINVAL;
+
+	if (engine->class != RENDER_CLASS)
+		return -EINVAL;
+
+	sseu = &engine->gt->info.sseu;
+
+	return fill_topology_info(sseu, query_item, sseu->geometry_subslice_mask);
+}
+
 static int
 query_engine_info(struct drm_i915_private *i915,
 		  struct drm_i915_query_item *query_item)
@@ -508,6 +540,7 @@  static int (* const i915_query_funcs[])(struct drm_i915_private *dev_priv,
 	query_perf_config,
 	query_memregion_info,
 	query_hwconfig_blob,
+	query_geometry_subslices,
 };
 
 int i915_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 9ab021c4d632..c2a18afcf791 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -2690,11 +2690,12 @@  struct drm_i915_perf_oa_config {
 struct drm_i915_query_item {
 	/** @query_id: The id for this query */
 	__u64 query_id;
-#define DRM_I915_QUERY_TOPOLOGY_INFO    1
-#define DRM_I915_QUERY_ENGINE_INFO	2
-#define DRM_I915_QUERY_PERF_CONFIG      3
-#define DRM_I915_QUERY_MEMORY_REGIONS   4
-#define DRM_I915_QUERY_HWCONFIG_BLOB	5
+#define DRM_I915_QUERY_TOPOLOGY_INFO		1
+#define DRM_I915_QUERY_ENGINE_INFO		2
+#define DRM_I915_QUERY_PERF_CONFIG		3
+#define DRM_I915_QUERY_MEMORY_REGIONS		4
+#define DRM_I915_QUERY_HWCONFIG_BLOB		5
+#define DRM_I915_QUERY_GEOMETRY_SUBSLICES	6
 /* Must be kept compact -- no holes and well documented */
 
 	/**
@@ -2718,6 +2719,9 @@  struct drm_i915_query_item {
 	 *	- DRM_I915_QUERY_PERF_CONFIG_LIST
 	 *      - DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID
 	 *      - DRM_I915_QUERY_PERF_CONFIG_FOR_UUID
+	 *
+	 * When query_id == DRM_I915_QUERY_GEOMETRY_SUBSLICES must have a valid
+	 * i915_engine_class_instance struct.
 	 */
 	__u32 flags;
 #define DRM_I915_QUERY_PERF_CONFIG_LIST          1
@@ -2776,16 +2780,20 @@  struct drm_i915_query {
 };
 
 /*
- * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO :
+ * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO,
+ * DRM_I915_QUERY_GEOMETRY_SUBSLICE:
  *
  * data: contains the 3 pieces of information :
  *
- * - the slice mask with one bit per slice telling whether a slice is
- *   available. The availability of slice X can be queried with the following
- *   formula :
+ * - For DRM_I915_QUERY_TOPOLOGY_INFO the slice mask with one bit per slice
+ *   telling whether a slice is available. The availability of slice X can be
+ *   queried with the following formula :
  *
  *           (data[X / 8] >> (X % 8)) & 1
  *
+ * - For DRM_I915_QUERY_GEOMETRY_SUBSLICES Slices are equal to 1 and this field
+ *   is not used.
+ *
  * - the subslice mask for each slice with one bit per subslice telling
  *   whether a subslice is available. Gen12 has dual-subslices, which are
  *   similar to two gen11 subslices. For gen12, this array represents dual-