summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/xe
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/xe')
-rw-r--r--drivers/gpu/drm/xe/xe_gt.c2
-rw-r--r--drivers/gpu/drm/xe/xe_gt_mcr.c80
-rw-r--r--drivers/gpu/drm/xe/xe_gt_mcr.h2
-rw-r--r--drivers/gpu/drm/xe/xe_gt_types.h7
4 files changed, 59 insertions, 32 deletions
diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
index 0e0d5cadb3e7..20dbc08d3685 100644
--- a/drivers/gpu/drm/xe/xe_gt.c
+++ b/drivers/gpu/drm/xe/xe_gt.c
@@ -500,6 +500,7 @@ static int all_fw_domain_init(struct xe_gt *gt)
if (err)
goto err_hw_fence_irq;
+ xe_gt_mcr_set_implicit_defaults(gt);
xe_reg_sr_apply_mmio(&gt->reg_sr, gt);
err = xe_gt_clock_init(gt);
@@ -633,6 +634,7 @@ static int do_gt_restart(struct xe_gt *gt)
setup_private_ppat(gt);
+ xe_gt_mcr_set_implicit_defaults(gt);
xe_reg_sr_apply_mmio(&gt->reg_sr, gt);
err = xe_wopcm_init(&gt->uc.wopcm);
diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.c b/drivers/gpu/drm/xe/xe_gt_mcr.c
index d7c89f7b56e2..bb71071c3435 100644
--- a/drivers/gpu/drm/xe/xe_gt_mcr.c
+++ b/drivers/gpu/drm/xe/xe_gt_mcr.c
@@ -155,15 +155,13 @@ static const struct xe_mmio_range xelpmp_oaddrm_steering_table[] = {
{},
};
-/*
- * DG2 GAM registers are a special case; this table is checked directly in
- * xe_gt_mcr_get_nonterminated_steering and is not hooked up via
- * gt->steering[].
- */
-static const struct xe_mmio_range dg2_gam_ranges[] = {
- { 0x004000, 0x004AFF },
- { 0x00C800, 0x00CFFF },
- { 0x00F000, 0x00FFFF },
+static const struct xe_mmio_range dg2_implicit_steering_table[] = {
+ { 0x000B00, 0x000BFF }, /* SF (SQIDI replication) */
+ { 0x001000, 0x001FFF }, /* SF (SQIDI replication) */
+ { 0x004000, 0x004AFF }, /* GAM (MSLICE replication) */
+ { 0x008700, 0x0087FF }, /* MCFG (SQIDI replication) */
+ { 0x00C800, 0x00CFFF }, /* GAM (MSLICE replication) */
+ { 0x00F000, 0x00FFFF }, /* GAM (MSLICE replication) */
{},
};
@@ -255,12 +253,14 @@ static const struct {
[DSS] = { "DSS", init_steering_dss },
[OADDRM] = { "OADDRM", init_steering_oaddrm },
[INSTANCE0] = { "INSTANCE 0", init_steering_inst0 },
+ [IMPLICIT_STEERING] = { "IMPLICIT", NULL },
};
void xe_gt_mcr_init(struct xe_gt *gt)
{
struct xe_device *xe = gt_to_xe(gt);
+ BUILD_BUG_ON(IMPLICIT_STEERING + 1 != NUM_STEERING_TYPES);
BUILD_BUG_ON(ARRAY_SIZE(xe_steering_types) != NUM_STEERING_TYPES);
spin_lock_init(&gt->mcr_lock);
@@ -280,6 +280,7 @@ void xe_gt_mcr_init(struct xe_gt *gt)
gt->steering[MSLICE].ranges = xehp_mslice_steering_table;
gt->steering[LNCF].ranges = xehp_lncf_steering_table;
gt->steering[DSS].ranges = xehp_dss_steering_table;
+ gt->steering[IMPLICIT_STEERING].ranges = dg2_implicit_steering_table;
} else {
gt->steering[L3BANK].ranges = xelp_l3bank_steering_table;
gt->steering[DSS].ranges = xelp_dss_steering_table;
@@ -291,6 +292,33 @@ void xe_gt_mcr_init(struct xe_gt *gt)
xe_steering_types[i].init(gt);
}
+/**
+ * xe_gt_mcr_set_implicit_defaults - Initialize steer control registers
+ * @gt: GT structure
+ *
+ * Some register ranges don't need to have their steering control registers
+ * changed on each access - it's sufficient to set them once on initialization.
+ * This function sets those registers for each platform *
+ */
+void xe_gt_mcr_set_implicit_defaults(struct xe_gt *gt)
+{
+ struct xe_device *xe = gt_to_xe(gt);
+
+ if (xe->info.platform == XE_DG2) {
+ u32 steer_val = REG_FIELD_PREP(GEN11_MCR_SLICE_MASK, 0) |
+ REG_FIELD_PREP(GEN11_MCR_SUBSLICE_MASK, 2);
+
+ xe_mmio_write32(gt, MCFG_MCR_SELECTOR.reg, steer_val);
+ xe_mmio_write32(gt, SF_MCR_SELECTOR.reg, steer_val);
+ /*
+ * For GAM registers, all reads should be directed to instance 1
+ * (unicast reads against other instances are not allowed),
+ * and instance 1 is already the hardware's default steering
+ * target, which we never change
+ */
+ }
+}
+
/*
* xe_gt_mcr_get_nonterminated_steering - find group/instance values that
* will steer a register to a non-terminated instance
@@ -305,14 +333,15 @@ void xe_gt_mcr_init(struct xe_gt *gt)
* steering.
*
* Returns true if the caller should steer to the @group/@instance values
- * returned. Returns false if the caller need not perform any steering (i.e.,
- * the DG2 GAM range special case).
+ * returned. Returns false if the caller need not perform any steering
*/
static bool xe_gt_mcr_get_nonterminated_steering(struct xe_gt *gt,
i915_mcr_reg_t reg,
u8 *group, u8 *instance)
{
- for (int type = 0; type < NUM_STEERING_TYPES; type++) {
+ const struct xe_mmio_range *implicit_ranges;
+
+ for (int type = 0; type < IMPLICIT_STEERING; type++) {
if (!gt->steering[type].ranges)
continue;
@@ -325,27 +354,15 @@ static bool xe_gt_mcr_get_nonterminated_steering(struct xe_gt *gt,
}
}
- /*
- * All MCR registers should usually be part of one of the steering
- * ranges we're tracking. However there's one special case: DG2
- * GAM registers are technically multicast registers, but are special
- * in a number of ways:
- * - they have their own dedicated steering control register (they
- * don't share 0xFDC with other MCR classes)
- * - all reads should be directed to instance 1 (unicast reads against
- * other instances are not allowed), and instance 1 is already the
- * the hardware's default steering target, which we never change
- *
- * Ultimately this means that we can just treat them as if they were
- * unicast registers and all operations will work properly.
- */
- for (int i = 0; dg2_gam_ranges[i].end > 0; i++)
- if (xe_mmio_in_range(&dg2_gam_ranges[i], reg.reg))
- return false;
+ implicit_ranges = gt->steering[IMPLICIT_STEERING].ranges;
+ if (implicit_ranges)
+ for (int i = 0; implicit_ranges[i].end > 0; i++)
+ if (xe_mmio_in_range(&implicit_ranges[i], reg.reg))
+ return false;
/*
- * Not found in a steering table and not a DG2 GAM register? We'll
- * just steer to 0/0 as a guess and raise a warning.
+ * Not found in a steering table and not a register with implicit
+ * steering. Just steer to 0/0 as a guess and raise a warning.
*/
drm_WARN(&gt_to_xe(gt)->drm, true,
"Did not find MCR register %#x in any MCR steering table\n",
@@ -467,7 +484,6 @@ u32 xe_gt_mcr_unicast_read_any(struct xe_gt *gt, i915_mcr_reg_t reg)
group, instance, 0);
mcr_unlock(gt);
} else {
- /* DG2 GAM special case rules; treat as if unicast */
val = xe_mmio_read32(gt, reg.reg);
}
diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.h b/drivers/gpu/drm/xe/xe_gt_mcr.h
index 62ec6eb654a0..c31987d2177c 100644
--- a/drivers/gpu/drm/xe/xe_gt_mcr.h
+++ b/drivers/gpu/drm/xe/xe_gt_mcr.h
@@ -13,6 +13,8 @@ struct xe_gt;
void xe_gt_mcr_init(struct xe_gt *gt);
+void xe_gt_mcr_set_implicit_defaults(struct xe_gt *gt);
+
u32 xe_gt_mcr_unicast_read(struct xe_gt *gt, i915_mcr_reg_t reg,
int group, int instance);
u32 xe_gt_mcr_unicast_read_any(struct xe_gt *gt, i915_mcr_reg_t reg);
diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h
index a40fab262ac9..b01edd3fdc4d 100644
--- a/drivers/gpu/drm/xe/xe_gt_types.h
+++ b/drivers/gpu/drm/xe/xe_gt_types.h
@@ -66,6 +66,13 @@ enum xe_steering_type {
*/
INSTANCE0,
+ /*
+ * Register ranges that don't need special steering for each register:
+ * it's sufficient to keep the HW-default for the selector, or only
+ * change it once, on GT initialization. This needs to be the last
+ * steering type.
+ */
+ IMPLICIT_STEERING,
NUM_STEERING_TYPES
};