From 6c50df305c7f1d934bfbcc14a9f1077d64f23df7 Mon Sep 17 00:00:00 2001 From: jsg Date: Tue, 13 Aug 2024 00:03:54 +0000 Subject: [PATCH] drm/i915: Bypass LMEMBAR/GTTMMADR for MTL stolen memory access From Ville Syrjala c08c364102d07288610734de34111a666e730ae7 in mainline linux --- sys/dev/pci/drm/i915/gem/i915_gem_stolen.c | 8 ++++++-- sys/dev/pci/drm/i915/gt/intel_ggtt.c | 19 +++++++++++++++++-- sys/dev/pci/drm/i915/i915_reg.h | 3 +++ sys/dev/pci/drm/i915/i915_utils.c | 17 +++++++++++++++++ sys/dev/pci/drm/i915/i915_utils.h | 2 ++ 5 files changed, 45 insertions(+), 4 deletions(-) diff --git a/sys/dev/pci/drm/i915/gem/i915_gem_stolen.c b/sys/dev/pci/drm/i915/gem/i915_gem_stolen.c index b8a19413320..1fdadbd45e8 100644 --- a/sys/dev/pci/drm/i915/gem/i915_gem_stolen.c +++ b/sys/dev/pci/drm/i915/gem/i915_gem_stolen.c @@ -990,8 +990,12 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type, dsm_size = ALIGN_DOWN(lmem_size - dsm_base, SZ_1M); } + if (i915_direct_stolen_access(i915)) { + drm_dbg(&i915->drm, "Using direct DSM access\n"); + io_start = intel_uncore_read64(uncore, GEN12_DSMBASE) & GEN12_BDSM_MASK; + io_size = dsm_size; #ifdef __linux__ - if (pci_resource_len(pdev, GEN12_LMEM_BAR) < lmem_size) { + } else if (pci_resource_len(pdev, GEN12_LMEM_BAR) < lmem_size) { io_start = 0; io_size = 0; } else { @@ -999,7 +1003,7 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type, io_size = dsm_size; } #else - if (lmem_len < lmem_size) { + } else if (lmem_len < lmem_size) { io_start = 0; io_size = 0; } else { diff --git a/sys/dev/pci/drm/i915/gt/intel_ggtt.c b/sys/dev/pci/drm/i915/gt/intel_ggtt.c index 2860d397f8e..14818a3d20b 100644 --- a/sys/dev/pci/drm/i915/gt/intel_ggtt.c +++ b/sys/dev/pci/drm/i915/gt/intel_ggtt.c @@ -24,6 +24,7 @@ #include "intel_ring.h" #include "i915_drv.h" #include "i915_pci.h" +#include "i915_reg.h" #include "i915_request.h" #include "i915_scatterlist.h" #include "i915_utils.h" @@ -1171,13 +1172,20 @@ static unsigned int gen6_gttadr_offset(struct drm_i915_private *i915) static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) { struct drm_i915_private *i915 = ggtt->vm.i915; + struct intel_uncore *uncore = ggtt->vm.gt->uncore; struct pci_dev *pdev = to_pci_dev(i915->drm.dev); phys_addr_t phys_addr; u32 pte_flags; int ret; GEM_WARN_ON(pci_resource_len(pdev, GEN4_GTTMMADR_BAR) != gen6_gttmmadr_size(i915)); - phys_addr = pci_resource_start(pdev, GEN4_GTTMMADR_BAR) + gen6_gttadr_offset(i915); + + if (i915_direct_stolen_access(i915)) { + drm_dbg(&i915->drm, "Using direct GSM access\n"); + phys_addr = intel_uncore_read64(uncore, GEN12_GSMBASE) & GEN12_BDSM_MASK; + } else { + phys_addr = pci_resource_start(pdev, GEN4_GTTMMADR_BAR) + gen6_gttadr_offset(i915); + } if (needs_wc_ggtt_mapping(i915)) ggtt->gsm = ioremap_wc(phys_addr, size); @@ -1216,6 +1224,7 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) { struct drm_i915_private *i915 = ggtt->vm.i915; + struct intel_uncore *uncore = ggtt->vm.gt->uncore; struct pci_dev *pdev = i915->drm.pdev; phys_addr_t phys_addr; bus_addr_t addr; @@ -1232,7 +1241,13 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) return ret; GEM_WARN_ON(len != gen6_gttmmadr_size(i915)); - phys_addr = addr + gen6_gttadr_offset(i915); + + if (i915_direct_stolen_access(i915)) { + drm_dbg(&i915->drm, "Using direct GSM access\n"); + phys_addr = intel_uncore_read64(uncore, GEN12_GSMBASE) & GEN12_BDSM_MASK; + } else { + phys_addr = addr + gen6_gttadr_offset(i915); + } if (needs_wc_ggtt_mapping(i915)) flags = BUS_SPACE_MAP_PREFETCHABLE; diff --git a/sys/dev/pci/drm/i915/i915_reg.h b/sys/dev/pci/drm/i915/i915_reg.h index aefad14ab27..386286356d2 100644 --- a/sys/dev/pci/drm/i915/i915_reg.h +++ b/sys/dev/pci/drm/i915/i915_reg.h @@ -5452,6 +5452,9 @@ #define GEN6_PCODE_FREQ_RING_RATIO_SHIFT 16 #define GEN6_PCODE_DATA1 _MMIO(0x13812C) +#define MTL_PCODE_STOLEN_ACCESS _MMIO(0x138914) +#define STOLEN_ACCESS_ALLOWED 0x1 + /* IVYBRIDGE DPF */ #define GEN7_L3CDERRST1(slice) _MMIO(0xB008 + (slice) * 0x200) /* L3CD Error Status 1 */ #define GEN7_L3CDERRST1_ROW_MASK (0x7ff << 14) diff --git a/sys/dev/pci/drm/i915/i915_utils.c b/sys/dev/pci/drm/i915/i915_utils.c index d742c01214e..95a95731d7d 100644 --- a/sys/dev/pci/drm/i915/i915_utils.c +++ b/sys/dev/pci/drm/i915/i915_utils.c @@ -8,6 +8,7 @@ #include #include "i915_drv.h" +#include "i915_reg.h" #include "i915_utils.h" #include @@ -138,3 +139,19 @@ bool i915_vtd_active(struct drm_i915_private *i915) return i915_run_as_guest(); #endif } + +bool i915_direct_stolen_access(struct drm_i915_private *i915) +{ + /* + * Wa_22018444074 + * + * Access via BAR can hang MTL, go directly to GSM/DSM, + * except for VM guests which won't have access to it. + * + * Normally this would not work but on MTL the system firmware + * should have relaxed the access permissions sufficiently. + * 0x138914==0x1 indicates that the firmware has done its job. + */ + return IS_METEORLAKE(i915) && !i915_run_as_guest() && + intel_uncore_read(&i915->uncore, MTL_PCODE_STOLEN_ACCESS) == STOLEN_ACCESS_ALLOWED; +} diff --git a/sys/dev/pci/drm/i915/i915_utils.h b/sys/dev/pci/drm/i915/i915_utils.h index 026fdb3ed1c..4ee6a182ac1 100644 --- a/sys/dev/pci/drm/i915/i915_utils.h +++ b/sys/dev/pci/drm/i915/i915_utils.h @@ -401,4 +401,6 @@ static inline bool i915_run_as_guest(void) bool i915_vtd_active(struct drm_i915_private *i915); +bool i915_direct_stolen_access(struct drm_i915_private *i915); + #endif /* !__I915_UTILS_H */ -- 2.20.1