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 4 #include <linux/pci.h> 5 6 extern struct pci_device_id amd_nb_misc_ids[]; 7 struct bootnode; 8 9 extern int early_is_amd_nb(u32 value);
··· 3 4 #include <linux/pci.h> 5 6 + struct amd_nb_bus_dev_range { 7 + u8 bus; 8 + u8 dev_base; 9 + u8 dev_limit; 10 + }; 11 + 12 extern struct pci_device_id amd_nb_misc_ids[]; 13 + extern const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[]; 14 struct bootnode; 15 16 extern int early_is_amd_nb(u32 value);
+7
arch/x86/kernel/amd_nb.c
··· 20 }; 21 EXPORT_SYMBOL(amd_nb_misc_ids); 22 23 struct amd_northbridge_info amd_northbridges; 24 EXPORT_SYMBOL(amd_northbridges); 25
··· 20 }; 21 EXPORT_SYMBOL(amd_nb_misc_ids); 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 + 30 struct amd_northbridge_info amd_northbridges; 31 EXPORT_SYMBOL(amd_northbridges); 32
+16 -28
arch/x86/kernel/aperture_64.c
··· 39 40 int fix_aperture __initdata = 1; 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 static struct resource gart_resource = { 55 .name = "GART", 56 .flags = IORESOURCE_MEM, ··· 282 search_agp_bridge(&agp_aper_order, &valid_agp); 283 284 fix = 0; 285 - for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { 286 int bus; 287 int dev_base, dev_limit; 288 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; 292 293 for (slot = dev_base; slot < dev_limit; slot++) { 294 if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) ··· 337 return; 338 339 /* disable them all at first */ 340 - for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { 341 int bus; 342 int dev_base, dev_limit; 343 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; 347 348 for (slot = dev_base; slot < dev_limit; slot++) { 349 if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) ··· 378 379 fix = 0; 380 node = 0; 381 - for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { 382 int bus; 383 int dev_base, dev_limit; 384 u32 ctl; 385 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; 389 390 for (slot = dev_base; slot < dev_limit; slot++) { 391 if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) ··· 493 } 494 495 /* Fix up the north bridges */ 496 - for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { 497 int bus, dev_base, dev_limit; 498 499 /* ··· 502 */ 503 u32 ctl = DISTLBWALKPRB | aper_order << 1; 504 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; 508 for (slot = dev_base; slot < dev_limit; slot++) { 509 if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) 510 continue;
··· 39 40 int fix_aperture __initdata = 1; 41 42 static struct resource gart_resource = { 43 .name = "GART", 44 .flags = IORESOURCE_MEM, ··· 294 search_agp_bridge(&agp_aper_order, &valid_agp); 295 296 fix = 0; 297 + for (i = 0; amd_nb_bus_dev_ranges[i].dev_limit; i++) { 298 int bus; 299 int dev_base, dev_limit; 300 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; 304 305 for (slot = dev_base; slot < dev_limit; slot++) { 306 if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) ··· 349 return; 350 351 /* disable them all at first */ 352 + for (i = 0; i < amd_nb_bus_dev_ranges[i].dev_limit; i++) { 353 int bus; 354 int dev_base, dev_limit; 355 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; 359 360 for (slot = dev_base; slot < dev_limit; slot++) { 361 if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) ··· 390 391 fix = 0; 392 node = 0; 393 + for (i = 0; i < amd_nb_bus_dev_ranges[i].dev_limit; i++) { 394 int bus; 395 int dev_base, dev_limit; 396 u32 ctl; 397 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; 401 402 for (slot = dev_base; slot < dev_limit; slot++) { 403 if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) ··· 505 } 506 507 /* Fix up the north bridges */ 508 + for (i = 0; i < amd_nb_bus_dev_ranges[i].dev_limit; i++) { 509 int bus, dev_base, dev_limit; 510 511 /* ··· 514 */ 515 u32 ctl = DISTLBWALKPRB | aper_order << 1; 516 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; 520 for (slot = dev_base; slot < dev_limit; slot++) { 521 if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) 522 continue;
+33
arch/x86/pci/amd_bus.c
··· 4 #include <linux/cpu.h> 5 #include <linux/range.h> 6 7 #include <asm/pci_x86.h> 8 9 #include <asm/pci-direct.h> ··· 379 .notifier_call = amd_cpu_notify, 380 }; 381 382 static int __init pci_io_ecs_init(void) 383 { 384 int cpu; ··· 414 /* assume all cpus from fam10h have IO ECS */ 415 if (boot_cpu_data.x86 < 0x10) 416 return 0; 417 418 register_cpu_notifier(&amd_cpu_notifier); 419 for_each_online_cpu(cpu)
··· 4 #include <linux/cpu.h> 5 #include <linux/range.h> 6 7 + #include <asm/amd_nb.h> 8 #include <asm/pci_x86.h> 9 10 #include <asm/pci-direct.h> ··· 378 .notifier_call = amd_cpu_notify, 379 }; 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 + 409 static int __init pci_io_ecs_init(void) 410 { 411 int cpu; ··· 385 /* assume all cpus from fam10h have IO ECS */ 386 if (boot_cpu_data.x86 < 0x10) 387 return 0; 388 + 389 + /* Try the PCI method first. */ 390 + if (early_pci_allowed()) 391 + pci_enable_pci_io_ecs(); 392 393 register_cpu_notifier(&amd_cpu_notifier); 394 for_each_online_cpu(cpu)