diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h index 4ee88f629c02..daef5f66955a 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -456,6 +456,10 @@ #define XEHPC_L3CLOS_MASK(i) XE_REG_MCR(0xb194 + (i) * 8) +#define L2COMPUTESIDECTRL XE_REG_MCR(0xb1c0) +#define CECTRL REG_GENMASK(2, 1) +#define CECTRL_CENODATA_ALWAYS REG_FIELD_PREP(CECTRL, 0x0) + #define XE2_GLOBAL_INVAL XE_REG(0xb404) #define XE2LPM_L3SQCREG2 XE_REG_MCR(0xb604) diff --git a/drivers/gpu/drm/xe/xe_device_wa_oob.rules b/drivers/gpu/drm/xe/xe_device_wa_oob.rules index 55ba01bc8f38..d129cddb6ead 100644 --- a/drivers/gpu/drm/xe/xe_device_wa_oob.rules +++ b/drivers/gpu/drm/xe/xe_device_wa_oob.rules @@ -3,3 +3,4 @@ PLATFORM(PANTHERLAKE) 22019338487_display PLATFORM(LUNARLAKE) 14022085890 SUBPLATFORM(BATTLEMAGE, G21) +14026539277 PLATFORM(NOVALAKE_P), PLATFORM_STEP(A0, B0) diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index f3bb856aad2a..bae895fa066a 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -10,6 +10,7 @@ #include #include +#include #include #include "instructions/xe_alu_commands.h" @@ -451,6 +452,35 @@ int xe_gt_record_default_lrcs(struct xe_gt *gt) return err; } +static void wa_14026539277(struct xe_gt *gt) +{ + struct xe_device *xe = gt_to_xe(gt); + u32 val; + + /* + * FIXME: We currently can't use FUNC(xe_rtp_match_not_sriov_vf) in the + * rules for Wa_14026539277 due to xe_wa_process_device_oob() being + * called before xe_sriov_probe_early(); and we can't move the call to + * the former to happen after the latter because MMIO read functions + * already depend on a device OOB workaround. This needs to be fixed by + * allowing workaround checks to happen at different stages of driver + * initialization. + */ + if (IS_SRIOV_VF(xe)) + return; + + if (!XE_DEVICE_WA(xe, 14026539277)) + return; + + if (!xe_gt_is_main_type(gt)) + return; + + val = xe_gt_mcr_unicast_read_any(gt, L2COMPUTESIDECTRL); + val &= ~CECTRL; + val |= CECTRL_CENODATA_ALWAYS; + xe_gt_mcr_multicast_write(gt, L2COMPUTESIDECTRL, val); +} + int xe_gt_init_early(struct xe_gt *gt) { int err; @@ -576,6 +606,15 @@ static int gt_init_with_gt_forcewake(struct xe_gt *gt) */ gt->info.gmdid = xe_mmio_read32(>->mmio, GMD_ID); + /* + * Wa_14026539277 can't be implemented as a regular GT workaround (i.e. + * as an entry in gt_was[]) for two reasons: it is actually a device + * workaround that happens to involve programming a GT register; and it + * needs to be applied early to avoid getting the hardware in a bad + * state before we have a chance to do the necessary programming. + */ + wa_14026539277(gt); + return 0; }