This programs the L3 configuration based on the sizes given for each partition as arguments. The relevant register writes are added to the workaround list so that they are re-applied to each context while it's initialized, preventing state leaks from other userspace processes which may have modified the L3 partitioning from its boot-up state, since all relevant registers are part of the software and hardware command checker whitelists. Some userspace clients (DDX and current versions of Mesa not patched with my L3 partitioning series [1]) assume that the L3 configuration, in particular the URB size, comes up in certain state when a context is created, but nothing in the kernel guarantees this assumption, the registers that control the partitioning of the L3 cache were being left untouched. Note that the VLV_L3SQCREG1_SQGHPCI_DEFAULT macro defined here has the same value as the previously defined VLV_B0_WA_L3SQCREG1_VALUE, but the latter will be removed in a future commit. [1] http://lists.freedesktop.org/archives/mesa-dev/2015-September/093550.html Signed-off-by: Francisco Jerez <currojerez@xxxxxxxxxx> --- drivers/gpu/drm/i915/i915_reg.h | 13 ++++++ drivers/gpu/drm/i915/intel_ringbuffer.c | 80 +++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a7c9e8c..663bc8f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5920,11 +5920,21 @@ enum skl_disp_power_wells { # define CHV_HZ_8X8_MODE_IN_1X (1<<15) # define BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE (1<<3) +#define GEN8_L3CNTLREG 0x7034 +#define GEN8_L3CNTLREG_URB_ALLOC(n) ((n) << 1) +#define GEN8_L3CNTLREG_RO_ALLOC(n) ((n) << 11) +#define GEN8_L3CNTLREG_DC_ALLOC(n) ((n) << 18) +#define GEN8_L3CNTLREG_ALL_ALLOC(n) ((n) << 25) + #define GEN9_SLICE_COMMON_ECO_CHICKEN0 0x7308 #define DISABLE_PIXEL_MASK_CAMMING (1<<14) #define GEN7_L3SQCREG1 0xB010 #define VLV_B0_WA_L3SQCREG1_VALUE 0x00D30000 +#define IVB_L3SQCREG1_SQGHPCI_DEFAULT 0x00730000 +#define VLV_L3SQCREG1_SQGHPCI_DEFAULT 0x00D30000 +#define HSW_L3SQCREG1_SQGHPCI_DEFAULT 0x00610000 +#define GEN7_L3SQCREG1_CONV_DC_UC (1 << 24) #define GEN8_L3SQCREG1 0xB100 #define BDW_WA_L3SQCREG1_DEFAULT 0x784000 @@ -5933,6 +5943,9 @@ enum skl_disp_power_wells { #define GEN7_WA_FOR_GEN7_L3_CONTROL 0x3C47FF8C #define GEN7_L3AGDIS (1<<19) #define GEN7_L3CNTLREG2 0xB020 +#define GEN7_L3CNTLREG2_URB_ALLOC(n) ((n) << 1) +#define GEN7_L3CNTLREG2_RO_ALLOC(n) ((n) << 14) +#define GEN7_L3CNTLREG2_DC_ALLOC(n) ((n) << 21) #define GEN7_L3CNTLREG3 0xB024 #define GEN7_L3_CHICKEN_MODE_REGISTER 0xB030 diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 9035f8c..54ca344 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -800,6 +800,86 @@ static int wa_add(struct drm_i915_private *dev_priv, #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val) +/** + * init_l3_partitioning_workarounds - Add L3 partitioning set-up to the WA list. + * + * @ring - Ring to program the L3 partitioning for. + * @n_urb - Number of ways to allocate for the URB. + * @n_ro - Number of ways to allocate for read-only L3 clients. + * @n_dc - Number of ways to allocate for the DC read-write L3 client. + * @n_all - Number of ways to allocate for the common pool shared + * among all L3 clients. + * + * Note that for this to work correctly the L3 cache must be + * completely flushed whenever the workaround list is applied to a + * context. + */ +static int init_l3_partitioning_workarounds(struct intel_engine_cs *ring, + unsigned int n_urb, + unsigned int n_ro, + unsigned int n_dc, + unsigned int n_all) +{ + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + if (INTEL_INFO(dev)->gen >= 8) { + /* + * The ALL partition may not be used simultaneously + * with RO and DC. + */ + BUG_ON(n_all && (n_ro || n_dc)); + + /* Just need to set up the L3 partitioning. */ + WA_WRITE(GEN8_L3CNTLREG, + GEN8_L3CNTLREG_URB_ALLOC(n_urb) | + GEN8_L3CNTLREG_RO_ALLOC(n_ro) | + GEN8_L3CNTLREG_DC_ALLOC(n_dc) | + GEN8_L3CNTLREG_ALL_ALLOC(n_all)); + + } else if (INTEL_INFO(dev)->gen >= 7) { + /* + * Offset applied by the hardware to the number of + * ways allocated to the URB, which is also the + * minimum legal URB allocation. + */ + const unsigned int n0_urb = (IS_VALLEYVIEW(dev) ? 32 : 0); + BUG_ON(n_urb < n0_urb); + + /* The ALL partition is not supported on Gen7. */ + BUG_ON(n_all); + + /* + * Init the L3SQ General and high priority credit + * initialization value to the hardware defaults + * (except for VLV B0 which supposedly defaults to a + * value different to the one we set here), and demote + * the DC to LLC if it has no ways assigned. + * + * WaIncreaseL3CreditsForVLVB0:vlv + */ + WA_WRITE(GEN7_L3SQCREG1, + (IS_HASWELL(dev) ? HSW_L3SQCREG1_SQGHPCI_DEFAULT : + IS_VALLEYVIEW(dev) ? VLV_L3SQCREG1_SQGHPCI_DEFAULT : + IVB_L3SQCREG1_SQGHPCI_DEFAULT) | + (n_dc ? 0 : GEN7_L3SQCREG1_CONV_DC_UC)); + + /* Set up the L3 partitioning. */ + WA_WRITE(GEN7_L3CNTLREG2, + GEN7_L3CNTLREG2_URB_ALLOC(n_urb - n0_urb) | + GEN7_L3CNTLREG2_RO_ALLOC(n_ro) | + GEN7_L3CNTLREG2_DC_ALLOC(n_dc)); + + WA_WRITE(GEN7_L3CNTLREG3, 0); + + } else { + /* No L3 on pre-Gen7 hardware. */ + BUG(); + } + + return 0; +} + static int gen8_init_workarounds(struct intel_engine_cs *ring) { struct drm_device *dev = ring->dev; -- 2.5.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx