aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-11 15:04:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-11 15:04:15 -0400
commit40e9963e622cf28ecef258e3dddb04457b65681c (patch)
treef8df0dec584da3ea243bc3feef5a3e143dff08bd /arch
parent8eab6cd031c11071cf88138b2fed19beaa216435 (diff)
parent0534af01cca338193abbfdb53650af91e65dbf10 (diff)
Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pullx86 core platform updates from Peter Anvin: "This is the x86/platform branch with the objectionable IOSF patches removed. What is left is proper memory handling for Intel GPUs, and a change to the Calgary IOMMU code which will be required to make kexec work sanely on those platforms after some upcoming kexec changes" * 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86, calgary: Use 8M TCE table size by default x86/gpu: Print the Intel graphics stolen memory range x86/gpu: Add Intel graphics stolen memory quirk for gen2 platforms x86/gpu: Add vfunc for Intel graphics stolen memory base address
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/early-quirks.c211
-rw-r--r--arch/x86/kernel/pci-calgary_64.c31
2 files changed, 201 insertions, 41 deletions
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index 6d7d5a1260a6..b0cc3809723d 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -225,7 +225,7 @@ static void __init intel_remapping_check(int num, int slot, int func)
225 * 225 *
226 * And yes, so far on current devices the base addr is always under 4G. 226 * And yes, so far on current devices the base addr is always under 4G.
227 */ 227 */
228static u32 __init intel_stolen_base(int num, int slot, int func) 228static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_size)
229{ 229{
230 u32 base; 230 u32 base;
231 231
@@ -244,6 +244,114 @@ static u32 __init intel_stolen_base(int num, int slot, int func)
244#define MB(x) (KB (KB (x))) 244#define MB(x) (KB (KB (x)))
245#define GB(x) (MB (KB (x))) 245#define GB(x) (MB (KB (x)))
246 246
247static size_t __init i830_tseg_size(void)
248{
249 u8 tmp = read_pci_config_byte(0, 0, 0, I830_ESMRAMC);
250
251 if (!(tmp & TSEG_ENABLE))
252 return 0;
253
254 if (tmp & I830_TSEG_SIZE_1M)
255 return MB(1);
256 else
257 return KB(512);
258}
259
260static size_t __init i845_tseg_size(void)
261{
262 u8 tmp = read_pci_config_byte(0, 0, 0, I845_ESMRAMC);
263
264 if (!(tmp & TSEG_ENABLE))
265 return 0;
266
267 switch (tmp & I845_TSEG_SIZE_MASK) {
268 case I845_TSEG_SIZE_512K:
269 return KB(512);
270 case I845_TSEG_SIZE_1M:
271 return MB(1);
272 default:
273 WARN_ON(1);
274 return 0;
275 }
276}
277
278static size_t __init i85x_tseg_size(void)
279{
280 u8 tmp = read_pci_config_byte(0, 0, 0, I85X_ESMRAMC);
281
282 if (!(tmp & TSEG_ENABLE))
283 return 0;
284
285 return MB(1);
286}
287
288static size_t __init i830_mem_size(void)
289{
290 return read_pci_config_byte(0, 0, 0, I830_DRB3) * MB(32);
291}
292
293static size_t __init i85x_mem_size(void)
294{
295 return read_pci_config_byte(0, 0, 1, I85X_DRB3) * MB(32);
296}
297
298/*
299 * On 830/845/85x the stolen memory base isn't available in any
300 * register. We need to calculate it as TOM-TSEG_SIZE-stolen_size.
301 */
302static u32 __init i830_stolen_base(int num, int slot, int func, size_t stolen_size)
303{
304 return i830_mem_size() - i830_tseg_size() - stolen_size;
305}
306
307static u32 __init i845_stolen_base(int num, int slot, int func, size_t stolen_size)
308{
309 return i830_mem_size() - i845_tseg_size() - stolen_size;
310}
311
312static u32 __init i85x_stolen_base(int num, int slot, int func, size_t stolen_size)
313{
314 return i85x_mem_size() - i85x_tseg_size() - stolen_size;
315}
316
317static u32 __init i865_stolen_base(int num, int slot, int func, size_t stolen_size)
318{
319 /*
320 * FIXME is the graphics stolen memory region
321 * always at TOUD? Ie. is it always the last
322 * one to be allocated by the BIOS?
323 */
324 return read_pci_config_16(0, 0, 0, I865_TOUD) << 16;
325}
326
327static size_t __init i830_stolen_size(int num, int slot, int func)
328{
329 size_t stolen_size;
330 u16 gmch_ctrl;
331
332 gmch_ctrl = read_pci_config_16(0, 0, 0, I830_GMCH_CTRL);
333
334 switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
335 case I830_GMCH_GMS_STOLEN_512:
336 stolen_size = KB(512);
337 break;
338 case I830_GMCH_GMS_STOLEN_1024:
339 stolen_size = MB(1);
340 break;
341 case I830_GMCH_GMS_STOLEN_8192:
342 stolen_size = MB(8);
343 break;
344 case I830_GMCH_GMS_LOCAL:
345 /* local memory isn't part of the normal address space */
346 stolen_size = 0;
347 break;
348 default:
349 return 0;
350 }
351
352 return stolen_size;
353}
354
247static size_t __init gen3_stolen_size(int num, int slot, int func) 355static size_t __init gen3_stolen_size(int num, int slot, int func)
248{ 356{
249 size_t stolen_size; 357 size_t stolen_size;
@@ -310,7 +418,7 @@ static size_t __init gen6_stolen_size(int num, int slot, int func)
310 return gmch_ctrl << 25; /* 32 MB units */ 418 return gmch_ctrl << 25; /* 32 MB units */
311} 419}
312 420
313static inline size_t gen8_stolen_size(int num, int slot, int func) 421static size_t gen8_stolen_size(int num, int slot, int func)
314{ 422{
315 u16 gmch_ctrl; 423 u16 gmch_ctrl;
316 424
@@ -320,31 +428,74 @@ static inline size_t gen8_stolen_size(int num, int slot, int func)
320 return gmch_ctrl << 25; /* 32 MB units */ 428 return gmch_ctrl << 25; /* 32 MB units */
321} 429}
322 430
323typedef size_t (*stolen_size_fn)(int num, int slot, int func); 431
432struct intel_stolen_funcs {
433 size_t (*size)(int num, int slot, int func);
434 u32 (*base)(int num, int slot, int func, size_t size);
435};
436
437static const struct intel_stolen_funcs i830_stolen_funcs = {
438 .base = i830_stolen_base,
439 .size = i830_stolen_size,
440};
441
442static const struct intel_stolen_funcs i845_stolen_funcs = {
443 .base = i845_stolen_base,
444 .size = i830_stolen_size,
445};
446
447static const struct intel_stolen_funcs i85x_stolen_funcs = {
448 .base = i85x_stolen_base,
449 .size = gen3_stolen_size,
450};
451
452static const struct intel_stolen_funcs i865_stolen_funcs = {
453 .base = i865_stolen_base,
454 .size = gen3_stolen_size,
455};
456
457static const struct intel_stolen_funcs gen3_stolen_funcs = {
458 .base = intel_stolen_base,
459 .size = gen3_stolen_size,
460};
461
462static const struct intel_stolen_funcs gen6_stolen_funcs = {
463 .base = intel_stolen_base,
464 .size = gen6_stolen_size,
465};
466
467static const struct intel_stolen_funcs gen8_stolen_funcs = {
468 .base = intel_stolen_base,
469 .size = gen8_stolen_size,
470};
324 471
325static struct pci_device_id intel_stolen_ids[] __initdata = { 472static struct pci_device_id intel_stolen_ids[] __initdata = {
326 INTEL_I915G_IDS(gen3_stolen_size), 473 INTEL_I830_IDS(&i830_stolen_funcs),
327 INTEL_I915GM_IDS(gen3_stolen_size), 474 INTEL_I845G_IDS(&i845_stolen_funcs),
328 INTEL_I945G_IDS(gen3_stolen_size), 475 INTEL_I85X_IDS(&i85x_stolen_funcs),
329 INTEL_I945GM_IDS(gen3_stolen_size), 476 INTEL_I865G_IDS(&i865_stolen_funcs),
330 INTEL_VLV_M_IDS(gen6_stolen_size), 477 INTEL_I915G_IDS(&gen3_stolen_funcs),
331 INTEL_VLV_D_IDS(gen6_stolen_size), 478 INTEL_I915GM_IDS(&gen3_stolen_funcs),
332 INTEL_PINEVIEW_IDS(gen3_stolen_size), 479 INTEL_I945G_IDS(&gen3_stolen_funcs),
333 INTEL_I965G_IDS(gen3_stolen_size), 480 INTEL_I945GM_IDS(&gen3_stolen_funcs),
334 INTEL_G33_IDS(gen3_stolen_size), 481 INTEL_VLV_M_IDS(&gen6_stolen_funcs),
335 INTEL_I965GM_IDS(gen3_stolen_size), 482 INTEL_VLV_D_IDS(&gen6_stolen_funcs),
336 INTEL_GM45_IDS(gen3_stolen_size), 483 INTEL_PINEVIEW_IDS(&gen3_stolen_funcs),
337 INTEL_G45_IDS(gen3_stolen_size), 484 INTEL_I965G_IDS(&gen3_stolen_funcs),
338 INTEL_IRONLAKE_D_IDS(gen3_stolen_size), 485 INTEL_G33_IDS(&gen3_stolen_funcs),
339 INTEL_IRONLAKE_M_IDS(gen3_stolen_size), 486 INTEL_I965GM_IDS(&gen3_stolen_funcs),
340 INTEL_SNB_D_IDS(gen6_stolen_size), 487 INTEL_GM45_IDS(&gen3_stolen_funcs),
341 INTEL_SNB_M_IDS(gen6_stolen_size), 488 INTEL_G45_IDS(&gen3_stolen_funcs),
342 INTEL_IVB_M_IDS(gen6_stolen_size), 489 INTEL_IRONLAKE_D_IDS(&gen3_stolen_funcs),
343 INTEL_IVB_D_IDS(gen6_stolen_size), 490 INTEL_IRONLAKE_M_IDS(&gen3_stolen_funcs),
344 INTEL_HSW_D_IDS(gen6_stolen_size), 491 INTEL_SNB_D_IDS(&gen6_stolen_funcs),
345 INTEL_HSW_M_IDS(gen6_stolen_size), 492 INTEL_SNB_M_IDS(&gen6_stolen_funcs),
346 INTEL_BDW_M_IDS(gen8_stolen_size), 493 INTEL_IVB_M_IDS(&gen6_stolen_funcs),
347 INTEL_BDW_D_IDS(gen8_stolen_size) 494 INTEL_IVB_D_IDS(&gen6_stolen_funcs),
495 INTEL_HSW_D_IDS(&gen6_stolen_funcs),
496 INTEL_HSW_M_IDS(&gen6_stolen_funcs),
497 INTEL_BDW_M_IDS(&gen8_stolen_funcs),
498 INTEL_BDW_D_IDS(&gen8_stolen_funcs)
348}; 499};
349 500
350static void __init intel_graphics_stolen(int num, int slot, int func) 501static void __init intel_graphics_stolen(int num, int slot, int func)
@@ -361,11 +512,13 @@ static void __init intel_graphics_stolen(int num, int slot, int func)
361 512
362 for (i = 0; i < ARRAY_SIZE(intel_stolen_ids); i++) { 513 for (i = 0; i < ARRAY_SIZE(intel_stolen_ids); i++) {
363 if (intel_stolen_ids[i].device == device) { 514 if (intel_stolen_ids[i].device == device) {
364 stolen_size_fn stolen_size = 515 const struct intel_stolen_funcs *stolen_funcs =
365 (stolen_size_fn)intel_stolen_ids[i].driver_data; 516 (const struct intel_stolen_funcs *)intel_stolen_ids[i].driver_data;
366 size = stolen_size(num, slot, func); 517 size = stolen_funcs->size(num, slot, func);
367 start = intel_stolen_base(num, slot, func); 518 start = stolen_funcs->base(num, slot, func, size);
368 if (size && start) { 519 if (size && start) {
520 printk(KERN_INFO "Reserving Intel graphics stolen memory at 0x%x-0x%x\n",
521 start, start + (u32)size - 1);
369 /* Mark this space as reserved */ 522 /* Mark this space as reserved */
370 e820_add_region(start, size, E820_RESERVED); 523 e820_add_region(start, size, E820_RESERVED);
371 sanitize_e820_map(e820.map, 524 sanitize_e820_map(e820.map,
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 299d49302e7d..0497f719977d 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -1207,23 +1207,31 @@ error:
1207 return ret; 1207 return ret;
1208} 1208}
1209 1209
1210static inline int __init determine_tce_table_size(u64 ram) 1210static inline int __init determine_tce_table_size(void)
1211{ 1211{
1212 int ret; 1212 int ret;
1213 1213
1214 if (specified_table_size != TCE_TABLE_SIZE_UNSPECIFIED) 1214 if (specified_table_size != TCE_TABLE_SIZE_UNSPECIFIED)
1215 return specified_table_size; 1215 return specified_table_size;
1216 1216
1217 /* 1217 if (is_kdump_kernel() && saved_max_pfn) {
1218 * Table sizes are from 0 to 7 (TCE_TABLE_SIZE_64K to 1218 /*
1219 * TCE_TABLE_SIZE_8M). Table size 0 has 8K entries and each 1219 * Table sizes are from 0 to 7 (TCE_TABLE_SIZE_64K to
1220 * larger table size has twice as many entries, so shift the 1220 * TCE_TABLE_SIZE_8M). Table size 0 has 8K entries and each
1221 * max ram address by 13 to divide by 8K and then look at the 1221 * larger table size has twice as many entries, so shift the
1222 * order of the result to choose between 0-7. 1222 * max ram address by 13 to divide by 8K and then look at the
1223 */ 1223 * order of the result to choose between 0-7.
1224 ret = get_order(ram >> 13); 1224 */
1225 if (ret > TCE_TABLE_SIZE_8M) 1225 ret = get_order((saved_max_pfn * PAGE_SIZE) >> 13);
1226 if (ret > TCE_TABLE_SIZE_8M)
1227 ret = TCE_TABLE_SIZE_8M;
1228 } else {
1229 /*
1230 * Use 8M by default (suggested by Muli) if it's not
1231 * kdump kernel and saved_max_pfn isn't set.
1232 */
1226 ret = TCE_TABLE_SIZE_8M; 1233 ret = TCE_TABLE_SIZE_8M;
1234 }
1227 1235
1228 return ret; 1236 return ret;
1229} 1237}
@@ -1418,8 +1426,7 @@ int __init detect_calgary(void)
1418 return -ENOMEM; 1426 return -ENOMEM;
1419 } 1427 }
1420 1428
1421 specified_table_size = determine_tce_table_size((is_kdump_kernel() ? 1429 specified_table_size = determine_tce_table_size();
1422 saved_max_pfn : max_pfn) * PAGE_SIZE);
1423 1430
1424 for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) { 1431 for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
1425 struct calgary_bus_info *info = &bus_info[bus]; 1432 struct calgary_bus_info *info = &bus_info[bus];