drm/i915: Bypass LMEMBAR/GTTMMADR for MTL stolen memory access
authorjsg <jsg@openbsd.org>
Tue, 13 Aug 2024 00:03:54 +0000 (00:03 +0000)
committerjsg <jsg@openbsd.org>
Tue, 13 Aug 2024 00:03:54 +0000 (00:03 +0000)
From Ville Syrjala
c08c364102d07288610734de34111a666e730ae7 in mainline linux

sys/dev/pci/drm/i915/gem/i915_gem_stolen.c
sys/dev/pci/drm/i915/gt/intel_ggtt.c
sys/dev/pci/drm/i915/i915_reg.h
sys/dev/pci/drm/i915/i915_utils.c
sys/dev/pci/drm/i915/i915_utils.h

index b8a1941..1fdadbd 100644 (file)
@@ -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 {
index 2860d39..14818a3 100644 (file)
@@ -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;
index aefad14..3862863 100644 (file)
 #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)
index d742c01..95a9573 100644 (file)
@@ -8,6 +8,7 @@
 #include <drm/drm_drv.h>
 
 #include "i915_drv.h"
+#include "i915_reg.h"
 #include "i915_utils.h"
 
 #include <sys/syslog.h>
@@ -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;
+}
index 026fdb3..4ee6a18 100644 (file)
@@ -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 */