aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2013-07-26 16:32:52 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-09-03 13:17:57 -0400
commit814c5f1f52a4beb3710317022acd6ad34fc0b6b9 (patch)
tree44af740be6678ecf2eb47f99a6bfa97852308617
parenta0a1807544fe59b42d3760ee912ea4c6741298f5 (diff)
x86: add early quirk for reserving Intel graphics stolen memory v5
Systems with Intel graphics controllers set aside memory exclusively for gfx driver use. This memory is not always marked in the E820 as reserved or as RAM, and so is subject to overlap from E820 manipulation later in the boot process. On some systems, MMIO space is allocated on top, despite the efforts of the "RAM buffer" approach, which simply rounds memory boundaries up to 64M to try to catch space that may decode as RAM and so is not suitable for MMIO. v2: use read_pci_config for 32 bit reads instead of adding a new one (Chris) add gen6 stolen size function (Chris) v3: use a function pointer (Chris) drop gen2 bits (Daniel) v4: call e820_sanitize_map after adding the region v5: fixup comments (Peter) simplify loop (Chris) Acked-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Acked-by: H. Peter Anvin <hpa@zytor.com> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=66726 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=66844 Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--arch/x86/kernel/early-quirks.c154
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h15
-rw-r--r--include/drm/i915_drm.h32
3 files changed, 186 insertions, 15 deletions
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index 63bdb29b2549..b3cd3ebae077 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -12,6 +12,7 @@
12#include <linux/pci.h> 12#include <linux/pci.h>
13#include <linux/acpi.h> 13#include <linux/acpi.h>
14#include <linux/pci_ids.h> 14#include <linux/pci_ids.h>
15#include <drm/i915_drm.h>
15#include <asm/pci-direct.h> 16#include <asm/pci-direct.h>
16#include <asm/dma.h> 17#include <asm/dma.h>
17#include <asm/io_apic.h> 18#include <asm/io_apic.h>
@@ -216,6 +217,157 @@ static void __init intel_remapping_check(int num, int slot, int func)
216 217
217} 218}
218 219
220/*
221 * Systems with Intel graphics controllers set aside memory exclusively
222 * for gfx driver use. This memory is not marked in the E820 as reserved
223 * or as RAM, and so is subject to overlap from E820 manipulation later
224 * in the boot process. On some systems, MMIO space is allocated on top,
225 * despite the efforts of the "RAM buffer" approach, which simply rounds
226 * memory boundaries up to 64M to try to catch space that may decode
227 * as RAM and so is not suitable for MMIO.
228 *
229 * And yes, so far on current devices the base addr is always under 4G.
230 */
231static u32 __init intel_stolen_base(int num, int slot, int func)
232{
233 u32 base;
234
235 /*
236 * For the PCI IDs in this quirk, the stolen base is always
237 * in 0x5c, aka the BDSM register (yes that's really what
238 * it's called).
239 */
240 base = read_pci_config(num, slot, func, 0x5c);
241 base &= ~((1<<20) - 1);
242
243 return base;
244}
245
246#define KB(x) ((x) * 1024)
247#define MB(x) (KB (KB (x)))
248#define GB(x) (MB (KB (x)))
249
250static size_t __init gen3_stolen_size(int num, int slot, int func)
251{
252 size_t stolen_size;
253 u16 gmch_ctrl;
254
255 gmch_ctrl = read_pci_config_16(0, 0, 0, I830_GMCH_CTRL);
256
257 switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
258 case I855_GMCH_GMS_STOLEN_1M:
259 stolen_size = MB(1);
260 break;
261 case I855_GMCH_GMS_STOLEN_4M:
262 stolen_size = MB(4);
263 break;
264 case I855_GMCH_GMS_STOLEN_8M:
265 stolen_size = MB(8);
266 break;
267 case I855_GMCH_GMS_STOLEN_16M:
268 stolen_size = MB(16);
269 break;
270 case I855_GMCH_GMS_STOLEN_32M:
271 stolen_size = MB(32);
272 break;
273 case I915_GMCH_GMS_STOLEN_48M:
274 stolen_size = MB(48);
275 break;
276 case I915_GMCH_GMS_STOLEN_64M:
277 stolen_size = MB(64);
278 break;
279 case G33_GMCH_GMS_STOLEN_128M:
280 stolen_size = MB(128);
281 break;
282 case G33_GMCH_GMS_STOLEN_256M:
283 stolen_size = MB(256);
284 break;
285 case INTEL_GMCH_GMS_STOLEN_96M:
286 stolen_size = MB(96);
287 break;
288 case INTEL_GMCH_GMS_STOLEN_160M:
289 stolen_size = MB(160);
290 break;
291 case INTEL_GMCH_GMS_STOLEN_224M:
292 stolen_size = MB(224);
293 break;
294 case INTEL_GMCH_GMS_STOLEN_352M:
295 stolen_size = MB(352);
296 break;
297 default:
298 stolen_size = 0;
299 break;
300 }
301
302 return stolen_size;
303}
304
305static size_t __init gen6_stolen_size(int num, int slot, int func)
306{
307 u16 gmch_ctrl;
308
309 gmch_ctrl = read_pci_config_16(num, slot, func, SNB_GMCH_CTRL);
310 gmch_ctrl >>= SNB_GMCH_GMS_SHIFT;
311 gmch_ctrl &= SNB_GMCH_GMS_MASK;
312
313 return gmch_ctrl << 25; /* 32 MB units */
314}
315
316typedef size_t (*stolen_size_fn)(int num, int slot, int func);
317
318static struct pci_device_id intel_stolen_ids[] __initdata = {
319 INTEL_I915G_IDS(gen3_stolen_size),
320 INTEL_I915GM_IDS(gen3_stolen_size),
321 INTEL_I945G_IDS(gen3_stolen_size),
322 INTEL_I945GM_IDS(gen3_stolen_size),
323 INTEL_VLV_M_IDS(gen3_stolen_size),
324 INTEL_VLV_D_IDS(gen3_stolen_size),
325 INTEL_PINEVIEW_IDS(gen3_stolen_size),
326 INTEL_I965G_IDS(gen3_stolen_size),
327 INTEL_G33_IDS(gen3_stolen_size),
328 INTEL_I965GM_IDS(gen3_stolen_size),
329 INTEL_GM45_IDS(gen3_stolen_size),
330 INTEL_G45_IDS(gen3_stolen_size),
331 INTEL_IRONLAKE_D_IDS(gen3_stolen_size),
332 INTEL_IRONLAKE_M_IDS(gen3_stolen_size),
333 INTEL_SNB_D_IDS(gen6_stolen_size),
334 INTEL_SNB_M_IDS(gen6_stolen_size),
335 INTEL_IVB_M_IDS(gen6_stolen_size),
336 INTEL_IVB_D_IDS(gen6_stolen_size),
337 INTEL_HSW_D_IDS(gen6_stolen_size),
338 INTEL_HSW_M_IDS(gen6_stolen_size),
339};
340
341static void __init intel_graphics_stolen(int num, int slot, int func)
342{
343 size_t size;
344 int i;
345 u32 start;
346 u16 device, subvendor, subdevice;
347
348 device = read_pci_config_16(num, slot, func, PCI_DEVICE_ID);
349 subvendor = read_pci_config_16(num, slot, func,
350 PCI_SUBSYSTEM_VENDOR_ID);
351 subdevice = read_pci_config_16(num, slot, func, PCI_SUBSYSTEM_ID);
352
353 for (i = 0; i < ARRAY_SIZE(intel_stolen_ids); i++) {
354 if (intel_stolen_ids[i].device == device) {
355 stolen_size_fn stolen_size =
356 (stolen_size_fn)intel_stolen_ids[i].driver_data;
357 size = stolen_size(num, slot, func);
358 start = intel_stolen_base(num, slot, func);
359 if (size && start) {
360 /* Mark this space as reserved */
361 e820_add_region(start, size, E820_RESERVED);
362 sanitize_e820_map(e820.map,
363 ARRAY_SIZE(e820.map),
364 &e820.nr_map);
365 }
366 return;
367 }
368 }
369}
370
219#define QFLAG_APPLY_ONCE 0x1 371#define QFLAG_APPLY_ONCE 0x1
220#define QFLAG_APPLIED 0x2 372#define QFLAG_APPLIED 0x2
221#define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED) 373#define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED)
@@ -251,6 +403,8 @@ static struct chipset early_qrk[] __initdata = {
251 PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, 403 PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check },
252 { PCI_VENDOR_ID_INTEL, 0x3406, PCI_CLASS_BRIDGE_HOST, 404 { PCI_VENDOR_ID_INTEL, 0x3406, PCI_CLASS_BRIDGE_HOST,
253 PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, 405 PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check },
406 { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA, PCI_ANY_ID,
407 QFLAG_APPLY_ONCE, intel_graphics_stolen },
254 {} 408 {}
255}; 409};
256 410
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index b2fa2a4c4454..dcc58ea157fe 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -33,21 +33,6 @@
33#define _MASKED_BIT_ENABLE(a) (((a) << 16) | (a)) 33#define _MASKED_BIT_ENABLE(a) (((a) << 16) | (a))
34#define _MASKED_BIT_DISABLE(a) ((a) << 16) 34#define _MASKED_BIT_DISABLE(a) ((a) << 16)
35 35
36/*
37 * The Bridge device's PCI config space has information about the
38 * fb aperture size and the amount of pre-reserved memory.
39 * This is all handled in the intel-gtt.ko module. i915.ko only
40 * cares about the vga bit for the vga rbiter.
41 */
42#define INTEL_GMCH_CTRL 0x52
43#define INTEL_GMCH_VGA_DISABLE (1 << 1)
44#define SNB_GMCH_CTRL 0x50
45#define SNB_GMCH_GGMS_SHIFT 8 /* GTT Graphics Memory Size */
46#define SNB_GMCH_GGMS_MASK 0x3
47#define SNB_GMCH_GMS_SHIFT 3 /* Graphics Mode Select */
48#define SNB_GMCH_GMS_MASK 0x1f
49
50
51/* PCI config space */ 36/* PCI config space */
52 37
53#define HPLLCC 0xc0 /* 855 only */ 38#define HPLLCC 0xc0 /* 855 only */
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 7276a72710e2..3abfa6ea226e 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -36,4 +36,36 @@ extern bool i915_gpu_lower(void);
36extern bool i915_gpu_busy(void); 36extern bool i915_gpu_busy(void);
37extern bool i915_gpu_turbo_disable(void); 37extern bool i915_gpu_turbo_disable(void);
38 38
39/*
40 * The Bridge device's PCI config space has information about the
41 * fb aperture size and the amount of pre-reserved memory.
42 * This is all handled in the intel-gtt.ko module. i915.ko only
43 * cares about the vga bit for the vga rbiter.
44 */
45#define INTEL_GMCH_CTRL 0x52
46#define INTEL_GMCH_VGA_DISABLE (1 << 1)
47#define SNB_GMCH_CTRL 0x50
48#define SNB_GMCH_GGMS_SHIFT 8 /* GTT Graphics Memory Size */
49#define SNB_GMCH_GGMS_MASK 0x3
50#define SNB_GMCH_GMS_SHIFT 3 /* Graphics Mode Select */
51#define SNB_GMCH_GMS_MASK 0x1f
52
53#define I830_GMCH_CTRL 0x52
54
55#define I855_GMCH_GMS_MASK 0xF0
56#define I855_GMCH_GMS_STOLEN_0M 0x0
57#define I855_GMCH_GMS_STOLEN_1M (0x1 << 4)
58#define I855_GMCH_GMS_STOLEN_4M (0x2 << 4)
59#define I855_GMCH_GMS_STOLEN_8M (0x3 << 4)
60#define I855_GMCH_GMS_STOLEN_16M (0x4 << 4)
61#define I855_GMCH_GMS_STOLEN_32M (0x5 << 4)
62#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4)
63#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4)
64#define G33_GMCH_GMS_STOLEN_128M (0x8 << 4)
65#define G33_GMCH_GMS_STOLEN_256M (0x9 << 4)
66#define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4)
67#define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4)
68#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4)
69#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4)
70
39#endif /* _I915_DRM_H_ */ 71#endif /* _I915_DRM_H_ */