x86: Use PCI method for enabling AMD extended config space before MSR method

While both methods should work equivalently well for the native
case, the Xen Dom0 case can't reliably work with the MSR one,
since there's no guarantee that the virtual CPUs it has
available fully cover all necessary physical ones.

As per the suggestion of Robert Richter the patch only adds the
PCI method, but leaves the MSR one as a fallback to cover new
systems the PCI IDs of which may not have got added to the code
base yet.

The only change in v2 is the breaking out of the new CPI
initialization method into a separate function, as requested by
Ingo.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
Acked-by: Robert Richter <robert.richter@amd.com>
Cc: Andreas Herrmann3 <Andreas.Herrmann3@amd.com>
Cc: Joerg Roedel <joerg.roedel@amd.com>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
LKML-Reference: <4D2B3FD7020000780002B67D@vpn.id2.novell.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

authored by Jan Beulich and committed by Ingo Molnar 24d9b70b 29fe359c

+63 -28
+7
arch/x86/include/asm/amd_nb.h
··· 3 3 4 4 #include <linux/pci.h> 5 5 6 + struct amd_nb_bus_dev_range { 7 + u8 bus; 8 + u8 dev_base; 9 + u8 dev_limit; 10 + }; 11 + 6 12 extern struct pci_device_id amd_nb_misc_ids[]; 13 + extern const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[]; 7 14 struct bootnode; 8 15 9 16 extern int early_is_amd_nb(u32 value);
+7
arch/x86/kernel/amd_nb.c
··· 20 20 }; 21 21 EXPORT_SYMBOL(amd_nb_misc_ids); 22 22 23 + const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[] __initconst = { 24 + { 0x00, 0x18, 0x20 }, 25 + { 0xff, 0x00, 0x20 }, 26 + { 0xfe, 0x00, 0x20 }, 27 + { } 28 + }; 29 + 23 30 struct amd_northbridge_info amd_northbridges; 24 31 EXPORT_SYMBOL(amd_northbridges); 25 32
+16 -28
arch/x86/kernel/aperture_64.c
··· 39 39 40 40 int fix_aperture __initdata = 1; 41 41 42 - struct bus_dev_range { 43 - int bus; 44 - int dev_base; 45 - int dev_limit; 46 - }; 47 - 48 - static struct bus_dev_range bus_dev_ranges[] __initdata = { 49 - { 0x00, 0x18, 0x20}, 50 - { 0xff, 0x00, 0x20}, 51 - { 0xfe, 0x00, 0x20} 52 - }; 53 - 54 42 static struct resource gart_resource = { 55 43 .name = "GART", 56 44 .flags = IORESOURCE_MEM, ··· 282 294 search_agp_bridge(&agp_aper_order, &valid_agp); 283 295 284 296 fix = 0; 285 - for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { 297 + for (i = 0; amd_nb_bus_dev_ranges[i].dev_limit; i++) { 286 298 int bus; 287 299 int dev_base, dev_limit; 288 300 289 - bus = bus_dev_ranges[i].bus; 290 - dev_base = bus_dev_ranges[i].dev_base; 291 - dev_limit = bus_dev_ranges[i].dev_limit; 301 + bus = amd_nb_bus_dev_ranges[i].bus; 302 + dev_base = amd_nb_bus_dev_ranges[i].dev_base; 303 + dev_limit = amd_nb_bus_dev_ranges[i].dev_limit; 292 304 293 305 for (slot = dev_base; slot < dev_limit; slot++) { 294 306 if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) ··· 337 349 return; 338 350 339 351 /* disable them all at first */ 340 - for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { 352 + for (i = 0; i < amd_nb_bus_dev_ranges[i].dev_limit; i++) { 341 353 int bus; 342 354 int dev_base, dev_limit; 343 355 344 - bus = bus_dev_ranges[i].bus; 345 - dev_base = bus_dev_ranges[i].dev_base; 346 - dev_limit = bus_dev_ranges[i].dev_limit; 356 + bus = amd_nb_bus_dev_ranges[i].bus; 357 + dev_base = amd_nb_bus_dev_ranges[i].dev_base; 358 + dev_limit = amd_nb_bus_dev_ranges[i].dev_limit; 347 359 348 360 for (slot = dev_base; slot < dev_limit; slot++) { 349 361 if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) ··· 378 390 379 391 fix = 0; 380 392 node = 0; 381 - for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { 393 + for (i = 0; i < amd_nb_bus_dev_ranges[i].dev_limit; i++) { 382 394 int bus; 383 395 int dev_base, dev_limit; 384 396 u32 ctl; 385 397 386 - bus = bus_dev_ranges[i].bus; 387 - dev_base = bus_dev_ranges[i].dev_base; 388 - dev_limit = bus_dev_ranges[i].dev_limit; 398 + bus = amd_nb_bus_dev_ranges[i].bus; 399 + dev_base = amd_nb_bus_dev_ranges[i].dev_base; 400 + dev_limit = amd_nb_bus_dev_ranges[i].dev_limit; 389 401 390 402 for (slot = dev_base; slot < dev_limit; slot++) { 391 403 if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) ··· 493 505 } 494 506 495 507 /* Fix up the north bridges */ 496 - for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { 508 + for (i = 0; i < amd_nb_bus_dev_ranges[i].dev_limit; i++) { 497 509 int bus, dev_base, dev_limit; 498 510 499 511 /* ··· 502 514 */ 503 515 u32 ctl = DISTLBWALKPRB | aper_order << 1; 504 516 505 - bus = bus_dev_ranges[i].bus; 506 - dev_base = bus_dev_ranges[i].dev_base; 507 - dev_limit = bus_dev_ranges[i].dev_limit; 517 + bus = amd_nb_bus_dev_ranges[i].bus; 518 + dev_base = amd_nb_bus_dev_ranges[i].dev_base; 519 + dev_limit = amd_nb_bus_dev_ranges[i].dev_limit; 508 520 for (slot = dev_base; slot < dev_limit; slot++) { 509 521 if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) 510 522 continue;
+33
arch/x86/pci/amd_bus.c
··· 4 4 #include <linux/cpu.h> 5 5 #include <linux/range.h> 6 6 7 + #include <asm/amd_nb.h> 7 8 #include <asm/pci_x86.h> 8 9 9 10 #include <asm/pci-direct.h> ··· 379 378 .notifier_call = amd_cpu_notify, 380 379 }; 381 380 381 + static void __init pci_enable_pci_io_ecs(void) 382 + { 383 + #ifdef CONFIG_AMD_NB 384 + unsigned int i, n; 385 + 386 + for (n = i = 0; !n && amd_nb_bus_dev_ranges[i].dev_limit; ++i) { 387 + u8 bus = amd_nb_bus_dev_ranges[i].bus; 388 + u8 slot = amd_nb_bus_dev_ranges[i].dev_base; 389 + u8 limit = amd_nb_bus_dev_ranges[i].dev_limit; 390 + 391 + for (; slot < limit; ++slot) { 392 + u32 val = read_pci_config(bus, slot, 3, 0); 393 + 394 + if (!early_is_amd_nb(val)) 395 + continue; 396 + 397 + val = read_pci_config(bus, slot, 3, 0x8c); 398 + if (!(val & (ENABLE_CF8_EXT_CFG >> 32))) { 399 + val |= ENABLE_CF8_EXT_CFG >> 32; 400 + write_pci_config(bus, slot, 3, 0x8c, val); 401 + } 402 + ++n; 403 + } 404 + } 405 + pr_info("Extended Config Space enabled on %u nodes\n", n); 406 + #endif 407 + } 408 + 382 409 static int __init pci_io_ecs_init(void) 383 410 { 384 411 int cpu; ··· 414 385 /* assume all cpus from fam10h have IO ECS */ 415 386 if (boot_cpu_data.x86 < 0x10) 416 387 return 0; 388 + 389 + /* Try the PCI method first. */ 390 + if (early_pci_allowed()) 391 + pci_enable_pci_io_ecs(); 417 392 418 393 register_cpu_notifier(&amd_cpu_notifier); 419 394 for_each_online_cpu(cpu)