Commit 564d64f8 authored by Lucas De Marchi's avatar Lucas De Marchi Committed by Rodrigo Vivi

drm/xe/mcr: Add SQIDI steering for DG2

Like detailed in commit 927dfdd0 ("drm/i915/dg2: Add SQIDI
steering"), some registers are expected to have the selector
initialized just once and never set to anything else. For xe, the
registers with SQIDI replication type (SF and MCFG) were missing,
resulting in warnings like:

	[  410.685565] xe 0000:03:00.0: Did not find MCR register 0x8724 in any MCR steering table

While adding these registers, abstract the handling for
"dg2_gam_ranges", moving them together with SF/MCFG to a dedicated
table. This also avoids that range to be checked for platforms other
than DG2. For DG2, this is the new steering output:

	# cat /sys/kernel/debug/dri/0/gt0/steering
	...
	IMPLICIT steering: group=0x0, instance=0x0
		0x000b00 - 0x000bff
		0x001000 - 0x001fff
		0x004000 - 0x004aff
		0x008700 - 0x0087ff
		0x00c800 - 0x00cfff
		0x00f000 - 0x00ffff
Signed-off-by: default avatarLucas De Marchi <lucas.demarchi@intel.com>
Reviewed-by: default avatarMatt Roper <matthew.d.roper@intel.com>
Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
parent 3319b213
......@@ -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);
......
......@@ -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);
}
......
......@@ -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);
......
......@@ -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
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment