[PATCH v2 3/4] drm/xe/guc: Start use explicitly usable GuC IDs for for submission
Piórkowski, Piotr <[email protected]>
| Newsgroups | org.freedesktop.lists.intel-xe |
|---|---|
| Message-ID | <[email protected]> |
From: Piotr Piórkowski <[email protected]> Switch GuC submission to explicitly allocate IDs from the usable ID pool. Also lets configure the GuC ID manager according to the device operating mode during submission initialization. Use dedicated initialization paths for native, PF and VF modes to expose the appropriate usable and shareable GuC ID ranges. v2: Use xe_root_mmio_gt() to get the primary GT so no NULL check is needed (Sashiko). Signed-off-by: Piotr Piórkowski <[email protected]> Cc: Michal Wajdeczko <[email protected]> --- drivers/gpu/drm/xe/tests/xe_guc_id_mgr_test.c | 106 +++++++++++++++++- drivers/gpu/drm/xe/xe_guc.c | 4 +- drivers/gpu/drm/xe/xe_guc_id_mgr.c | 73 +++++++----- drivers/gpu/drm/xe/xe_guc_id_mgr.h | 14 ++- drivers/gpu/drm/xe/xe_guc_submit.c | 27 +++-- drivers/gpu/drm/xe/xe_guc_submit.h | 2 +- 6 files changed, 178 insertions(+), 48 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 295c17dbc21f..f21d3341b503 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,19 +7,42 @@ #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_guc_id_mgr *idm; 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; return 0; } +#ifdef CONFIG_PCI_IOV +static int guc_id_mgr_pf_test_init(struct kunit *test) +{ + struct xe_pci_fake_data fake = { + .sriov_mode = XE_SRIOV_MODE_PF, + .platform = XE_TIGERLAKE, /* some random platform */ + .subplatform = XE_SUBPLATFORM_NONE, + }; + struct xe_guc_id_mgr *idm; + + test->priv = &fake; + xe_kunit_helper_xe_device_test_init(test); + KUNIT_ASSERT_TRUE(test, IS_SRIOV_PF(test->priv)); + + idm = &xe_root_mmio_gt(test->priv)->uc.guc.submission_state.idm; + mutex_init(idm_mutex(idm)); + test->priv = idm; + + return 0; +} +#endif + static void bad_init(struct kunit *test) { struct xe_guc_id_mgr *idm = test->priv; @@ -33,7 +56,7 @@ 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)); @@ -51,6 +74,59 @@ static void init_fini(struct kunit *test) KUNIT_EXPECT_EQ(test, idm_total(idm), 0); } +static void check_init_native(struct kunit *test) +{ + struct xe_guc_id_mgr *idm = test->priv; + + KUNIT_ASSERT_EQ(test, xe_guc_id_mgr_init(idm), 0); + 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), 0); + KUNIT_EXPECT_EQ(test, idm_total(idm), GUC_ID_MAX); + + KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_reserve_usable(idm, 1), 0); + KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_usable(idm, 0, 1), 0); + KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_reserve_shareable(idm, 1, 0), -ENODATA); +} + +static void check_init_small(struct kunit *test) +{ + struct xe_guc_id_mgr *idm = test->priv; + unsigned int count = 8; + + KUNIT_ASSERT_EQ(test, xe_guc_id_mgr_init_small(idm, count), 0); + KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_max_usable(idm), count); + KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_max_shareable(idm), 0); + KUNIT_EXPECT_EQ(test, idm_total(idm), count); + + KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_reserve_usable(idm, count), 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, count), 0); +} + +#ifdef CONFIG_PCI_IOV +static void check_init_shared(struct kunit *test) +{ + struct xe_guc_id_mgr *idm = test->priv; + int usable_id, shareable_id; + + KUNIT_ASSERT_TRUE(test, IS_SRIOV_PF(idm_to_xe(idm))); + + KUNIT_ASSERT_EQ(test, xe_guc_id_mgr_init_shared(idm), 0); + 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); + + usable_id = xe_guc_id_mgr_reserve_usable(idm, 1); + KUNIT_ASSERT_GE(test, usable_id, 0); + + shareable_id = xe_guc_id_mgr_reserve_shareable(idm, 1, 0); + KUNIT_ASSERT_GE(test, shareable_id, 0); + + KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_usable(idm, usable_id, 1), 0); + KUNIT_EXPECT_EQ(test, xe_guc_id_mgr_release_shareable(idm, shareable_id, 1), 0); +} +#endif + static void check_used(struct kunit *test) { struct xe_guc_id_mgr *idm = test->priv; @@ -63,7 +139,7 @@ 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, idm_used_total(idm), n); - KUNIT_EXPECT_GE(test, idm_reserve_chunk_locked(idm, 1, 0), 0); + KUNIT_EXPECT_GE(test, xe_guc_id_mgr_reserve_usable_locked(idm, 1), 0); KUNIT_EXPECT_EQ(test, idm_used_total(idm), n + 1); } KUNIT_EXPECT_EQ(test, idm_used_total(idm), idm_total(idm)); @@ -97,7 +173,6 @@ static void check_quota(struct kunit *test) KUNIT_EXPECT_EQ(test, idm_used_total(idm), idm_total(idm)); idm_release_chunk_locked(idm, 0, idm_total(idm)); KUNIT_EXPECT_EQ(test, idm_used_total(idm), 0); - mutex_unlock(idm_mutex(idm)); } @@ -111,7 +186,7 @@ static void check_all(struct kunit *test) mutex_lock(idm_mutex(idm)); for (n = 0; n < idm_total(idm); n++) - KUNIT_EXPECT_LE(test, 0, idm_reserve_chunk_locked(idm, 1, 0)); + KUNIT_EXPECT_GE(test, xe_guc_id_mgr_reserve_usable_locked(idm, 1), 0); KUNIT_EXPECT_EQ(test, idm_used_total(idm), idm_total(idm)); for (n = 0; n < idm_total(idm); n++) idm_release_chunk_locked(idm, n, 1); @@ -493,6 +568,8 @@ static struct kunit_case guc_id_mgr_test_cases[] = { KUNIT_CASE(bad_init), KUNIT_CASE(no_init), KUNIT_CASE(init_fini), + KUNIT_CASE(check_init_native), + KUNIT_CASE(check_init_small), KUNIT_CASE(check_used), KUNIT_CASE(check_quota), KUNIT_CASE(check_limits), @@ -520,4 +597,23 @@ static struct kunit_suite guc_id_mgr_suite = { .exit = NULL, }; +#ifdef CONFIG_PCI_IOV +static struct kunit_case guc_id_mgr_pf_test_cases[] = { + KUNIT_CASE(check_init_shared), + {} +}; + +static struct kunit_suite guc_id_mgr_pf_suite = { + .name = "guc_idm_pf", + .test_cases = guc_id_mgr_pf_test_cases, + + .init = guc_id_mgr_pf_test_init, + .exit = NULL, +}; +#endif + +#ifdef CONFIG_PCI_IOV +kunit_test_suites(&guc_id_mgr_suite, &guc_id_mgr_pf_suite); +#else kunit_test_suites(&guc_id_mgr_suite); +#endif diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c index c7f8bbd4cb92..f1c802d53987 100644 --- a/drivers/gpu/drm/xe/xe_guc.c +++ b/drivers/gpu/drm/xe/xe_guc.c @@ -853,7 +853,7 @@ static int vf_guc_init_post_hwconfig(struct xe_guc *guc) { int err; - err = xe_guc_submit_init(guc, xe_gt_sriov_vf_guc_ids(guc_to_gt(guc))); + err = xe_guc_submit_init(guc); if (err) return err; @@ -897,7 +897,7 @@ int xe_guc_init_post_hwconfig(struct xe_guc *guc) guc_init_params_post_hwconfig(guc); - ret = xe_guc_submit_init(guc, ~0); + ret = xe_guc_submit_init(guc); if (ret) return ret; diff --git a/drivers/gpu/drm/xe/xe_guc_id_mgr.c b/drivers/gpu/drm/xe/xe_guc_id_mgr.c index 08e72af2735f..31425011a311 100644 --- a/drivers/gpu/drm/xe/xe_guc_id_mgr.c +++ b/drivers/gpu/drm/xe/xe_guc_id_mgr.c @@ -131,29 +131,63 @@ static int idm_init(struct xe_guc_id_mgr *idm, unsigned int usable, unsigned int } /** - * xe_guc_id_mgr_init() - Initialize GuC context ID Manager. + * xe_guc_id_mgr_init() - Initialize GuC ID manager for native. * @idm: the &xe_guc_id_mgr to initialize - * @limit: number of IDs to manage * - * 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. + * This function initializes the GuC ID manager to manage the full range of + * GuC context IDs (0..GUC_ID_MAX) for use by the GuC submission code. + * No GuC context IDs will be reserved for sharing with VFs. + * + * Can only be called when the device is not in SR-IOV mode. * * 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 xe_guc_id_mgr_init(struct xe_guc_id_mgr *idm) { - if (limit == ~0) - limit = GUC_ID_MAX; - else if (limit > GUC_ID_MAX) - return -ERANGE; - else if (!limit) - return -EINVAL; - return idm_init(idm, limit, IS_SRIOV_PF(idm_to_xe(idm)) ? limit : 0); + xe_gt_assert(idm_to_gt(idm), !IS_SRIOV(idm_to_xe(idm))); + + return idm_init(idm, GUC_ID_MAX, 0); +} + +/** + * xe_guc_id_mgr_init_small() - Initialize GuC ID manager for small count. + * @idm: the &xe_guc_id_mgr to initialize + * @count: the number of usable GuC context IDs + * + * This function initializes the GuC ID manager to manage a small number of + * GuC context IDs (0..count-1) for use by the GuC submission code. + * + * Return: 0 on success, or a negative error code on failure. + */ +int xe_guc_id_mgr_init_small(struct xe_guc_id_mgr *idm, unsigned int count) +{ + return idm_init(idm, count, 0); +} + +#ifdef CONFIG_PCI_IOV +/** + * xe_guc_id_mgr_init_shared() - Initialize GuC ID manager for PF. + * @idm: the &xe_guc_id_mgr to initialize + * + * This function initializes the GuC ID manager to manage the full range of + * GuC context IDs (0..GUC_ID_MAX) for use by the GuC submission code. + * All GuC context IDs will be shareable with VFs. + * + * Can only be called when the device is in SR-IOV PF mode. + * + * Return: 0 on success, or a negative error code on failure. + */ +int xe_guc_id_mgr_init_shared(struct xe_guc_id_mgr *idm) +{ + xe_gt_assert(idm_to_gt(idm), IS_SRIOV_PF(idm_to_xe(idm))); + + return idm_init(idm, GUC_ID_MAX, GUC_ID_MAX); } +#endif /* CONFIG_PCI_IOV */ /** * xe_guc_id_mgr_max_usable() - Get maximum number of usable GuC context IDs. @@ -381,21 +415,6 @@ int xe_guc_id_mgr_reserve_shareable_locked(struct xe_guc_id_mgr *idm, unsigned i return idm_reserve_chunk_shareable_locked(idm, count, spare); } -/** - * xe_guc_id_mgr_reserve_locked() - Reserve one or more GuC context IDs. - * @idm: the &xe_guc_id_mgr - * @count: number of IDs to allocate (can't be 0) - * - * This function is dedicated for the use by the GuC submission code, - * where submission lock is already taken. - * - * 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) -{ - return idm_reserve_chunk_locked(idm, count, 0); -} - /** * xe_guc_id_mgr_release_locked() - Release one or more GuC context IDs. * @idm: the &xe_guc_id_mgr diff --git a/drivers/gpu/drm/xe/xe_guc_id_mgr.h b/drivers/gpu/drm/xe/xe_guc_id_mgr.h index b2b4c1212a8c..f7ab753070da 100644 --- a/drivers/gpu/drm/xe/xe_guc_id_mgr.h +++ b/drivers/gpu/drm/xe/xe_guc_id_mgr.h @@ -6,10 +6,21 @@ #ifndef _XE_GUC_ID_MGR_H_ #define _XE_GUC_ID_MGR_H_ +#include <linux/errno.h> + 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); +int xe_guc_id_mgr_init_small(struct xe_guc_id_mgr *idm, unsigned int count); +#ifdef CONFIG_PCI_IOV +int xe_guc_id_mgr_init_shared(struct xe_guc_id_mgr *idm); +#else +static inline int xe_guc_id_mgr_init_shared(struct xe_guc_id_mgr *idm) +{ + return -ENODEV; +} +#endif 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); @@ -20,7 +31,6 @@ int xe_guc_id_mgr_reserve_shareable_locked(struct xe_guc_id_mgr *idm, unsigned i 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, diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 9036f89dff7d..36dd5dfd51cb 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -282,20 +282,26 @@ static void primelockdep(struct xe_guc *guc) fs_reclaim_release(GFP_KERNEL); } +static int guc_id_mgr_init(struct xe_guc *guc) +{ + if (IS_SRIOV_PF(guc_to_xe(guc))) + return xe_guc_id_mgr_init_shared(&guc->submission_state.idm); + else if (IS_SRIOV_VF(guc_to_xe(guc))) + return xe_guc_id_mgr_init_small(&guc->submission_state.idm, + xe_gt_sriov_vf_guc_ids(guc_to_gt(guc))); + else + return xe_guc_id_mgr_init(&guc->submission_state.idm); +} + /** * xe_guc_submit_init() - Initialize GuC submission. * @guc: the &xe_guc to initialize - * @num_ids: number of GuC context IDs to use - * - * The bare-metal or PF driver can pass ~0 as &num_ids to indicate that all - * GuC context IDs supported by the GuC firmware should be used for submission. * - * Only VF drivers will have to provide explicit number of GuC context IDs - * that they can use for submission. + * This function initializes the GuC submission state. * * Return: 0 on success or a negative error code on failure. */ -int xe_guc_submit_init(struct xe_guc *guc, unsigned int num_ids) +int xe_guc_submit_init(struct xe_guc *guc) { struct xe_device *xe = guc_to_xe(guc); struct xe_gt *gt = guc_to_gt(guc); @@ -305,7 +311,7 @@ int xe_guc_submit_init(struct xe_guc *guc, unsigned int num_ids) if (err) return err; - err = xe_guc_id_mgr_init(&guc->submission_state.idm, num_ids); + err = guc_id_mgr_init(guc); if (err) return err; @@ -411,8 +417,7 @@ static int alloc_guc_id(struct xe_guc *guc, struct xe_exec_queue *q) int ret, i; mutex_lock(&guc->submission_state.lock); - ret = xe_guc_id_mgr_reserve_locked(&guc->submission_state.idm, - q->width); + ret = xe_guc_id_mgr_reserve_usable_locked(&guc->submission_state.idm, q->width); mutex_unlock(&guc->submission_state.lock); if (ret < 0) return ret; @@ -3170,7 +3175,7 @@ g2h_exec_queue_lookup(struct xe_guc *guc, u32 guc_id) struct xe_gt *gt = guc_to_gt(guc); struct xe_exec_queue *q; - if (unlikely(guc_id >= GUC_ID_MAX)) { + if (unlikely(guc_id >= xe_guc_id_mgr_max_usable(&guc->submission_state.idm))) { xe_gt_err(gt, "Invalid guc_id %u\n", guc_id); return NULL; } diff --git a/drivers/gpu/drm/xe/xe_guc_submit.h b/drivers/gpu/drm/xe/xe_guc_submit.h index ccade320dc69..07682f174aa8 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.h +++ b/drivers/gpu/drm/xe/xe_guc_submit.h @@ -12,7 +12,7 @@ struct drm_printer; struct xe_exec_queue; struct xe_guc; -int xe_guc_submit_init(struct xe_guc *guc, unsigned int num_ids); +int xe_guc_submit_init(struct xe_guc *guc); int xe_guc_submit_enable(struct xe_guc *guc); void xe_guc_submit_disable(struct xe_guc *guc); -- 2.34.1