From: "Piórkowski, Piotr" <piotr.piorkowski@intel.com>
To: <intel-xe@lists.freedesktop.org>
Cc: "Piotr Piórkowski" <piotr.piorkowski@intel.com>,
"Michal Wajdeczko" <michal.wajdeczko@intel.com>
Subject: [PATCH v4 2/4] drm/xe/kunit: Extend GuC ID manager split-pool coverage
Date: Thu, 27 Aug 2026 12:57:48 +0200 [thread overview]
Message-ID: <20260827105750.1248792-3-piotr.piorkowski@intel.com> (raw)
In-Reply-To: <20260827105750.1248792-1-piotr.piorkowski@intel.com>
From: Piotr Piórkowski <piotr.piorkowski@intel.com>
Expand the GuC ID manager KUnit coverage to exercise the new
usable/shareable pool model.
v2: Use KUNIT_EXPECT instead of KUNIT_ASSERT inside the locked section
so the mutex is not leaked on failure (Sashiko).
v3: Guard failed ID reservations before releasing test allocations.
v4: Avoid releasing unreserved ID ranges after failed test reservations.
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 | 609 +++++++++++++++++-
1 file changed, 594 insertions(+), 15 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 78d3de46b757..5fe71eac2e38 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
@@ -7,13 +7,27 @@
#include "xe_device.h"
#include "xe_kunit_helpers.h"
+#include "xe_pci_test.h"
static int guc_id_mgr_test_init(struct kunit *test)
{
+ struct xe_pci_fake_data *fake;
struct xe_guc_id_mgr *idm;
+ /* Keep one logical suite: use PF fixture when IOV is enabled. */
+ fake = kunit_kzalloc(test, sizeof(*fake), GFP_KERNEL);
+ if (!fake)
+ return -ENOMEM;
+
+ *fake = (struct xe_pci_fake_data) {
+ .sriov_mode = XE_SRIOV_MODE_PF,
+ .platform = XE_TIGERLAKE, /* some random platform */
+ .subplatform = XE_SUBPLATFORM_NONE,
+ };
+ test->priv = fake;
+
xe_kunit_helper_xe_device_test_init(test);
- idm = &xe_device_get_gt(test->priv, 0)->uc.guc.submission_state.idm;
+ idm = &xe_root_mmio_gt(test->priv)->uc.guc.submission_state.idm;
mutex_init(idm_mutex(idm));
test->priv = idm;
@@ -33,10 +47,10 @@ static void no_init(struct kunit *test)
struct xe_guc_id_mgr *idm = test->priv;
mutex_lock(idm_mutex(idm));
- KUNIT_EXPECT_EQ(test, -ENODATA, xe_guc_id_mgr_reserve_locked(idm, 0));
+ KUNIT_EXPECT_EQ(test, -ENODATA, xe_guc_id_mgr_reserve_usable_locked(idm, 0));
mutex_unlock(idm_mutex(idm));
- KUNIT_EXPECT_EQ(test, -ENODATA, xe_guc_id_mgr_reserve(idm, 1, 1));
+ KUNIT_EXPECT_EQ(test, -ENODATA, xe_guc_id_mgr_reserve_shareable(idm, 1, 1));
}
static void init_fini(struct kunit *test)
@@ -51,6 +65,23 @@ static void init_fini(struct kunit *test)
KUNIT_EXPECT_EQ(test, idm_total(idm), 0);
}
+static bool require_iov_config_or_skip(struct kunit *test)
+{
+ if (!IS_ENABLED(CONFIG_PCI_IOV)) {
+ kunit_skip(test, "requires CONFIG_PCI_IOV");
+ return false;
+ }
+
+ return true;
+}
+
+static unsigned int test_idm_used_total(struct xe_guc_id_mgr *idm)
+{
+ lockdep_assert_held(idm_mutex(idm));
+
+ return bitmap_weight(idm->bitmap, idm_total(idm));
+}
+
static void check_used(struct kunit *test)
{
struct xe_guc_id_mgr *idm = test->priv;
@@ -62,13 +93,13 @@ static void check_used(struct kunit *test)
for (n = 0; n < idm_total(idm); n++) {
kunit_info(test, "n=%u", n);
- KUNIT_EXPECT_EQ(test, bitmap_weight(idm->bitmap, idm_total(idm)), n);
+ KUNIT_EXPECT_EQ(test, test_idm_used_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, test_idm_used_total(idm), n + 1);
}
- 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);
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), idm_total(idm));
+ idm_release_chunk_locked(idm, 0, test_idm_used_total(idm));
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), 0);
mutex_unlock(idm_mutex(idm));
}
@@ -76,32 +107,566 @@ static void check_used(struct kunit *test)
static void check_quota(struct kunit *test)
{
struct xe_guc_id_mgr *idm = test->priv;
+ unsigned int usable = GUC_ID_MAX - 10;
+ unsigned int shareable = 20;
+ unsigned int spare = 11;
+ unsigned int tail = 10;
+ int usable_id, tail_id;
- KUNIT_ASSERT_EQ(test, 0, idm_init(idm, 2, 0));
+ if (!require_iov_config_or_skip(test))
+ return;
+
+ KUNIT_ASSERT_EQ(test, 0, idm_init(idm, usable, shareable));
+
+ mutex_lock(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);
+ /* spare is larger than the overlap, but the PF-exclusive range is free. */
+ usable_id = xe_guc_id_mgr_reserve_usable_locked(idm, usable - spare);
+ KUNIT_EXPECT_GE(test, usable_id, 0);
+ if (usable_id < 0) {
+ mutex_unlock(idm_mutex(idm));
+ return;
+ }
+
+ tail_id = xe_guc_id_mgr_reserve_shareable_locked(idm, tail, spare);
+ KUNIT_EXPECT_EQ(test, tail_id, usable);
+ if (tail_id < 0) {
+ idm_release_chunk_locked(idm, usable_id, usable - spare);
+ mutex_unlock(idm_mutex(idm));
+ return;
+ }
+
+ KUNIT_EXPECT_EQ(test,
+ xe_guc_id_mgr_reserve_shareable_locked(idm, 1, spare), -EDQUOT);
+
+ idm_release_chunk_locked(idm, usable_id, usable - spare);
+ idm_release_chunk_locked(idm, tail_id, tail);
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), 0);
+
+ mutex_unlock(idm_mutex(idm));
}
static void check_all(struct kunit *test)
{
struct xe_guc_id_mgr *idm = test->priv;
unsigned int n;
+ int id;
KUNIT_ASSERT_EQ(test, 0, idm_init(idm, GUC_ID_MAX, 0));
mutex_lock(idm_mutex(idm));
- 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++) {
+ id = xe_guc_id_mgr_reserve_usable_locked(idm, 1);
+ KUNIT_EXPECT_GE(test, id, 0);
+ if (id < 0)
+ break;
+ }
+ if (n < idm_total(idm)) {
+ if (n)
+ idm_release_chunk_locked(idm, 0, n);
+ mutex_unlock(idm_mutex(idm));
+ return;
+ }
+
+ KUNIT_EXPECT_EQ(test, test_idm_used_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));
}
+static void check_limits(struct kunit *test)
+{
+ struct xe_guc_id_mgr *idm = test->priv;
+
+ if (!require_iov_config_or_skip(test))
+ return;
+
+ KUNIT_ASSERT_EQ(test, 0, idm_init(idm, 10, 20));
+
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_max_usable(idm), 10);
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_max_shareable(idm), 20);
+ KUNIT_EXPECT_EQ(test, idm_total(idm), 30);
+}
+
+static void check_overlap(struct kunit *test)
+{
+ struct xe_guc_id_mgr *idm = test->priv;
+
+ if (!require_iov_config_or_skip(test))
+ return;
+
+ KUNIT_ASSERT_EQ(test, 0, idm_init(idm, GUC_ID_MAX, GUC_ID_MAX));
+
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_max_usable(idm), GUC_ID_MAX);
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_max_shareable(idm), GUC_ID_MAX);
+ KUNIT_EXPECT_EQ(test, idm_total(idm), GUC_ID_MAX);
+}
+
+static void check_overlap_alloc(struct kunit *test)
+{
+ struct xe_guc_id_mgr *idm = test->priv;
+ unsigned int total;
+ int usable_id, shareable_id;
+
+ if (!require_iov_config_or_skip(test))
+ return;
+
+ KUNIT_ASSERT_EQ(test, 0, idm_init(idm, GUC_ID_MAX, GUC_ID_MAX));
+
+ mutex_lock(idm_mutex(idm));
+ total = idm_total(idm);
+
+ usable_id = xe_guc_id_mgr_reserve_usable_locked(idm, 2);
+ KUNIT_EXPECT_EQ(test, usable_id, 0);
+
+ shareable_id = xe_guc_id_mgr_reserve_shareable_locked(idm, 3, 0);
+ KUNIT_EXPECT_EQ(test, shareable_id, total - 3);
+
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), 5);
+ KUNIT_EXPECT_EQ(test, idm_used_usable(idm), 5);
+ KUNIT_EXPECT_EQ(test, idm_used_shareable(idm), 5);
+
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_usable_locked(idm, usable_id, 2), 0);
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_shareable_locked(idm, shareable_id, 3), 0);
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), 0);
+
+ mutex_unlock(idm_mutex(idm));
+}
+
+static void check_overlap_release(struct kunit *test)
+{
+ struct xe_guc_id_mgr *idm = test->priv;
+ unsigned int total;
+ int id;
+
+ if (!require_iov_config_or_skip(test))
+ return;
+
+ KUNIT_ASSERT_EQ(test, 0, idm_init(idm, GUC_ID_MAX, GUC_ID_MAX));
+
+ mutex_lock(idm_mutex(idm));
+ total = idm_total(idm);
+
+ id = xe_guc_id_mgr_reserve_usable_locked(idm, 4);
+ KUNIT_EXPECT_EQ(test, id, 0);
+
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_shareable_locked(idm, id, 4), 0);
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), 0);
+
+ id = xe_guc_id_mgr_reserve_shareable_locked(idm, 4, 0);
+ KUNIT_EXPECT_EQ(test, id, total - 4);
+
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_usable_locked(idm, id, 4), 0);
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), 0);
+
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_usable_locked(idm, 0, 0), -EINVAL);
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_shareable_locked(idm, 0, 0), -EINVAL);
+
+ mutex_unlock(idm_mutex(idm));
+}
+
+static void check_overlap_partial_init(struct kunit *test)
+{
+ struct xe_guc_id_mgr *idm = test->priv;
+ unsigned int pools_size = (GUC_ID_MAX / 3) * 2;
+ unsigned int shareable_start;
+ unsigned int rest;
+ int usable_id, shareable_id;
+
+ if (!require_iov_config_or_skip(test))
+ return;
+
+ KUNIT_ASSERT_EQ(test, 0, idm_init(idm, pools_size, pools_size));
+
+ mutex_lock(idm_mutex(idm));
+
+ shareable_start = idm_shareable_start(idm);
+ rest = idm_total(idm) - pools_size;
+
+ KUNIT_EXPECT_EQ(test, idm_total(idm), GUC_ID_MAX);
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_max_usable(idm), pools_size);
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_max_shareable(idm), pools_size);
+ KUNIT_EXPECT_EQ(test, shareable_start, GUC_ID_MAX - pools_size);
+
+ usable_id = xe_guc_id_mgr_reserve_usable_locked(idm, pools_size);
+ KUNIT_EXPECT_EQ(test, usable_id, 0);
+ if (usable_id < 0) {
+ mutex_unlock(idm_mutex(idm));
+ return;
+ }
+
+ shareable_id = xe_guc_id_mgr_reserve_shareable_locked(idm, rest, 0);
+ KUNIT_EXPECT_EQ(test, shareable_id, pools_size);
+ if (shareable_id < 0) {
+ idm_release_chunk_locked(idm, usable_id, pools_size);
+ mutex_unlock(idm_mutex(idm));
+ return;
+ }
+
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), GUC_ID_MAX);
+ KUNIT_EXPECT_EQ(test, idm_used_usable(idm), pools_size);
+ KUNIT_EXPECT_EQ(test, idm_used_shareable(idm), pools_size);
+
+ KUNIT_EXPECT_EQ(test,
+ xe_guc_id_mgr_release_usable_locked(idm, usable_id, pools_size), 0);
+ KUNIT_EXPECT_EQ(test,
+ xe_guc_id_mgr_release_shareable_locked(idm, shareable_id, rest), 0);
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), 0);
+
+ mutex_unlock(idm_mutex(idm));
+}
+
+static void check_overlap_partial_shared_range_blocking(struct kunit *test)
+{
+ struct xe_guc_id_mgr *idm = test->priv;
+ unsigned int pools_size = (GUC_ID_MAX / 3) * 2;
+ int usable_id, shareable_range_id, shareable_overlap_id;
+ unsigned int shareable_start;
+ unsigned int nonoverlap_size;
+ unsigned int overlap_size;
+ unsigned int total;
+
+ if (!require_iov_config_or_skip(test))
+ return;
+
+ KUNIT_ASSERT_EQ(test, 0, idm_init(idm, pools_size, pools_size));
+
+ mutex_lock(idm_mutex(idm));
+
+ total = idm_total(idm);
+ shareable_start = idm_shareable_start(idm);
+ nonoverlap_size = total - pools_size;
+ overlap_size = pools_size - shareable_start;
+
+ KUNIT_EXPECT_GT(test, nonoverlap_size, 0);
+ KUNIT_EXPECT_GT(test, overlap_size, 0);
+
+ shareable_range_id = xe_guc_id_mgr_reserve_shareable_locked(idm, nonoverlap_size, 0);
+ KUNIT_EXPECT_EQ(test, shareable_range_id, pools_size);
+
+ usable_id = xe_guc_id_mgr_reserve_usable_locked(idm, pools_size);
+ KUNIT_EXPECT_EQ(test, usable_id, 0);
+
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_reserve_shareable_locked(idm, 1, 0), -ENOSPC);
+
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_usable_locked(idm, usable_id, pools_size), 0);
+
+ shareable_overlap_id = xe_guc_id_mgr_reserve_shareable_locked(idm, overlap_size, 0);
+ KUNIT_EXPECT_EQ(test, shareable_overlap_id, shareable_start);
+
+ usable_id = xe_guc_id_mgr_reserve_usable_locked(idm, shareable_start);
+ KUNIT_EXPECT_EQ(test, usable_id, 0);
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_reserve_usable_locked(idm, 1), -ENOSPC);
+
+ KUNIT_EXPECT_EQ(test,
+ xe_guc_id_mgr_release_usable_locked(idm, usable_id, shareable_start),
+ 0);
+ KUNIT_EXPECT_EQ(test,
+ xe_guc_id_mgr_release_shareable_locked(idm, shareable_overlap_id,
+ overlap_size),
+ 0);
+ KUNIT_EXPECT_EQ(test,
+ xe_guc_id_mgr_release_shareable_locked(idm, shareable_range_id,
+ nonoverlap_size),
+ 0);
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), 0);
+
+ mutex_unlock(idm_mutex(idm));
+}
+
+static void check_used_usable(struct kunit *test)
+{
+ struct xe_guc_id_mgr *idm = test->priv;
+ int id;
+
+ KUNIT_ASSERT_EQ(test, 0, idm_init(idm, 8, 0));
+
+ mutex_lock(idm_mutex(idm));
+
+ KUNIT_EXPECT_EQ(test, idm_used_usable(idm), 0);
+ KUNIT_EXPECT_EQ(test, idm_used_shareable(idm), 0);
+
+ id = xe_guc_id_mgr_reserve_usable_locked(idm, 2);
+ KUNIT_EXPECT_GE(test, id, 0);
+ if (id < 0) {
+ mutex_unlock(idm_mutex(idm));
+ return;
+ }
+
+ KUNIT_EXPECT_EQ(test, idm_used_usable(idm), 2);
+ KUNIT_EXPECT_EQ(test, idm_used_shareable(idm), 0);
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), 2);
+
+ idm_release_chunk_locked(idm, id, 2);
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), 0);
+
+ mutex_unlock(idm_mutex(idm));
+}
+
+static void check_used_shareable(struct kunit *test)
+{
+ struct xe_guc_id_mgr *idm = test->priv;
+ unsigned int shareable_start;
+ int id;
+
+ if (!require_iov_config_or_skip(test))
+ return;
+
+ KUNIT_ASSERT_EQ(test, 0, idm_init(idm, 8, 8));
+
+ mutex_lock(idm_mutex(idm));
+ shareable_start = idm_shareable_start(idm);
+
+ KUNIT_EXPECT_EQ(test, idm_used_usable(idm), 0);
+ KUNIT_EXPECT_EQ(test, idm_used_shareable(idm), 0);
+
+ id = xe_guc_id_mgr_reserve_shareable_locked(idm, 3, 0);
+ KUNIT_EXPECT_EQ(test, id, shareable_start);
+ if (id < 0) {
+ mutex_unlock(idm_mutex(idm));
+ return;
+ }
+
+ KUNIT_EXPECT_EQ(test, idm_used_usable(idm), 0);
+ KUNIT_EXPECT_EQ(test, idm_used_shareable(idm), 3);
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), 3);
+
+ idm_release_chunk_locked(idm, id, 3);
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), 0);
+
+ mutex_unlock(idm_mutex(idm));
+}
+
+static void check_used_mixed(struct kunit *test)
+{
+ struct xe_guc_id_mgr *idm = test->priv;
+ unsigned int shareable_start;
+ int usable_id, shareable_id;
+
+ if (!require_iov_config_or_skip(test))
+ return;
+
+ KUNIT_ASSERT_EQ(test, 0, idm_init(idm, 8, 8));
+
+ mutex_lock(idm_mutex(idm));
+ shareable_start = idm_shareable_start(idm);
+
+ usable_id = xe_guc_id_mgr_reserve_usable_locked(idm, 2);
+ KUNIT_EXPECT_EQ(test, usable_id, 0);
+
+ shareable_id = xe_guc_id_mgr_reserve_shareable_locked(idm, 3, 0);
+ KUNIT_EXPECT_EQ(test, shareable_id, shareable_start);
+
+ KUNIT_EXPECT_EQ(test, idm_used_usable(idm), 2);
+ KUNIT_EXPECT_EQ(test, idm_used_shareable(idm), 3);
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), 5);
+
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_usable_locked(idm, usable_id, 2), 0);
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_shareable_locked(idm, shareable_id, 3), 0);
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), 0);
+
+ mutex_unlock(idm_mutex(idm));
+}
+
+static void check_release_usable_range(struct kunit *test)
+{
+ struct xe_guc_id_mgr *idm = test->priv;
+ int id;
+
+ KUNIT_ASSERT_EQ(test, 0, idm_init(idm, 8, 0));
+
+ mutex_lock(idm_mutex(idm));
+
+ id = xe_guc_id_mgr_reserve_usable_locked(idm, 4);
+ KUNIT_EXPECT_EQ(test, id, 0);
+
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_usable_locked(idm, 4, 7), -ERANGE);
+ KUNIT_EXPECT_EQ(test, idm_used_usable(idm), 4);
+
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_usable_locked(idm, 0, 0), -EINVAL);
+ KUNIT_EXPECT_EQ(test, idm_used_usable(idm), 4);
+
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_usable_locked(idm, id, 4), 0);
+ KUNIT_EXPECT_EQ(test, idm_used_usable(idm), 0);
+
+ mutex_unlock(idm_mutex(idm));
+}
+
+static void check_release_shareable_range(struct kunit *test)
+{
+ struct xe_guc_id_mgr *idm = test->priv;
+ unsigned int shareable_start;
+ int id;
+
+ if (!require_iov_config_or_skip(test))
+ return;
+
+ KUNIT_ASSERT_EQ(test, 0, idm_init(idm, 8, 8));
+
+ mutex_lock(idm_mutex(idm));
+
+ shareable_start = idm_shareable_start(idm);
+ id = xe_guc_id_mgr_reserve_shareable_locked(idm, 4, 0);
+ KUNIT_EXPECT_EQ(test, id, shareable_start);
+
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_shareable_locked(idm, 4, 7), -ERANGE);
+ KUNIT_EXPECT_EQ(test, idm_used_shareable(idm), 4);
+
+ KUNIT_EXPECT_EQ(test,
+ xe_guc_id_mgr_release_shareable_locked(idm, shareable_start, 0),
+ -EINVAL);
+ KUNIT_EXPECT_EQ(test, idm_used_shareable(idm), 4);
+
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_shareable_locked(idm, id, 4), 0);
+ KUNIT_EXPECT_EQ(test, idm_used_shareable(idm), 0);
+
+ mutex_unlock(idm_mutex(idm));
+}
+
+static void check_split_boundaries(struct kunit *test)
+{
+ struct xe_guc_id_mgr *idm = test->priv;
+ unsigned int shareable_start;
+ int usable_id, shareable_id;
+
+ if (!require_iov_config_or_skip(test))
+ return;
+
+ KUNIT_ASSERT_EQ(test, 0, idm_init(idm, 4, 4));
+
+ mutex_lock(idm_mutex(idm));
+
+ shareable_start = idm_shareable_start(idm);
+
+ usable_id = xe_guc_id_mgr_reserve_usable_locked(idm, 4);
+ KUNIT_EXPECT_EQ(test, usable_id, 0);
+ if (usable_id < 0) {
+ mutex_unlock(idm_mutex(idm));
+ return;
+ }
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_reserve_usable_locked(idm, 1), -ENOSPC);
+
+ shareable_id = xe_guc_id_mgr_reserve_shareable_locked(idm, 4, 0);
+ KUNIT_EXPECT_EQ(test, shareable_id, shareable_start);
+ if (shareable_id < 0) {
+ idm_release_chunk_locked(idm, usable_id, 4);
+ mutex_unlock(idm_mutex(idm));
+ return;
+ }
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_reserve_shareable_locked(idm, 1, 0), -ENOSPC);
+
+ KUNIT_EXPECT_EQ(test, idm_used_usable(idm), 4);
+ KUNIT_EXPECT_EQ(test, idm_used_shareable(idm), 4);
+
+ idm_release_chunk_locked(idm, usable_id, 4);
+ idm_release_chunk_locked(idm, shareable_id, 4);
+ KUNIT_EXPECT_EQ(test, test_idm_used_total(idm), 0);
+
+ mutex_unlock(idm_mutex(idm));
+}
+
+static void check_shareable_spare(struct kunit *test)
+{
+ struct xe_guc_id_mgr *idm = test->priv;
+ unsigned int pools_size = (GUC_ID_MAX / 3) * 2;
+ unsigned int shareable_start;
+ unsigned int overlap_size;
+ unsigned int shared_tail;
+ int id_tail, id_overlap, id_extra;
+
+ if (!require_iov_config_or_skip(test))
+ return;
+
+ KUNIT_ASSERT_EQ(test, 0, idm_init(idm, pools_size, pools_size));
+
+ mutex_lock(idm_mutex(idm));
+ shareable_start = idm_shareable_start(idm);
+ overlap_size = idm->usable - shareable_start;
+ shared_tail = idm_total(idm) - idm->usable;
+
+ KUNIT_EXPECT_GT(test, overlap_size, 0);
+ KUNIT_EXPECT_GT(test, shared_tail, 0);
+
+ id_tail = xe_guc_id_mgr_reserve_shareable_locked(idm, shared_tail, 1);
+ KUNIT_EXPECT_EQ(test, id_tail, idm->usable);
+ if (id_tail < 0) {
+ mutex_unlock(idm_mutex(idm));
+ return;
+ }
+ KUNIT_EXPECT_EQ(test, idm_used_shareable(idm), shared_tail);
+
+ id_overlap = xe_guc_id_mgr_reserve_shareable_locked(idm, overlap_size - 1, 1);
+ KUNIT_EXPECT_EQ(test, id_overlap, shareable_start + 1);
+ if (id_overlap < 0) {
+ idm_release_chunk_locked(idm, id_tail, shared_tail);
+ mutex_unlock(idm_mutex(idm));
+ return;
+ }
+ KUNIT_EXPECT_EQ(test, idm_used_shareable(idm), idm->shareable - 1);
+
+ id_extra = xe_guc_id_mgr_reserve_shareable_locked(idm, 1, 1);
+ KUNIT_EXPECT_EQ(test, id_extra, shareable_start);
+ if (id_extra < 0) {
+ idm_release_chunk_locked(idm, id_tail, shared_tail);
+ idm_release_chunk_locked(idm, id_overlap, overlap_size - 1);
+ mutex_unlock(idm_mutex(idm));
+ return;
+ }
+ KUNIT_EXPECT_EQ(test, idm_used_shareable(idm), idm->shareable);
+
+ idm_release_chunk_locked(idm, id_tail, shared_tail);
+ idm_release_chunk_locked(idm, id_overlap, overlap_size - 1);
+ idm_release_chunk_locked(idm, id_extra, 1);
+ KUNIT_EXPECT_EQ(test, idm_used_shareable(idm), 0);
+
+ mutex_unlock(idm_mutex(idm));
+}
+
+static void check_shareable_spare_fragmented_tail(struct kunit *test)
+{
+ struct xe_guc_id_mgr *idm = test->priv;
+ unsigned int usable = GUC_ID_MAX - 50;
+ unsigned int shareable = 90;
+ unsigned int shareable_start;
+ unsigned int overlap_size;
+ unsigned int count = 39;
+ unsigned int spare = 10;
+ unsigned int i;
+
+ if (!require_iov_config_or_skip(test))
+ return;
+
+ KUNIT_ASSERT_EQ(test, 0, idm_init(idm, usable, shareable));
+
+ mutex_lock(idm_mutex(idm));
+ shareable_start = idm_shareable_start(idm);
+ overlap_size = idm->usable - shareable_start;
+ KUNIT_EXPECT_EQ(test, overlap_size, 40);
+
+ bitmap_fill(idm->bitmap, idm_total(idm));
+ bitmap_set(idm->bitmap, 0, 1);
+ bitmap_clear(idm->bitmap, shareable_start + 1, overlap_size - 1);
+ for (i = idm->usable; i < idm_total(idm); i++) {
+ if ((i - idm->usable) % 5)
+ bitmap_clear(idm->bitmap, i, 1);
+ }
+
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_reserve_shareable_locked(idm, count, spare),
+ -EDQUOT);
+
+ bitmap_fill(idm->bitmap, idm_total(idm));
+ bitmap_clear(idm->bitmap, shareable_start, 30);
+ bitmap_clear(idm->bitmap, idm_total(idm) - 20, 20);
+ KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_reserve_shareable_locked(idm, 30, 1),
+ -EDQUOT);
+
+ bitmap_zero(idm->bitmap, idm_total(idm));
+
+ mutex_unlock(idm_mutex(idm));
+}
+
static struct kunit_case guc_id_mgr_test_cases[] = {
KUNIT_CASE(bad_init),
KUNIT_CASE(no_init),
@@ -109,6 +674,20 @@ static struct kunit_case guc_id_mgr_test_cases[] = {
KUNIT_CASE(check_used),
KUNIT_CASE(check_quota),
KUNIT_CASE_SLOW(check_all),
+ KUNIT_CASE(check_limits),
+ KUNIT_CASE(check_overlap),
+ KUNIT_CASE(check_overlap_alloc),
+ KUNIT_CASE(check_overlap_release),
+ KUNIT_CASE(check_overlap_partial_init),
+ KUNIT_CASE(check_overlap_partial_shared_range_blocking),
+ KUNIT_CASE(check_used_usable),
+ KUNIT_CASE(check_used_shareable),
+ KUNIT_CASE(check_used_mixed),
+ KUNIT_CASE(check_release_usable_range),
+ KUNIT_CASE(check_release_shareable_range),
+ KUNIT_CASE(check_split_boundaries),
+ KUNIT_CASE(check_shareable_spare),
+ KUNIT_CASE(check_shareable_spare_fragmented_tail),
{}
};
--
2.34.1
next prev parent reply other threads:[~2026-08-27 10:58 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-27 10:57 [PATCH v4 0/4] Split GuC ID space into usable and shareable pools Piórkowski, Piotr
2026-08-27 10:57 ` [PATCH v4 1/4] drm/xe/guc: Split GuC ID manager " Piórkowski, Piotr
2026-08-27 11:16 ` sashiko-bot
2026-08-27 10:57 ` Piórkowski, Piotr [this message]
2026-08-27 10:57 ` [PATCH v4 3/4] drm/xe/guc: Start use explicitly usable GuC IDs for for submission Piórkowski, Piotr
2026-08-27 11:15 ` sashiko-bot
2026-08-27 10:57 ` [PATCH v4 4/4] drm/xe/pf: Explicitly use shareable GuC IDs for VFs provisioning Piórkowski, Piotr
2026-08-27 11:47 ` ✓ CI.KUnit: success for Split GuC ID space into usable and shareable pools (rev4) Patchwork
2026-08-27 12:26 ` ✓ Xe.CI.BAT: " Patchwork
2026-08-27 13:36 ` ✓ 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=20260827105750.1248792-3-piotr.piorkowski@intel.com \
--to=piotr.piorkowski@intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=michal.wajdeczko@intel.com \
/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