Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: "K V P, Satyanarayana" <satyanarayana.k.v.p@intel.com>
To: <intel-xe@lists.freedesktop.org>
Subject: Re: [PATCH v5 1/4] drm/xe/guc: Split GuC ID manager into usable and shareable pools
Date: Tue, 6 Oct 2026 14:05:43 +0530	[thread overview]
Message-ID: <866ddae9-3df8-4bdc-a9bf-48efbb49135e@intel.com> (raw)
In-Reply-To: <20261005085132.3720685-2-piotr.piorkowski@intel.com>


On 05-Oct-26 2:21 PM, Piórkowski, Piotr wrote:
> From: Piotr Piórkowski <piotr.piorkowski@intel.com>
>
> Modify the GuC identifier manager so that it distinguishes between
> usable GuC IDs allocated for GuC submissions, and shareable those that
> can be shared with VFs. Both pools are represented as a single bitmap
> and may overlap.
> Let's Replace the single-pool accounting model with separate usable and
> shareable pools, add helpers for pool accounting and limits, and update
> debug reporting.
>
> For now, let's keep the current allocation behaviour by mapping both pools
> onto the same GuC ID space. This prepares the ID manager for separate
> management of submission IDs and VF allocations in following changes.
>
> v2: Do not change how VF IDs are allocated in the legacy path (Sashiko)
>
> v3: Fix shareable spare quota accounting to include
>      PF-exclusive usable IDs.
>
> v4: Do not apply spare quota to VF-exclusive shareable IDs (Sashiko)
>      Drop redundant checks and asserts (Satya)
>
> Assisted-by: Claude:claude-5-sonnet
> Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> ---
>   drivers/gpu/drm/xe/tests/xe_guc_id_mgr_test.c |  57 +--
>   drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c    |   2 +-
>   drivers/gpu/drm/xe/xe_guc_id_mgr.c            | 443 ++++++++++++++----
>   drivers/gpu/drm/xe/xe_guc_id_mgr.h            |  20 +-
>   drivers/gpu/drm/xe/xe_guc_types.h             |   8 +-
>   5 files changed, 405 insertions(+), 125 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/tests/xe_guc_id_mgr_test.c b/drivers/gpu/drm/xe/tests/xe_guc_id_mgr_test.c
> index ee30a1939eb0e..78d3de46b7572 100644
> --- a/drivers/gpu/drm/xe/tests/xe_guc_id_mgr_test.c
> +++ b/drivers/gpu/drm/xe/tests/xe_guc_id_mgr_test.c
> @@ -24,8 +24,8 @@ static void bad_init(struct kunit *test)
>   {
>   	struct xe_guc_id_mgr *idm = test->priv;
>   
> -	KUNIT_EXPECT_EQ(test, -EINVAL, xe_guc_id_mgr_init(idm, 0));
> -	KUNIT_EXPECT_EQ(test, -ERANGE, xe_guc_id_mgr_init(idm, GUC_ID_MAX + 1));
> +	KUNIT_EXPECT_EQ(test, -EINVAL, idm_init(idm, 0, 0));
> +	KUNIT_EXPECT_EQ(test, -ERANGE, idm_init(idm, GUC_ID_MAX + 1, 0));
>   }
>   
>   static void no_init(struct kunit *test)
> @@ -43,12 +43,12 @@ static void init_fini(struct kunit *test)
>   {
>   	struct xe_guc_id_mgr *idm = test->priv;
>   
> -	KUNIT_ASSERT_EQ(test, 0, xe_guc_id_mgr_init(idm, -1));
> +	KUNIT_ASSERT_EQ(test, 0, idm_init(idm, GUC_ID_MAX, 0));
>   	KUNIT_EXPECT_NOT_NULL(test, idm->bitmap);
> -	KUNIT_EXPECT_EQ(test, idm->total, GUC_ID_MAX);
> +	KUNIT_EXPECT_EQ(test, idm_total(idm), GUC_ID_MAX);
>   	__fini_idm(NULL, idm);
>   	KUNIT_EXPECT_NULL(test, idm->bitmap);
> -	KUNIT_EXPECT_EQ(test, idm->total, 0);
> +	KUNIT_EXPECT_EQ(test, idm_total(idm), 0);
>   }
>   
>   static void check_used(struct kunit *test)
> @@ -56,19 +56,19 @@ static void check_used(struct kunit *test)
>   	struct xe_guc_id_mgr *idm = test->priv;
>   	unsigned int n;
>   
> -	KUNIT_ASSERT_EQ(test, 0, xe_guc_id_mgr_init(idm, 2));
> +	KUNIT_ASSERT_EQ(test, 0, idm_init(idm, 2, 0));
>   
>   	mutex_lock(idm_mutex(idm));
>   
> -	for (n = 0; n < idm->total; n++) {
> +	for (n = 0; n < idm_total(idm); n++) {
>   		kunit_info(test, "n=%u", n);
> -		KUNIT_EXPECT_EQ(test, idm->used, n);
> -		KUNIT_EXPECT_GE(test, idm_reserve_chunk_locked(idm, 1, 0), 0);
> -		KUNIT_EXPECT_EQ(test, idm->used, n + 1);
> +		KUNIT_EXPECT_EQ(test, bitmap_weight(idm->bitmap, idm_total(idm)), n);
> +		KUNIT_EXPECT_GE(test, xe_guc_id_mgr_reserve_usable_locked(idm, 1), 0);
> +		KUNIT_EXPECT_EQ(test, bitmap_weight(idm->bitmap, idm_total(idm)), n + 1);
>   	}
> -	KUNIT_EXPECT_EQ(test, idm->used, idm->total);
> -	idm_release_chunk_locked(idm, 0, idm->used);
> -	KUNIT_EXPECT_EQ(test, idm->used, 0);
> +	KUNIT_EXPECT_EQ(test, bitmap_weight(idm->bitmap, idm_total(idm)), idm_total(idm));
> +	idm_release_chunk_locked(idm, 0, idm_total(idm));
> +	KUNIT_EXPECT_EQ(test, bitmap_weight(idm->bitmap, idm_total(idm)), 0);
>   
>   	mutex_unlock(idm_mutex(idm));
>   }
> @@ -76,25 +76,12 @@ static void check_used(struct kunit *test)
>   static void check_quota(struct kunit *test)
>   {
>   	struct xe_guc_id_mgr *idm = test->priv;
> -	unsigned int n;
> -
> -	KUNIT_ASSERT_EQ(test, 0, xe_guc_id_mgr_init(idm, 2));
>   
> -	mutex_lock(idm_mutex(idm));
> +	KUNIT_ASSERT_EQ(test, 0, idm_init(idm, 2, 0));
>   
> -	for (n = 0; n < idm->total - 1; n++) {
> -		kunit_info(test, "n=%u", n);
> -		KUNIT_EXPECT_EQ(test, idm_reserve_chunk_locked(idm, 1, idm->total), -EDQUOT);
> -		KUNIT_EXPECT_EQ(test, idm_reserve_chunk_locked(idm, 1, idm->total - n), -EDQUOT);
> -		KUNIT_EXPECT_EQ(test, idm_reserve_chunk_locked(idm, idm->total - n, 1), -EDQUOT);
> -		KUNIT_EXPECT_GE(test, idm_reserve_chunk_locked(idm, 1, 1), 0);
> -	}
> -	KUNIT_EXPECT_LE(test, 0, idm_reserve_chunk_locked(idm, 1, 0));
> -	KUNIT_EXPECT_EQ(test, idm->used, idm->total);
> -	idm_release_chunk_locked(idm, 0, idm->total);
> -	KUNIT_EXPECT_EQ(test, idm->used, 0);
> -
> -	mutex_unlock(idm_mutex(idm));
> +	KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_reserve_usable(idm, 2), 0);
> +	KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_reserve_usable(idm, 1), -ENOSPC);
> +	KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_usable(idm, 0, 2), 0);
>   }
>   
>   static void check_all(struct kunit *test)
> @@ -102,14 +89,14 @@ static void check_all(struct kunit *test)
>   	struct xe_guc_id_mgr *idm = test->priv;
>   	unsigned int n;
>   
> -	KUNIT_ASSERT_EQ(test, 0, xe_guc_id_mgr_init(idm, -1));
> +	KUNIT_ASSERT_EQ(test, 0, idm_init(idm, GUC_ID_MAX, 0));
>   
>   	mutex_lock(idm_mutex(idm));
>   
> -	for (n = 0; n < idm->total; n++)
> -		KUNIT_EXPECT_LE(test, 0, idm_reserve_chunk_locked(idm, 1, 0));
> -	KUNIT_EXPECT_EQ(test, idm->used, idm->total);
> -	for (n = 0; n < idm->total; n++)
> +	for (n = 0; n < idm_total(idm); n++)
> +		KUNIT_EXPECT_LE(test, 0, xe_guc_id_mgr_reserve_usable_locked(idm, 1));
> +	KUNIT_EXPECT_EQ(test, bitmap_weight(idm->bitmap, idm_total(idm)), idm_total(idm));
> +	for (n = 0; n < idm_total(idm); n++)
>   		idm_release_chunk_locked(idm, n, 1);
>   
>   	mutex_unlock(idm_mutex(idm));
> diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
> index 6947aeed458ed..de1ac58e31412 100644
> --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
> +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
> @@ -1182,7 +1182,7 @@ static u32 pf_estimate_fair_ctxs(struct xe_gt *gt, unsigned int num_vfs)
>   {
>   	struct xe_guc_id_mgr *idm = &gt->uc.guc.submission_state.idm;
>   	u32 spare = pf_get_spare_ctxs(gt);
> -	u32 fair = (idm->total - spare) / num_vfs;
> +	u32 fair = (xe_guc_id_mgr_max_usable(idm) - spare) / num_vfs;
>   	int ret;
>   
>   	for (; fair; --fair) {
> diff --git a/drivers/gpu/drm/xe/xe_guc_id_mgr.c b/drivers/gpu/drm/xe/xe_guc_id_mgr.c
> index e845425d670be..8f90a5337fe4c 100644
> --- a/drivers/gpu/drm/xe/xe_guc_id_mgr.c
> +++ b/drivers/gpu/drm/xe/xe_guc_id_mgr.c
> @@ -34,6 +34,34 @@ static struct xe_device *idm_to_xe(struct xe_guc_id_mgr *idm)
>   
>   static void idm_print_locked(struct xe_guc_id_mgr *idm, struct drm_printer *p, int indent);
>   
> +static unsigned int idm_total(struct xe_guc_id_mgr *idm)
> +{
> +	if (idm->usable > GUC_ID_MAX - idm->shareable)
> +		return GUC_ID_MAX;
> +
> +	return idm->usable + idm->shareable;
> +}
> +
> +static unsigned int idm_shareable_start(struct xe_guc_id_mgr *idm)
> +{
> +	return idm_total(idm) - idm->shareable;
> +}
> +
> +static unsigned int idm_used_usable(struct xe_guc_id_mgr *idm)
> +{
> +	lockdep_assert_held(idm_mutex(idm));
> +
> +	return bitmap_weight(idm->bitmap, idm->usable);
> +}
> +
> +static unsigned int idm_used_shareable(struct xe_guc_id_mgr *idm)
> +{
> +	lockdep_assert_held(idm_mutex(idm));
> +
> +	return bitmap_weight(idm->bitmap, idm_total(idm)) -
> +	       bitmap_weight(idm->bitmap, idm_shareable_start(idm));
> +}
> +
>   static void __fini_idm(struct drm_device *drm, void *arg)
>   {
>   	struct xe_guc_id_mgr *idm = arg;
> @@ -41,25 +69,56 @@ static void __fini_idm(struct drm_device *drm, void *arg)
>   	mutex_lock(idm_mutex(idm));
>   
>   	if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) {
> -		unsigned int weight = bitmap_weight(idm->bitmap, idm->total);
> +		unsigned int weight = bitmap_weight(idm->bitmap, idm_total(idm));
>   
>   		if (weight) {
>   			struct drm_printer p = xe_gt_info_printer(idm_to_gt(idm));
>   
>   			xe_gt_err(idm_to_gt(idm), "GUC ID manager unclean (%u/%u)\n",
> -				  weight, idm->total);
> +				  weight, idm_total(idm));
>   			idm_print_locked(idm, &p, 1);
>   		}
>   	}
>   
>   	bitmap_free(idm->bitmap);
>   	idm->bitmap = NULL;
> -	idm->total = 0;
> -	idm->used = 0;
> +	idm->usable = 0;
> +	idm->shareable = 0;
>   
>   	mutex_unlock(idm_mutex(idm));
>   }
>   
> +static int idm_init(struct xe_guc_id_mgr *idm, unsigned int usable, unsigned int shareable)
> +{
> +	bool overlap = usable > GUC_ID_MAX - shareable;
> +	unsigned int total;
> +	int ret;
> +
> +	if (!usable)
> +		return -EINVAL;
> +	if (usable > GUC_ID_MAX || shareable > GUC_ID_MAX)
> +		return -ERANGE;
> +
> +	idm_assert(idm, !idm->bitmap);
> +	idm_assert(idm, !shareable || IS_SRIOV_PF(idm_to_xe(idm)));
> +	total = overlap ? GUC_ID_MAX : usable + shareable;
> +
> +	idm->bitmap = bitmap_zalloc(total, GFP_KERNEL);
> +	if (!idm->bitmap)
> +		return -ENOMEM;
> +
> +	idm->usable = usable;
> +	idm->shareable = shareable;
> +
> +	ret = drmm_add_action_or_reset(&idm_to_xe(idm)->drm, __fini_idm, idm);
> +	if (ret)
> +		return ret;
> +
> +	xe_gt_dbg(idm_to_gt(idm), "using %u GuC ID%s, %u GuC ID%s shareable with VFs\n",
> +		  idm->usable, str_plural(idm->usable), idm->shareable, str_plural(idm->shareable));
> +	return 0;
> +}
> +
>   /**
>    * xe_guc_id_mgr_init() - Initialize GuC context ID Manager.
>    * @idm: the &xe_guc_id_mgr to initialize
> @@ -68,90 +127,156 @@ static void __fini_idm(struct drm_device *drm, void *arg)
>    * The bare-metal or PF driver can pass ~0 as &limit to indicate that all
>    * context IDs supported by the GuC firmware are available for use.
>    *
> - * Only VF drivers will have to provide explicit number of context IDs
> - * that they can use.
> - *
>    * Return: 0 on success or a negative error code on failure.
>    */
>   int xe_guc_id_mgr_init(struct xe_guc_id_mgr *idm, unsigned int limit)
>   {
> -	int ret;
> -
> -	idm_assert(idm, !idm->bitmap);
> -	idm_assert(idm, !idm->total);
> -	idm_assert(idm, !idm->used);
> -
>   	if (limit == ~0)
>   		limit = GUC_ID_MAX;
> -	else if (limit > GUC_ID_MAX)
> -		return -ERANGE;
> -	else if (!limit)
> -		return -EINVAL;
>   
> -	idm->bitmap = bitmap_zalloc(limit, GFP_KERNEL);
> -	if (!idm->bitmap)
> -		return -ENOMEM;
> -	idm->total = limit;
> +	return idm_init(idm, limit, 0);
> +}
>   
> -	ret = drmm_add_action_or_reset(&idm_to_xe(idm)->drm, __fini_idm, idm);
> -	if (ret)
> -		return ret;
> +/**
> + * xe_guc_id_mgr_max_usable() - Get maximum number of usable GuC context IDs.
> + * @idm: the &xe_guc_id_mgr to query
> + *
> + * Return: maximum number of GuC context IDs that can be used by @idm for GuC submission.
> + */
> +unsigned int xe_guc_id_mgr_max_usable(struct xe_guc_id_mgr *idm)
> +{
> +	return idm->usable;
> +}
>   
> -	xe_gt_dbg(idm_to_gt(idm), "using %u GuC ID%s\n",
> -		  idm->total, str_plural(idm->total));
> -	return 0;
> +/**
> + * xe_guc_id_mgr_max_shareable() - Get maximum number of shareable GuC context IDs.
> + * @idm: the &xe_guc_id_mgr to query
> + *
> + * Return: maximum number of GuC context IDs that can be shared with VFs.
> + */
> +unsigned int xe_guc_id_mgr_max_shareable(struct xe_guc_id_mgr *idm)
> +{
> +	return idm->shareable;
>   }
>   
> -static unsigned int find_last_zero_area(unsigned long *bitmap,
> -					unsigned int total,
> -					unsigned int count)
> +static int idm_reserve_chunk_usable_locked(struct xe_guc_id_mgr *idm, unsigned int count)
> +{
> +	int id;
> +
> +	idm_assert(idm, count);
> +	lockdep_assert_held(idm_mutex(idm));
> +
> +	if (!idm->usable)
> +		return -ENODATA;
> +
> +	id = bitmap_find_next_zero_area(idm->bitmap, idm->usable, 0, count, 0);
> +	if (id >= idm->usable)
> +		return -ENOSPC;
> +
> +	bitmap_set(idm->bitmap, id, count);
> +
> +	return id;
> +}
> +
> +static unsigned int idm_find_last_zero_area_in_range(unsigned long *bitmap,
> +						     unsigned int range_start,
> +						     unsigned int range_end,
> +						     unsigned int count)
>   {
> -	unsigned int found = total;
> -	unsigned int rs, re, range;
> +	unsigned int found = range_end;
> +	unsigned int rs, re;
> +
> +	for_each_clear_bitrange(rs, re, bitmap, range_end) {
> +		unsigned int start = max(rs, range_start);
> +		unsigned int end = min(re, range_end);
> +		unsigned int range;
>   
> -	for_each_clear_bitrange(rs, re, bitmap, total) {
> -		range = re - rs;
> +		if (start >= end)
> +			continue;
> +
> +		range = end - start;
>   		if (range < count)
>   			continue;
> -		found = rs + (range - count);
> +
> +		found = start + (range - count);
>   	}
> +
>   	return found;
>   }
>   
> -static int idm_reserve_chunk_locked(struct xe_guc_id_mgr *idm,
> -				    unsigned int count, unsigned int retain)
> +static int idm_reserve_chunk_shareable_locked(struct xe_guc_id_mgr *idm, unsigned int count,
> +					      unsigned int spare)
>   {
> +	unsigned int shareable_start = idm_shareable_start(idm);
> +	unsigned int total = idm_total(idm);
>   	int id;
>   
>   	idm_assert(idm, count);
>   	lockdep_assert_held(idm_mutex(idm));
>   
> -	if (!idm->total)
> +	if (!idm->shareable)
>   		return -ENODATA;
>   
> -	if (retain) {
> +	if (shareable_start < idm->usable) {
>   		/*
> -		 * For IDs reservations (used on PF for VFs) we want to make
> -		 * sure there will be at least 'retain' available for the PF
> +		 * Spare is meaningful only for IDs that are shared between usable and
> +		 * shareable pools. For non-overlapping pools, shareable reservations do
> +		 * not reduce PF usable capacity, so there is nothing to retain.
>   		 */
> -		if (idm->used + count + retain > idm->total)
> -			return -EDQUOT;
> +		id = idm_find_last_zero_area_in_range(idm->bitmap, shareable_start, total, count);
> +		if (id >= total)
> +			return -ENOSPC;
> +
>   		/*
> -		 * ... and we want to reserve highest IDs close to the end.
> +		 * Only IDs taken from the overlapping part reduce PF usable capacity,
> +		 * so a chunk located entirely in the VF-exclusive part is never limited
> +		 * by the spare.
>   		 */
> -		id = find_last_zero_area(idm->bitmap, idm->total, count);
> +		if (spare && id < idm->usable) {
> +			unsigned int used_usable = bitmap_weight(idm->bitmap, idm->usable);
> +			unsigned int need_overlap = min(id + count, idm->usable) - id;
> +
> +			if (used_usable + need_overlap + spare > idm->usable)
> +				return -EDQUOT;
Can we write a helper to check these limits and return error?
> +		}
>   	} else {
> -		/*
> -		 * For regular IDs reservations (used by submission code)
> -		 * we start searching from the lower range of IDs.
> -		 */
> -		id = bitmap_find_next_zero_area(idm->bitmap, idm->total, 0, count, 0);
> +		id = bitmap_find_next_zero_area(idm->bitmap, total, shareable_start, count, 0);
> +		if (id + count > total)
> +			return -ENOSPC;
Same as above.
> +	}
> +
> +	bitmap_set(idm->bitmap, id, count);
> +
> +	return id;
> +}
> +
> +static int idm_reserve_chunk_locked(struct xe_guc_id_mgr *idm, unsigned int count,
> +				    unsigned int retain)
> +{
> +	unsigned int total = idm_total(idm);
> +	int id;
> +
> +	idm_assert(idm, count);
> +	lockdep_assert_held(idm_mutex(idm));
> +
> +	if (!total)
> +		return -ENODATA;
> +
> +	if (retain) {
> +		unsigned int used = bitmap_weight(idm->bitmap, total);
> +
> +		if (used + count + retain > total)
> +			return -EDQUOT;
Same as above.
> +
> +		id = idm_find_last_zero_area_in_range(idm->bitmap, 0, total, count);
> +	} else {
> +		id = bitmap_find_next_zero_area(idm->bitmap, total, 0, count, 0);
>   	}
> -	if (id >= idm->total)
> +
> +	if (id >= total)
>   		return -ENOSPC;

Same as above.

Otherwise LGTM.

-Satya.

>   
>   	bitmap_set(idm->bitmap, id, count);
> -	idm->used += count;
>   
>   	return id;
>   }
> @@ -160,9 +285,8 @@ static void idm_release_chunk_locked(struct xe_guc_id_mgr *idm,
>   				     unsigned int start, unsigned int count)
>   {
>   	idm_assert(idm, count);
> -	idm_assert(idm, count <= idm->used);
> -	idm_assert(idm, start < idm->total);
> -	idm_assert(idm, start + count - 1 < idm->total);
> +	idm_assert(idm, start < idm_total(idm));
> +	idm_assert(idm, start + count - 1 < idm_total(idm));
>   	lockdep_assert_held(idm_mutex(idm));
>   
>   	if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) {
> @@ -172,22 +296,61 @@ static void idm_release_chunk_locked(struct xe_guc_id_mgr *idm,
>   			idm_assert(idm, test_bit(start + n, idm->bitmap));
>   	}
>   	bitmap_clear(idm->bitmap, start, count);
> -	idm->used -= count;
> +}
> +
> +static int idm_release_chunk_in_range_locked(struct xe_guc_id_mgr *idm,
> +					     unsigned int start,
> +					     unsigned int count,
> +					     unsigned int range_start,
> +					     unsigned int range_end)
> +{
> +	lockdep_assert_held(idm_mutex(idm));
> +
> +	if (!count)
> +		return -EINVAL;
> +
> +	if (start < range_start || start >= range_end)
> +		return -ERANGE;
> +
> +	if (count > range_end - start)
> +		return -ERANGE;
> +
> +	idm_release_chunk_locked(idm, start, count);
> +
> +	return 0;
>   }
>   
>   /**
> - * xe_guc_id_mgr_reserve_locked() - Reserve one or more GuC context IDs.
> + * xe_guc_id_mgr_reserve_usable_locked() - Reserve one or more usable GuC context IDs.
>    * @idm: the &xe_guc_id_mgr
> - * @count: number of IDs to allocate (can't be 0)
> + * @count: number of usable GuC context IDs to reserve (can't be 0)
>    *
> - * This function is dedicated for the use by the GuC submission code,
> - * where submission lock is already taken.
> + * This function is dedicated for use by the GuC submission code when the
> + * submission lock is already held.
>    *
>    * Return: ID of allocated GuC context or a negative error code on failure.
>    */
> -int xe_guc_id_mgr_reserve_locked(struct xe_guc_id_mgr *idm, unsigned int count)
> +int xe_guc_id_mgr_reserve_usable_locked(struct xe_guc_id_mgr *idm, unsigned int count)
>   {
> -	return idm_reserve_chunk_locked(idm, count, 0);
> +	return idm_reserve_chunk_usable_locked(idm, count);
> +}
> +
> +/**
> + * xe_guc_id_mgr_reserve_shareable_locked() - Reserve one or more shareable GuC context IDs.
> + * @idm: the &xe_guc_id_mgr
> + * @count: number of shareable GuC context IDs to reserve (can't be 0)
> + * @spare: number of usable IDs to keep available for the PF
> + *
> + * This function is dedicated for use by the PF driver, which expects the
> + * reserved range of IDs to be contiguous. The function expects that the
> + * caller has already taken the lock.
> + *
> + * Return: ID of allocated GuC context or a negative error code on failure.
> + */
> +int xe_guc_id_mgr_reserve_shareable_locked(struct xe_guc_id_mgr *idm, unsigned int count,
> +					   unsigned int spare)
> +{
> +	return idm_reserve_chunk_shareable_locked(idm, count, spare);
>   }
>   
>   /**
> @@ -206,60 +369,175 @@ void xe_guc_id_mgr_release_locked(struct xe_guc_id_mgr *idm, unsigned int id,
>   }
>   
>   /**
> - * xe_guc_id_mgr_reserve() - Reserve a range of GuC context IDs.
> + * xe_guc_id_mgr_release_usable_locked() - Release one or more usable GuC context IDs.
> + * @idm: the &xe_guc_id_mgr
> + * @id: the first usable GuC context ID to release
> + * @count: number of usable GuC context IDs to release
> + *
> + * This function is dedicated for use by the GuC submission code when the
> + * submission lock is already held.
> + *
> + * Return: 0 on success, or a negative error code on failure.
> + */
> +int xe_guc_id_mgr_release_usable_locked(struct xe_guc_id_mgr *idm, unsigned int id,
> +					unsigned int count)
> +{
> +	return idm_release_chunk_in_range_locked(idm, id, count, 0, idm->usable);
> +}
> +
> +/**
> + * xe_guc_id_mgr_release_shareable_locked() - Release one or more shareable GuC context IDs.
>    * @idm: the &xe_guc_id_mgr
> - * @count: number of GuC context IDs to reserve (can't be 0)
> - * @retain: number of GuC context IDs to keep available (can't be 0)
> + * @id: the first shareable GuC context ID to release
> + * @count: number of shareable GuC context IDs to release
>    *
> - * This function is dedicated for the use by the PF driver which expects that
> - * reserved range of IDs will be contiguous and that there will be at least
> - * &retain IDs still available for the PF after this reservation.
> + * Return: 0 on success, or a negative error code on failure.
> + */
> +int xe_guc_id_mgr_release_shareable_locked(struct xe_guc_id_mgr *idm, unsigned int id,
> +					   unsigned int count)
> +{
> +	return idm_release_chunk_in_range_locked(idm, id, count,
> +						 idm_shareable_start(idm), idm_total(idm));
> +}
> +
> +/**
> + * xe_guc_id_mgr_reserve_usable() - Reserve one or more usable GuC context IDs.
> + * @idm: the &xe_guc_id_mgr
> + * @count: number of usable GuC context IDs to reserve (can't be 0)
> + *
> + * Return: ID of allocated GuC context or a negative error code on failure.
> + */
> +int xe_guc_id_mgr_reserve_usable(struct xe_guc_id_mgr *idm, unsigned int count)
> +{
> +	guard(mutex)(idm_mutex(idm));
> +
> +	idm_assert(idm, count);
> +
> +	return idm_reserve_chunk_usable_locked(idm, count);
> +}
> +
> +/**
> + * xe_guc_id_mgr_reserve_shareable() - Reserve one or more shareable GuC context IDs for VFs.
> + * @idm: the &xe_guc_id_mgr
> + * @count: number of shareable GuC context IDs to reserve (can't be 0)
> + * @spare: number of usable IDs to keep available for the PF
> + *
> + * This function is dedicated for use by the PF driver, which expects the
> + * reserved range of IDs to be contiguous.
>    *
>    * Return: starting ID of the allocated GuC context ID range or
>    *         a negative error code on failure.
>    */
> -int xe_guc_id_mgr_reserve(struct xe_guc_id_mgr *idm,
> -			  unsigned int count, unsigned int retain)
> +int xe_guc_id_mgr_reserve_shareable(struct xe_guc_id_mgr *idm, unsigned int count,
> +				    unsigned int spare)
> +{
> +	guard(mutex)(idm_mutex(idm));
> +
> +	idm_assert(idm, count);
> +
> +	return idm_reserve_chunk_shareable_locked(idm, count, spare);
> +}
> +
> +int xe_guc_id_mgr_reserve_locked(struct xe_guc_id_mgr *idm, unsigned int count)
> +{
> +	return idm_reserve_chunk_locked(idm, count, 0);
> +}
> +
> +int xe_guc_id_mgr_reserve(struct xe_guc_id_mgr *idm, unsigned int count,
> +			  unsigned int retain)
>   {
>   	int ret;
>   
>   	idm_assert(idm, count);
>   	idm_assert(idm, retain);
>   
> -	mutex_lock(idm_mutex(idm));
> +	guard(mutex)(idm_mutex(idm));
>   	ret = idm_reserve_chunk_locked(idm, count, retain);
> -	mutex_unlock(idm_mutex(idm));
>   
>   	return ret;
>   }
>   
>   /**
> - * xe_guc_id_mgr_release() - Release a range of GuC context IDs.
> + * xe_guc_id_mgr_release() - Release one or more GuC context IDs.
>    * @idm: the &xe_guc_id_mgr
> - * @start: the starting ID of GuC context range to release
> + * @start: the first GuC context ID to release
>    * @count: number of GuC context IDs to release
>    */
>   void xe_guc_id_mgr_release(struct xe_guc_id_mgr *idm,
>   			   unsigned int start, unsigned int count)
>   {
> -	mutex_lock(idm_mutex(idm));
> +	guard(mutex)(idm_mutex(idm));
> +
>   	idm_release_chunk_locked(idm, start, count);
> -	mutex_unlock(idm_mutex(idm));
>   }
>   
> -static void idm_print_locked(struct xe_guc_id_mgr *idm, struct drm_printer *p, int indent)
> +/**
> + * xe_guc_id_mgr_release_usable() - Release one or more usable GuC context IDs.
> + * @idm: the &xe_guc_id_mgr
> + * @id: the first usable GuC context ID to release
> + * @count: number of usable GuC context IDs to release
> + *
> + * Return: 0 on success, or a negative error code on failure.
> + */
> +int xe_guc_id_mgr_release_usable(struct xe_guc_id_mgr *idm, unsigned int id, unsigned int count)
> +{
> +	guard(mutex)(idm_mutex(idm));
> +
> +	return xe_guc_id_mgr_release_usable_locked(idm, id, count);
> +}
> +
> +/**
> + * xe_guc_id_mgr_release_shareable() - Release one or more shareable GuC context IDs.
> + * @idm: the &xe_guc_id_mgr
> + * @id: the first shareable GuC context ID to release
> + * @count: number of shareable GuC context IDs to release
> + *
> + * Return: 0 on success, or a negative error code on failure.
> + */
> +int xe_guc_id_mgr_release_shareable(struct xe_guc_id_mgr *idm, unsigned int id,
> +				    unsigned int count)
> +{
> +	guard(mutex)(idm_mutex(idm));
> +
> +	return xe_guc_id_mgr_release_shareable_locked(idm, id, count);
> +}
> +
> +static void idm_print_range_locked(struct xe_guc_id_mgr *idm,
> +				   struct drm_printer *p,
> +				   int indent,
> +				   const char *name,
> +				   unsigned int range_start,
> +				   unsigned int range_end,
> +				   unsigned int used)
>   {
>   	unsigned int rs, re;
>   
>   	lockdep_assert_held(idm_mutex(idm));
>   
> -	drm_printf_indent(p, indent, "total %u\n", idm->total);
> +	drm_printf_indent(p, indent, "%s used %u\n", name, used);
> +	for_each_set_bitrange(rs, re, idm->bitmap, range_end) {
> +		rs = max(rs, range_start);
> +		re = min(re, range_end);
> +
> +		if (rs < re)
> +			drm_printf_indent(p, indent, "%s range %u..%u (%u)\n",
> +					  name, rs, re - 1, re - rs);
> +	}
> +}
> +
> +static void idm_print_locked(struct xe_guc_id_mgr *idm, struct drm_printer *p, int indent)
> +{
> +	lockdep_assert_held(idm_mutex(idm));
> +
> +	drm_printf_indent(p, indent, "total %u\n", idm_total(idm));
>   	if (!idm->bitmap)
>   		return;
>   
> -	drm_printf_indent(p, indent, "used %u\n", idm->used);
> -	for_each_set_bitrange(rs, re, idm->bitmap, idm->total)
> -		drm_printf_indent(p, indent, "range %u..%u (%u)\n", rs, re - 1, re - rs);
> +	idm_print_range_locked(idm, p, indent, "usable", 0, idm->usable,
> +			       idm_used_usable(idm));
> +	idm_print_range_locked(idm, p, indent, "shareable",
> +			       idm_shareable_start(idm), idm_total(idm),
> +			       idm_used_shareable(idm));
>   }
>   
>   /**
> @@ -270,9 +548,8 @@ static void idm_print_locked(struct xe_guc_id_mgr *idm, struct drm_printer *p, i
>    */
>   void xe_guc_id_mgr_print(struct xe_guc_id_mgr *idm, struct drm_printer *p, int indent)
>   {
> -	mutex_lock(idm_mutex(idm));
> +	guard(mutex)(idm_mutex(idm));
>   	idm_print_locked(idm, p, indent);
> -	mutex_unlock(idm_mutex(idm));
>   }
>   
>   #if IS_BUILTIN(CONFIG_DRM_XE_KUNIT_TEST)
> diff --git a/drivers/gpu/drm/xe/xe_guc_id_mgr.h b/drivers/gpu/drm/xe/xe_guc_id_mgr.h
> index 368f8c80e4c7d..209f99831f1b4 100644
> --- a/drivers/gpu/drm/xe/xe_guc_id_mgr.h
> +++ b/drivers/gpu/drm/xe/xe_guc_id_mgr.h
> @@ -9,13 +9,29 @@
>   struct drm_printer;
>   struct xe_guc_id_mgr;
>   
> -int xe_guc_id_mgr_init(struct xe_guc_id_mgr *idm, unsigned int count);
> +int xe_guc_id_mgr_init(struct xe_guc_id_mgr *idm, unsigned int limit);
>   
> +unsigned int xe_guc_id_mgr_max_usable(struct xe_guc_id_mgr *idm);
> +unsigned int xe_guc_id_mgr_max_shareable(struct xe_guc_id_mgr *idm);
> +
> +int xe_guc_id_mgr_reserve_usable_locked(struct xe_guc_id_mgr *idm, unsigned int count);
> +int xe_guc_id_mgr_reserve_usable(struct xe_guc_id_mgr *idm, unsigned int count);
> +int xe_guc_id_mgr_reserve_shareable_locked(struct xe_guc_id_mgr *idm, unsigned int count,
> +					   unsigned int spare);
> +int xe_guc_id_mgr_reserve_shareable(struct xe_guc_id_mgr *idm, unsigned int count,
> +				    unsigned int spare);
>   int xe_guc_id_mgr_reserve_locked(struct xe_guc_id_mgr *idm, unsigned int count);
> +int xe_guc_id_mgr_reserve(struct xe_guc_id_mgr *idm, unsigned int count, unsigned int retain);
>   void xe_guc_id_mgr_release_locked(struct xe_guc_id_mgr *idm, unsigned int id, unsigned int count);
> +int xe_guc_id_mgr_release_usable_locked(struct xe_guc_id_mgr *idm, unsigned int id,
> +					unsigned int count);
> +int xe_guc_id_mgr_release_shareable_locked(struct xe_guc_id_mgr *idm, unsigned int id,
> +					   unsigned int count);
>   
> -int xe_guc_id_mgr_reserve(struct xe_guc_id_mgr *idm, unsigned int count, unsigned int retain);
>   void xe_guc_id_mgr_release(struct xe_guc_id_mgr *idm, unsigned int start, unsigned int count);
> +int xe_guc_id_mgr_release_usable(struct xe_guc_id_mgr *idm, unsigned int id, unsigned int count);
> +int xe_guc_id_mgr_release_shareable(struct xe_guc_id_mgr *idm, unsigned int id,
> +				    unsigned int count);
>   
>   void xe_guc_id_mgr_print(struct xe_guc_id_mgr *idm, struct drm_printer *p, int indent);
>   
> diff --git a/drivers/gpu/drm/xe/xe_guc_types.h b/drivers/gpu/drm/xe/xe_guc_types.h
> index 3dbcb1331690e..6da43691e54c5 100644
> --- a/drivers/gpu/drm/xe/xe_guc_types.h
> +++ b/drivers/gpu/drm/xe/xe_guc_types.h
> @@ -42,10 +42,10 @@ struct xe_guc_db_mgr {
>   struct xe_guc_id_mgr {
>   	/** @bitmap: bitmap to track allocated IDs */
>   	unsigned long *bitmap;
> -	/** @total: total number of IDs being managed */
> -	unsigned int total;
> -	/** @used: number of IDs currently in use */
> -	unsigned int used;
> +	/** @usable: number of IDs being managed for GuC submission */
> +	unsigned int usable;
> +	/** @shareable: number of IDs that can be shared with VFs */
> +	unsigned int shareable;
>   };
>   
>   /**

  reply	other threads:[~2026-10-06  8:36 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-05  8:51 [PATCH v5 0/4] Split GuC ID space into usable and shareable pools Piórkowski, Piotr
2026-10-05  8:51 ` [PATCH v5 1/4] drm/xe/guc: Split GuC ID manager " Piórkowski, Piotr
2026-10-06  8:35   ` K V P, Satyanarayana [this message]
2026-10-05  8:51 ` [PATCH v5 2/4] drm/xe/kunit: Extend GuC ID manager split-pool coverage Piórkowski, Piotr
2026-10-05  9:04   ` sashiko-bot
2026-10-05  8:51 ` [PATCH v5 3/4] drm/xe/guc: Start use explicitly usable GuC IDs for for submission Piórkowski, Piotr
2026-10-08  6:04   ` K V P, Satyanarayana
2026-10-05  8:51 ` [PATCH v5 4/4] drm/xe/pf: Explicitly use shareable GuC IDs for VFs provisioning Piórkowski, Piotr
2026-10-08  6:16   ` K V P, Satyanarayana
2026-10-05  9:23 ` ✓ CI.KUnit: success for Split GuC ID space into usable and shareable pools (rev5) Patchwork
2026-10-05 10:11 ` ✓ Xe.CI.BAT: " Patchwork
2026-10-05 14:02 ` ✓ Xe.CI.FULL: " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=866ddae9-3df8-4bdc-a9bf-48efbb49135e@intel.com \
    --to=satyanarayana.k.v.p@intel.com \
    --cc=intel-xe@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox