aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson2012-11-15 05:32:18 -0600
committerGreg Kroah-Hartman2013-05-11 15:54:00 -0500
commite7066b70bb8f147cda6fe039006bafee89128136 (patch)
treeebbcce1f170c48890ad2181f1ed193759711eee7
parent294b04d109ad9654f0f6608e7963a2f821d784c5 (diff)
downloadkernel-omap-e7066b70bb8f147cda6fe039006bafee89128136.tar.gz
kernel-omap-e7066b70bb8f147cda6fe039006bafee89128136.tar.xz
kernel-omap-e7066b70bb8f147cda6fe039006bafee89128136.zip
drm/i915: Fix detection of base of stolen memory
commit e12a2d53ae45a69aea499b64f75e7222cca0f12f upstream. The routine to query the base of stolen memory was using the wrong registers and the wrong encodings on virtually every platform. It was not until the G33 refresh, that a PCI config register was introduced that explicitly said where the stolen memory was. Prior to 865G there was not even a register that said where the end of usable low memory was and where the stolen memory began (or ended depending upon chipset). Before then, one has to look at the BIOS memory maps to find the Top of Memory. Alas that is not exported by arch/x86 and so we have to resort to disabling stolen memory on gen2 for the time being. Then SandyBridge enlarged the PCI register to a full 32-bits and change the encoding of the address, so even though we happened to be querying the right register, we read the wrong bits and ended up using address 0 for our stolen data, i.e. notably FBC. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1
-rw-r--r--drivers/gpu/drm/i915/i915_gem_stolen.c81
2 files changed, 42 insertions, 40 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7339a4b89d5f..7c3c179a784f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -774,6 +774,7 @@ typedef struct drm_i915_private {
774 unsigned long gtt_start; 774 unsigned long gtt_start;
775 unsigned long gtt_mappable_end; 775 unsigned long gtt_mappable_end;
776 unsigned long gtt_end; 776 unsigned long gtt_end;
777 unsigned long stolen_base; /* limited to low memory (32-bit) */
777 778
778 struct io_mapping *gtt_mapping; 779 struct io_mapping *gtt_mapping;
779 phys_addr_t gtt_base_addr; 780 phys_addr_t gtt_base_addr;
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index 8e91083b126f..be24312cd32f 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -42,56 +42,50 @@
42 * for is a boon. 42 * for is a boon.
43 */ 43 */
44 44
45#define PTE_ADDRESS_MASK 0xfffff000 45static unsigned long i915_stolen_to_physical(struct drm_device *dev)
46#define PTE_ADDRESS_MASK_HIGH 0x000000f0 /* i915+ */
47#define PTE_MAPPING_TYPE_UNCACHED (0 << 1)
48#define PTE_MAPPING_TYPE_DCACHE (1 << 1) /* i830 only */
49#define PTE_MAPPING_TYPE_CACHED (3 << 1)
50#define PTE_MAPPING_TYPE_MASK (3 << 1)
51#define PTE_VALID (1 << 0)
52
53/**
54 * i915_stolen_to_phys - take an offset into stolen memory and turn it into
55 * a physical one
56 * @dev: drm device
57 * @offset: address to translate
58 *
59 * Some chip functions require allocations from stolen space and need the
60 * physical address of the memory in question.
61 */
62static unsigned long i915_stolen_to_phys(struct drm_device *dev, u32 offset)
63{ 46{
64 struct drm_i915_private *dev_priv = dev->dev_private; 47 struct drm_i915_private *dev_priv = dev->dev_private;
65 struct pci_dev *pdev = dev_priv->bridge_dev; 48 struct pci_dev *pdev = dev_priv->bridge_dev;
66 u32 base; 49 u32 base;
67 50
68#if 0
69 /* On the machines I have tested the Graphics Base of Stolen Memory 51 /* On the machines I have tested the Graphics Base of Stolen Memory
70 * is unreliable, so compute the base by subtracting the stolen memory 52 * is unreliable, so on those compute the base by subtracting the
71 * from the Top of Low Usable DRAM which is where the BIOS places 53 * stolen memory from the Top of Low Usable DRAM which is where the
72 * the graphics stolen memory. 54 * BIOS places the graphics stolen memory.
55 *
56 * On gen2, the layout is slightly different with the Graphics Segment
57 * immediately following Top of Memory (or Top of Usable DRAM). Note
58 * it appears that TOUD is only reported by 865g, so we just use the
59 * top of memory as determined by the e820 probe.
60 *
61 * XXX gen2 requires an unavailable symbol and 945gm fails with
62 * its value of TOLUD.
73 */ 63 */
74 if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) { 64 base = 0;
75 /* top 32bits are reserved = 0 */ 65 if (INTEL_INFO(dev)->gen >= 6) {
66 /* Read Base Data of Stolen Memory Register (BDSM) directly.
67 * Note that there is also a MCHBAR miror at 0x1080c0 or
68 * we could use device 2:0x5c instead.
69 */
70 pci_read_config_dword(pdev, 0xB0, &base);
71 base &= ~4095; /* lower bits used for locking register */
72 } else if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
73 /* Read Graphics Base of Stolen Memory directly */
76 pci_read_config_dword(pdev, 0xA4, &base); 74 pci_read_config_dword(pdev, 0xA4, &base);
77 } else { 75#if 0
78 /* XXX presume 8xx is the same as i915 */ 76 } else if (IS_GEN3(dev)) {
79 pci_bus_read_config_dword(pdev->bus, 2, 0x5C, &base);
80 }
81#else
82 if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
83 u16 val;
84 pci_read_config_word(pdev, 0xb0, &val);
85 base = val >> 4 << 20;
86 } else {
87 u8 val; 77 u8 val;
78 /* Stolen is immediately below Top of Low Usable DRAM */
88 pci_read_config_byte(pdev, 0x9c, &val); 79 pci_read_config_byte(pdev, 0x9c, &val);
89 base = val >> 3 << 27; 80 base = val >> 3 << 27;
90 } 81 base -= dev_priv->mm.gtt->stolen_size;
91 base -= dev_priv->mm.gtt->stolen_size; 82 } else {
83 /* Stolen is immediately above Top of Memory */
84 base = max_low_pfn_mapped << PAGE_SHIFT;
92#endif 85#endif
86 }
93 87
94 return base + offset; 88 return base;
95} 89}
96 90
97static void i915_warn_stolen(struct drm_device *dev) 91static void i915_warn_stolen(struct drm_device *dev)
@@ -116,7 +110,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
116 if (!compressed_fb) 110 if (!compressed_fb)
117 goto err; 111 goto err;
118 112
119 cfb_base = i915_stolen_to_phys(dev, compressed_fb->start); 113 cfb_base = dev_priv->mm.stolen_base + compressed_fb->start;
120 if (!cfb_base) 114 if (!cfb_base)
121 goto err_fb; 115 goto err_fb;
122 116
@@ -129,7 +123,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
129 if (!compressed_llb) 123 if (!compressed_llb)
130 goto err_fb; 124 goto err_fb;
131 125
132 ll_base = i915_stolen_to_phys(dev, compressed_llb->start); 126 ll_base = dev_priv->mm.stolen_base + compressed_llb->start;
133 if (!ll_base) 127 if (!ll_base)
134 goto err_llb; 128 goto err_llb;
135 } 129 }
@@ -148,7 +142,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
148 } 142 }
149 143
150 DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", 144 DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n",
151 cfb_base, ll_base, size >> 20); 145 (long)cfb_base, (long)ll_base, size >> 20);
152 return; 146 return;
153 147
154err_llb: 148err_llb:
@@ -180,6 +174,13 @@ int i915_gem_init_stolen(struct drm_device *dev)
180 struct drm_i915_private *dev_priv = dev->dev_private; 174 struct drm_i915_private *dev_priv = dev->dev_private;
181 unsigned long prealloc_size = dev_priv->mm.gtt->stolen_size; 175 unsigned long prealloc_size = dev_priv->mm.gtt->stolen_size;
182 176
177 dev_priv->mm.stolen_base = i915_stolen_to_physical(dev);
178 if (dev_priv->mm.stolen_base == 0)
179 return 0;
180
181 DRM_DEBUG_KMS("found %d bytes of stolen memory at %08lx\n",
182 dev_priv->mm.gtt->stolen_size, dev_priv->mm.stolen_base);
183
183 /* Basic memrange allocator for stolen space */ 184 /* Basic memrange allocator for stolen space */
184 drm_mm_init(&dev_priv->mm.stolen, 0, prealloc_size); 185 drm_mm_init(&dev_priv->mm.stolen, 0, prealloc_size);
185 186