summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMatthew Auld <matthew.auld@intel.com>2026-06-26 12:15:29 +0100
committerMatthew Auld <matthew.auld@intel.com>2026-07-10 12:50:19 +0100
commitfe0d94f65bf2fcc6fea930360d834b199a77e1c2 (patch)
treeaac64eac767a5e8ae2de3a721475c56d8b36d990 /drivers
parentd4438cf37005f7c1e12e5a79844be5c5ca35ea7c (diff)
downloadlinux-next-fe0d94f65bf2fcc6fea930360d834b199a77e1c2.tar.gz
linux-next-fe0d94f65bf2fcc6fea930360d834b199a77e1c2.zip
drm/xe/vf: wire up NUM_PAGING_ENGINE_INSTANCES
When host PF writes the logical configuration for the GUC PAGING engine, the VF is meant to query it, and mirror it. Size of N means we have paging logical index range [0, N-1], with N fewer normal copy engines. Agreement is that PF will only spawn PAGING engines on NVL-S+, so this should be zero on older platforms, where we should simply fall back to the old behaviour. v2 (Sashiko): - We can't call use the guc_has_paging_engine() this early in the VF code. With that just unconditionally do the query, if the GuC is new enough and take the value as-is. With that drop the -1 special case and just let the upper layers figure out the rest. v3: - Also update xe_guc_klv_key_to_string. (Michal) - Add kernel-doc for xe_gt_sriov_vf_paging_engines(), plus other tweaks. (Michal) - Update with final GuC version. v4: - Just fallback to manual reserve when vf reported paging engines is zero. Will revisit in the future. v5 (Michal): - Convert the assert to a full abort if we ever see non-zero GuC paging engine count, on pre-nvl. - Move the VF hunk in guc_has_paging_engine() here. - Some small tweaks. Signed-off-by: Matthew Auld <matthew.auld@intel.com> Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com> Cc: Piotr Piórkowski <piotr.piorkowski@intel.com> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com> Reviewed-by: Michal Wajdeczko <michal.wajdeczko@intel.com> Link: https://patch.msgid.link/20260626111520.487997-20-matthew.auld@intel.com
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/xe/abi/guc_klvs_abi.h9
-rw-r--r--drivers/gpu/drm/xe/xe_gt_sriov_vf.c47
-rw-r--r--drivers/gpu/drm/xe/xe_gt_sriov_vf.h1
-rw-r--r--drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h4
-rw-r--r--drivers/gpu/drm/xe/xe_guc.c6
-rw-r--r--drivers/gpu/drm/xe/xe_guc_klv_helpers.c2
-rw-r--r--drivers/gpu/drm/xe/xe_hw_engine.c32
7 files changed, 99 insertions, 2 deletions
diff --git a/drivers/gpu/drm/xe/abi/guc_klvs_abi.h b/drivers/gpu/drm/xe/abi/guc_klvs_abi.h
index ec9c22dc21be..e50c586f6146 100644
--- a/drivers/gpu/drm/xe/abi/guc_klvs_abi.h
+++ b/drivers/gpu/drm/xe/abi/guc_klvs_abi.h
@@ -52,6 +52,12 @@
* _`GUC_KLV_GLOBAL_CFG_GROUP_SCHEDULING_AVAILABLE` : 0x3001
* Tells the driver whether scheduler groups are enabled or not.
* Requires GuC ABI 1.26+
+ *
+ * _`GUC_KLV_GLOBAL_CFG_NUM_PAGING_ENGINE_INSTANCES` : 0x3003
+ * Tells the driver the paging engine configuration.
+ * Paging engine logical instances are guaranteed to be dense starting at
+ * index 0.
+ * Requires GuC ABI 1.36+
*/
#define GUC_KLV_GLOBAL_CFG_GMD_ID_KEY 0x3000u
@@ -60,6 +66,9 @@
#define GUC_KLV_GLOBAL_CFG_GROUP_SCHEDULING_AVAILABLE_KEY 0x3001u
#define GUC_KLV_GLOBAL_CFG_GROUP_SCHEDULING_AVAILABLE_LEN 1u
+#define GUC_KLV_GLOBAL_CFG_NUM_PAGING_ENGINE_INSTANCES_KEY 0x3003u
+#define GUC_KLV_GLOBAL_CFG_NUM_PAGING_ENGINE_INSTANCES_LEN 1u
+
/**
* DOC: GuC Self Config KLVs
*
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
index 0cd9d77f3351..37899fcf5b22 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
@@ -658,6 +658,33 @@ static int vf_cache_sched_groups_status(struct xe_gt *gt)
return 0;
}
+static int vf_cache_num_paging_engines(struct xe_gt *gt)
+{
+ struct xe_guc *guc = &gt->uc.guc;
+ struct xe_uc_fw_version guc_version;
+ u32 value = 0;
+ int err;
+
+ xe_gt_sriov_vf_guc_versions(gt, NULL, &guc_version);
+
+ if (MAKE_GUC_VER_STRUCT(guc_version) < MAKE_GUC_VER(1, 36, 0))
+ return 0;
+
+ err = guc_action_query_single_klv32(guc, GUC_KLV_GLOBAL_CFG_NUM_PAGING_ENGINE_INSTANCES_KEY,
+ &value);
+ if (unlikely(err)) {
+ xe_gt_sriov_err(gt,
+ "Failed to obtain the number of paging instances (%pe)\n",
+ ERR_PTR(err));
+ return err;
+ }
+
+ gt->sriov.vf.runtime.num_paging_engine_instances = value;
+
+ xe_gt_sriov_dbg(gt, "num_paging_engines %u\n", value);
+ return 0;
+}
+
/**
* xe_gt_sriov_vf_query_config - Query SR-IOV config data over MMIO.
* @gt: the &xe_gt
@@ -694,6 +721,10 @@ int xe_gt_sriov_vf_query_config(struct xe_gt *gt)
if (has_gmdid(xe))
vf_cache_gmdid(gt);
+ err = vf_cache_num_paging_engines(gt);
+ if (unlikely(err))
+ return err;
+
return 0;
}
@@ -731,6 +762,22 @@ u16 xe_gt_sriov_vf_guc_ids(struct xe_gt *gt)
return gt->sriov.vf.self_config.num_ctxs;
}
+/**
+ * xe_gt_sriov_vf_paging_engines - Return the number of paging engine instances
+ * @gt: the &xe_gt
+ *
+ * This function is for VF use only.
+ *
+ * Return: number of GuC paging engine instances configured by the PF.
+ */
+u32 xe_gt_sriov_vf_paging_engines(struct xe_gt *gt)
+{
+ xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt)));
+ xe_gt_assert(gt, gt->sriov.vf.guc_version.major);
+
+ return gt->sriov.vf.runtime.num_paging_engine_instances;
+}
+
static int relay_action_handshake(struct xe_gt *gt, u32 *major, u32 *minor)
{
u32 request[VF2PF_HANDSHAKE_REQUEST_MSG_LEN] = {
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h
index 79878f21b1da..d171a8242a34 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h
@@ -31,6 +31,7 @@ u32 xe_gt_sriov_vf_gmdid(struct xe_gt *gt);
u16 xe_gt_sriov_vf_guc_ids(struct xe_gt *gt);
u64 xe_gt_sriov_vf_lmem(struct xe_gt *gt);
bool xe_gt_sriov_vf_sched_groups_enabled(struct xe_gt *gt);
+u32 xe_gt_sriov_vf_paging_engines(struct xe_gt *gt);
u32 xe_gt_sriov_vf_read32(struct xe_gt *gt, struct xe_reg reg);
void xe_gt_sriov_vf_write32(struct xe_gt *gt, struct xe_reg reg, u32 val);
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h
index 80562ffadb16..466f0abd9c28 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h
@@ -29,6 +29,10 @@ struct xe_gt_sriov_vf_runtime {
u32 gmdid;
/** @uses_sched_groups: whether PF enabled sched groups or not. */
bool uses_sched_groups;
+ /**
+ * @num_paging_engine_instances: number of configured paging engines.
+ */
+ u32 num_paging_engine_instances;
/** @regs_size: size of runtime register array. */
u32 regs_size;
/** @num_regs: number of runtime registers in the array. */
diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c
index bbf6dfb74532..8ccaf4b16832 100644
--- a/drivers/gpu/drm/xe/xe_guc.c
+++ b/drivers/gpu/drm/xe/xe_guc.c
@@ -1858,6 +1858,9 @@ bool xe_guc_using_main_gamctrl_queues(struct xe_guc *guc)
bool xe_guc_has_paging_engine(struct xe_guc *guc)
{
+ struct xe_gt *gt = guc_to_gt(guc);
+ struct xe_device *xe = gt_to_xe(gt);
+
/*
* On newer platforms the GuC now has a dedicated engine class for the
* special PAGING engine, which is the driver reserved BCS engine used
@@ -1867,6 +1870,9 @@ bool xe_guc_has_paging_engine(struct xe_guc *guc)
* need to respect.
*/
+ if (IS_SRIOV_VF(xe))
+ return xe_gt_sriov_vf_paging_engines(gt);
+
/* TODO: Have some way to query this from the GuC? */
return false;
}
diff --git a/drivers/gpu/drm/xe/xe_guc_klv_helpers.c b/drivers/gpu/drm/xe/xe_guc_klv_helpers.c
index 97600edda837..be992b8da9a1 100644
--- a/drivers/gpu/drm/xe/xe_guc_klv_helpers.c
+++ b/drivers/gpu/drm/xe/xe_guc_klv_helpers.c
@@ -24,6 +24,8 @@ const char *xe_guc_klv_key_to_string(u16 key)
/* GuC Global Config KLVs */
case GUC_KLV_GLOBAL_CFG_GROUP_SCHEDULING_AVAILABLE_KEY:
return "group_scheduling_available";
+ case GUC_KLV_GLOBAL_CFG_NUM_PAGING_ENGINE_INSTANCES_KEY:
+ return "num_paging_engine_instances";
/* VGT POLICY keys */
case GUC_KLV_VGT_POLICY_SCHED_IF_IDLE_KEY:
return "sched_if_idle";
diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c
index d741d93601b2..0e03328a564d 100644
--- a/drivers/gpu/drm/xe/xe_hw_engine.c
+++ b/drivers/gpu/drm/xe/xe_hw_engine.c
@@ -658,7 +658,7 @@ err_name:
return err;
}
-static void hw_engine_setup_logical_and_paging_mapping(struct xe_gt *gt)
+static int hw_engine_setup_logical_and_paging_mapping(struct xe_gt *gt)
{
struct xe_device *xe = gt_to_xe(gt);
unsigned int num_copy_engines = 0, num_paging_engines = 0;
@@ -675,6 +675,29 @@ static void hw_engine_setup_logical_and_paging_mapping(struct xe_gt *gt)
if (num_copy_engines && xe->info.has_usm)
num_paging_engines = 1;
+ if (IS_SRIOV_VF(xe)) {
+ u32 vf_num_paging_engines;
+
+ /*
+ * PF could in theory reserve multiple paging engines, which
+ * internally the submission/scheduling backend can load balance
+ * from. Not something we currently expect, but we are at the
+ * mercy of the PF, so we just need try our best to mirror the
+ * paging configuration.
+ */
+ vf_num_paging_engines = xe_gt_sriov_vf_paging_engines(gt);
+ if (vf_num_paging_engines) {
+ /* This should only be non-zero on NVL-S+ */
+ if (xe_gt_WARN_ON(gt, xe->info.platform < XE_NOVALAKE_S))
+ return -EINVAL;
+
+ num_paging_engines = vf_num_paging_engines;
+ }
+ }
+
+ if (xe_gt_WARN_ON(gt, num_paging_engines > num_copy_engines))
+ return -EINVAL;
+
reserved_logical_bcs_start = num_copy_engines - num_paging_engines;
/* FIXME: Doing a simple logical mapping that works for most hardware */
@@ -696,6 +719,8 @@ static void hw_engine_setup_logical_and_paging_mapping(struct xe_gt *gt)
}
}
}
+
+ return 0;
}
static void read_media_fuses(struct xe_gt *gt)
@@ -914,7 +939,10 @@ int xe_hw_engines_init(struct xe_gt *gt)
return err;
}
- hw_engine_setup_logical_and_paging_mapping(gt);
+ err = hw_engine_setup_logical_and_paging_mapping(gt);
+ if (err)
+ return err;
+
err = xe_hw_engine_setup_groups(gt);
if (err)
return err;