aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/xe/xe_gt_mcr.c40
-rw-r--r--drivers/gpu/drm/xe/xe_gt_types.h6
-rw-r--r--drivers/gpu/drm/xe/xe_guc_hwconfig.c40
-rw-r--r--drivers/gpu/drm/xe/xe_guc_hwconfig.h1
4 files changed, 83 insertions, 4 deletions
diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.c b/drivers/gpu/drm/xe/xe_gt_mcr.c
index 6d948a469126..7d7bd0be6233 100644
--- a/drivers/gpu/drm/xe/xe_gt_mcr.c
+++ b/drivers/gpu/drm/xe/xe_gt_mcr.c
@@ -8,8 +8,10 @@
#include "regs/xe_gt_regs.h"
#include "xe_assert.h"
#include "xe_gt.h"
+#include "xe_gt_printk.h"
#include "xe_gt_topology.h"
#include "xe_gt_types.h"
+#include "xe_guc_hwconfig.h"
#include "xe_mmio.h"
#include "xe_sriov.h"
@@ -297,6 +299,36 @@ static void init_steering_mslice(struct xe_gt *gt)
static unsigned int dss_per_group(struct xe_gt *gt)
{
+ struct xe_guc *guc = &gt->uc.guc;
+ u32 max_slices = 0, max_subslices = 0;
+ int ret;
+
+ /*
+ * Try to query the GuC's hwconfig table for the maximum number of
+ * slices and subslices. These don't reflect the platform's actual
+ * slice/DSS counts, just the physical layout by which we should
+ * determine the steering targets. On older platforms with older GuC
+ * firmware releases it's possible that these attributes may not be
+ * included in the table, so we can always fall back to the old
+ * hardcoded layouts.
+ */
+#define HWCONFIG_ATTR_MAX_SLICES 1
+#define HWCONFIG_ATTR_MAX_SUBSLICES 70
+
+ ret = xe_guc_hwconfig_lookup_u32(guc, HWCONFIG_ATTR_MAX_SLICES,
+ &max_slices);
+ if (ret < 0 || max_slices == 0)
+ goto fallback;
+
+ ret = xe_guc_hwconfig_lookup_u32(guc, HWCONFIG_ATTR_MAX_SUBSLICES,
+ &max_subslices);
+ if (ret < 0 || max_subslices == 0)
+ goto fallback;
+
+ return DIV_ROUND_UP(max_subslices, max_slices);
+
+fallback:
+ xe_gt_dbg(gt, "GuC hwconfig cannot provide dss/slice; using typical fallback values\n");
if (gt_to_xe(gt)->info.platform == XE_PVC)
return 8;
else if (GRAPHICS_VERx100(gt_to_xe(gt)) >= 1250)
@@ -314,16 +346,16 @@ static unsigned int dss_per_group(struct xe_gt *gt)
*/
void xe_gt_mcr_get_dss_steering(struct xe_gt *gt, unsigned int dss, u16 *group, u16 *instance)
{
- int dss_per_grp = dss_per_group(gt);
-
xe_gt_assert(gt, dss < XE_MAX_DSS_FUSE_BITS);
- *group = dss / dss_per_grp;
- *instance = dss % dss_per_grp;
+ *group = dss / gt->steering_dss_per_grp;
+ *instance = dss % gt->steering_dss_per_grp;
}
static void init_steering_dss(struct xe_gt *gt)
{
+ gt->steering_dss_per_grp = dss_per_group(gt);
+
xe_gt_mcr_get_dss_steering(gt,
min(xe_dss_mask_group_ffs(gt->fuse_topo.g_dss_mask, 0, 0),
xe_dss_mask_group_ffs(gt->fuse_topo.c_dss_mask, 0, 0)),
diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h
index 8e46c0969bc7..82cf9f631736 100644
--- a/drivers/gpu/drm/xe/xe_gt_types.h
+++ b/drivers/gpu/drm/xe/xe_gt_types.h
@@ -377,6 +377,12 @@ struct xe_gt {
} steering[NUM_STEERING_TYPES];
/**
+ * @steering_dss_per_grp: number of DSS per steering group (gslice,
+ * cslice, etc.).
+ */
+ unsigned int steering_dss_per_grp;
+
+ /**
* @mcr_lock: protects the MCR_SELECTOR register for the duration
* of a steered operation
*/
diff --git a/drivers/gpu/drm/xe/xe_guc_hwconfig.c b/drivers/gpu/drm/xe/xe_guc_hwconfig.c
index 025bad701556..af2c817d552c 100644
--- a/drivers/gpu/drm/xe/xe_guc_hwconfig.c
+++ b/drivers/gpu/drm/xe/xe_guc_hwconfig.c
@@ -160,3 +160,43 @@ void xe_guc_hwconfig_dump(struct xe_guc *guc, struct drm_printer *p)
kfree(hwconfig);
}
+
+/*
+ * Lookup a specific 32-bit attribute value in the GuC's hwconfig table.
+ */
+int xe_guc_hwconfig_lookup_u32(struct xe_guc *guc, u32 attribute, u32 *val)
+{
+ size_t size = xe_guc_hwconfig_size(guc);
+ u64 num_dw = div_u64(size, sizeof(u32));
+ u32 *hwconfig;
+ bool found = false;
+ int i = 0;
+
+ if (num_dw == 0)
+ return -EINVAL;
+
+ hwconfig = kzalloc(size, GFP_KERNEL);
+ if (!hwconfig)
+ return -ENOMEM;
+
+ xe_guc_hwconfig_copy(guc, hwconfig);
+
+ /* An entry requires at least three dwords for key, length, value */
+ while (i + 3 <= num_dw) {
+ u32 key = hwconfig[i++];
+ u32 len_dw = hwconfig[i++];
+
+ if (key != attribute) {
+ i += len_dw;
+ continue;
+ }
+
+ *val = hwconfig[i];
+ found = true;
+ break;
+ }
+
+ kfree(hwconfig);
+
+ return found ? 0 : -ENOENT;
+}
diff --git a/drivers/gpu/drm/xe/xe_guc_hwconfig.h b/drivers/gpu/drm/xe/xe_guc_hwconfig.h
index 7df315900e1c..ab4e5038236e 100644
--- a/drivers/gpu/drm/xe/xe_guc_hwconfig.h
+++ b/drivers/gpu/drm/xe/xe_guc_hwconfig.h
@@ -15,5 +15,6 @@ int xe_guc_hwconfig_init(struct xe_guc *guc);
u32 xe_guc_hwconfig_size(struct xe_guc *guc);
void xe_guc_hwconfig_copy(struct xe_guc *guc, void *dst);
void xe_guc_hwconfig_dump(struct xe_guc *guc, struct drm_printer *p);
+int xe_guc_hwconfig_lookup_u32(struct xe_guc *guc, u32 attribute, u32 *val);
#endif