diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-11 14:11:46 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-11 14:11:46 -0500 |
| commit | 16ee8db6a93ffbc021132599f33288613f042c3d (patch) | |
| tree | 3f919fb63f24f4b9d9f8b34269ba95ed3e81396e | |
| parent | 5943a268002fce97885f2ca08827ff1b0312068c (diff) | |
| parent | fa36e956c5027d9a985d555d104d293c0a98d2c3 (diff) | |
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
x86: Fix Moorestown VRTC fixmap placement
x86/gpio: Implement x86 gpio_to_irq convert function
x86, UV: Fix APICID shift for Westmere processors
x86: Use PCI method for enabling AMD extended config space before MSR method
x86: tsc: Prevent delayed init if initial tsc calibration failed
x86, lapic-timer: Increase the max_delta to 31 bits
x86: Fix sparse non-ANSI function warnings in smpboot.c
x86, numa: Fix CONFIG_DEBUG_PER_CPU_MAPS without NUMA emulation
x86, AMD, PCI: Add AMD northbridge PCI device id for CPU families 12h and 14h
x86, numa: Fix cpu to node mapping for sparse node ids
x86, numa: Fake node-to-cpumask for NUMA emulation
x86, numa: Fake apicid and pxm mappings for NUMA emulation
x86, numa: Avoid compiling NUMA emulation functions without CONFIG_NUMA_EMU
x86, numa: Reduce minimum fake node size to 32M
Fix up trivial conflict in arch/x86/kernel/apic/x2apic_uv_x.c
| -rw-r--r-- | arch/x86/include/asm/acpi.h | 11 | ||||
| -rw-r--r-- | arch/x86/include/asm/amd_nb.h | 13 | ||||
| -rw-r--r-- | arch/x86/include/asm/fixmap.h | 4 | ||||
| -rw-r--r-- | arch/x86/include/asm/gpio.h | 5 | ||||
| -rw-r--r-- | arch/x86/include/asm/numa_64.h | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/amd_nb.c | 7 | ||||
| -rw-r--r-- | arch/x86/kernel/aperture_64.c | 44 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/apic.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/x2apic_uv_x.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/smpboot.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/tsc.c | 2 | ||||
| -rw-r--r-- | arch/x86/mm/amdtopology_64.c | 86 | ||||
| -rw-r--r-- | arch/x86/mm/numa_64.c | 157 | ||||
| -rw-r--r-- | arch/x86/mm/srat_64.c | 26 | ||||
| -rw-r--r-- | arch/x86/pci/amd_bus.c | 33 | ||||
| -rw-r--r-- | include/linux/pci_ids.h | 1 |
16 files changed, 297 insertions, 102 deletions
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 55d106b5e31b..211ca3f7fd16 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h | |||
| @@ -185,17 +185,16 @@ struct bootnode; | |||
| 185 | 185 | ||
| 186 | #ifdef CONFIG_ACPI_NUMA | 186 | #ifdef CONFIG_ACPI_NUMA |
| 187 | extern int acpi_numa; | 187 | extern int acpi_numa; |
| 188 | extern int acpi_get_nodes(struct bootnode *physnodes); | 188 | extern void acpi_get_nodes(struct bootnode *physnodes, unsigned long start, |
| 189 | unsigned long end); | ||
| 189 | extern int acpi_scan_nodes(unsigned long start, unsigned long end); | 190 | extern int acpi_scan_nodes(unsigned long start, unsigned long end); |
| 190 | #define NR_NODE_MEMBLKS (MAX_NUMNODES*2) | 191 | #define NR_NODE_MEMBLKS (MAX_NUMNODES*2) |
| 192 | |||
| 193 | #ifdef CONFIG_NUMA_EMU | ||
| 191 | extern void acpi_fake_nodes(const struct bootnode *fake_nodes, | 194 | extern void acpi_fake_nodes(const struct bootnode *fake_nodes, |
| 192 | int num_nodes); | 195 | int num_nodes); |
| 193 | #else | ||
| 194 | static inline void acpi_fake_nodes(const struct bootnode *fake_nodes, | ||
| 195 | int num_nodes) | ||
| 196 | { | ||
| 197 | } | ||
| 198 | #endif | 196 | #endif |
| 197 | #endif /* CONFIG_ACPI_NUMA */ | ||
| 199 | 198 | ||
| 200 | #define acpi_unlazy_tlb(x) leave_mm(x) | 199 | #define acpi_unlazy_tlb(x) leave_mm(x) |
| 201 | 200 | ||
diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h index 6aee50d655d1..64dc82ee19f0 100644 --- a/arch/x86/include/asm/amd_nb.h +++ b/arch/x86/include/asm/amd_nb.h | |||
| @@ -3,16 +3,27 @@ | |||
| 3 | 3 | ||
| 4 | #include <linux/pci.h> | 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 | extern struct pci_device_id amd_nb_misc_ids[]; | 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 | struct bootnode; | 14 | struct bootnode; |
| 8 | 15 | ||
| 9 | extern int early_is_amd_nb(u32 value); | 16 | extern int early_is_amd_nb(u32 value); |
| 10 | extern int amd_cache_northbridges(void); | 17 | extern int amd_cache_northbridges(void); |
| 11 | extern void amd_flush_garts(void); | 18 | extern void amd_flush_garts(void); |
| 12 | extern int amd_get_nodes(struct bootnode *nodes); | ||
| 13 | extern int amd_numa_init(unsigned long start_pfn, unsigned long end_pfn); | 19 | extern int amd_numa_init(unsigned long start_pfn, unsigned long end_pfn); |
| 14 | extern int amd_scan_nodes(void); | 20 | extern int amd_scan_nodes(void); |
| 15 | 21 | ||
| 22 | #ifdef CONFIG_NUMA_EMU | ||
| 23 | extern void amd_fake_nodes(const struct bootnode *nodes, int nr_nodes); | ||
| 24 | extern void amd_get_nodes(struct bootnode *nodes); | ||
| 25 | #endif | ||
| 26 | |||
| 16 | struct amd_northbridge { | 27 | struct amd_northbridge { |
| 17 | struct pci_dev *misc; | 28 | struct pci_dev *misc; |
| 18 | }; | 29 | }; |
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index 0141b234406f..4729b2b63117 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h | |||
| @@ -116,11 +116,11 @@ enum fixed_addresses { | |||
| 116 | #endif | 116 | #endif |
| 117 | FIX_TEXT_POKE1, /* reserve 2 pages for text_poke() */ | 117 | FIX_TEXT_POKE1, /* reserve 2 pages for text_poke() */ |
| 118 | FIX_TEXT_POKE0, /* first page is last, because allocation is backward */ | 118 | FIX_TEXT_POKE0, /* first page is last, because allocation is backward */ |
| 119 | __end_of_permanent_fixed_addresses, | ||
| 120 | |||
| 121 | #ifdef CONFIG_X86_MRST | 119 | #ifdef CONFIG_X86_MRST |
| 122 | FIX_LNW_VRTC, | 120 | FIX_LNW_VRTC, |
| 123 | #endif | 121 | #endif |
| 122 | __end_of_permanent_fixed_addresses, | ||
| 123 | |||
| 124 | /* | 124 | /* |
| 125 | * 256 temporary boot-time mappings, used by early_ioremap(), | 125 | * 256 temporary boot-time mappings, used by early_ioremap(), |
| 126 | * before ioremap() is functional. | 126 | * before ioremap() is functional. |
diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h index 49dbfdfa50f9..91d915a65259 100644 --- a/arch/x86/include/asm/gpio.h +++ b/arch/x86/include/asm/gpio.h | |||
| @@ -38,12 +38,9 @@ static inline int gpio_cansleep(unsigned int gpio) | |||
| 38 | return __gpio_cansleep(gpio); | 38 | return __gpio_cansleep(gpio); |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | /* | ||
| 42 | * Not implemented, yet. | ||
| 43 | */ | ||
| 44 | static inline int gpio_to_irq(unsigned int gpio) | 41 | static inline int gpio_to_irq(unsigned int gpio) |
| 45 | { | 42 | { |
| 46 | return -ENOSYS; | 43 | return __gpio_to_irq(gpio); |
| 47 | } | 44 | } |
| 48 | 45 | ||
| 49 | static inline int irq_to_gpio(unsigned int irq) | 46 | static inline int irq_to_gpio(unsigned int irq) |
diff --git a/arch/x86/include/asm/numa_64.h b/arch/x86/include/asm/numa_64.h index 823e070e7c26..5ae87285a502 100644 --- a/arch/x86/include/asm/numa_64.h +++ b/arch/x86/include/asm/numa_64.h | |||
| @@ -38,7 +38,7 @@ extern void __cpuinit numa_add_cpu(int cpu); | |||
| 38 | extern void __cpuinit numa_remove_cpu(int cpu); | 38 | extern void __cpuinit numa_remove_cpu(int cpu); |
| 39 | 39 | ||
| 40 | #ifdef CONFIG_NUMA_EMU | 40 | #ifdef CONFIG_NUMA_EMU |
| 41 | #define FAKE_NODE_MIN_SIZE ((u64)64 << 20) | 41 | #define FAKE_NODE_MIN_SIZE ((u64)32 << 20) |
| 42 | #define FAKE_NODE_MIN_HASH_MASK (~(FAKE_NODE_MIN_SIZE - 1UL)) | 42 | #define FAKE_NODE_MIN_HASH_MASK (~(FAKE_NODE_MIN_SIZE - 1UL)) |
| 43 | #endif /* CONFIG_NUMA_EMU */ | 43 | #endif /* CONFIG_NUMA_EMU */ |
| 44 | #else | 44 | #else |
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index affacb5e0065..0a99f7198bc3 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c | |||
| @@ -20,6 +20,13 @@ struct pci_device_id amd_nb_misc_ids[] = { | |||
| 20 | }; | 20 | }; |
| 21 | EXPORT_SYMBOL(amd_nb_misc_ids); | 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 | struct amd_northbridge_info amd_northbridges; | 30 | struct amd_northbridge_info amd_northbridges; |
| 24 | EXPORT_SYMBOL(amd_northbridges); | 31 | EXPORT_SYMBOL(amd_northbridges); |
| 25 | 32 | ||
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index dcd7c83e1659..5955a7800a96 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c | |||
| @@ -39,18 +39,6 @@ int fallback_aper_force __initdata; | |||
| 39 | 39 | ||
| 40 | int fix_aperture __initdata = 1; | 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 | static struct resource gart_resource = { | 42 | static struct resource gart_resource = { |
| 55 | .name = "GART", | 43 | .name = "GART", |
| 56 | .flags = IORESOURCE_MEM, | 44 | .flags = IORESOURCE_MEM, |
| @@ -294,13 +282,13 @@ void __init early_gart_iommu_check(void) | |||
| 294 | search_agp_bridge(&agp_aper_order, &valid_agp); | 282 | search_agp_bridge(&agp_aper_order, &valid_agp); |
| 295 | 283 | ||
| 296 | fix = 0; | 284 | fix = 0; |
| 297 | for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { | 285 | for (i = 0; amd_nb_bus_dev_ranges[i].dev_limit; i++) { |
| 298 | int bus; | 286 | int bus; |
| 299 | int dev_base, dev_limit; | 287 | int dev_base, dev_limit; |
| 300 | 288 | ||
| 301 | bus = bus_dev_ranges[i].bus; | 289 | bus = amd_nb_bus_dev_ranges[i].bus; |
| 302 | dev_base = bus_dev_ranges[i].dev_base; | 290 | dev_base = amd_nb_bus_dev_ranges[i].dev_base; |
| 303 | dev_limit = bus_dev_ranges[i].dev_limit; | 291 | dev_limit = amd_nb_bus_dev_ranges[i].dev_limit; |
| 304 | 292 | ||
| 305 | for (slot = dev_base; slot < dev_limit; slot++) { | 293 | for (slot = dev_base; slot < dev_limit; slot++) { |
| 306 | if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) | 294 | if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) |
| @@ -349,13 +337,13 @@ void __init early_gart_iommu_check(void) | |||
| 349 | return; | 337 | return; |
| 350 | 338 | ||
| 351 | /* disable them all at first */ | 339 | /* disable them all at first */ |
| 352 | for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { | 340 | for (i = 0; i < amd_nb_bus_dev_ranges[i].dev_limit; i++) { |
| 353 | int bus; | 341 | int bus; |
| 354 | int dev_base, dev_limit; | 342 | int dev_base, dev_limit; |
| 355 | 343 | ||
| 356 | bus = bus_dev_ranges[i].bus; | 344 | bus = amd_nb_bus_dev_ranges[i].bus; |
| 357 | dev_base = bus_dev_ranges[i].dev_base; | 345 | dev_base = amd_nb_bus_dev_ranges[i].dev_base; |
| 358 | dev_limit = bus_dev_ranges[i].dev_limit; | 346 | dev_limit = amd_nb_bus_dev_ranges[i].dev_limit; |
| 359 | 347 | ||
| 360 | for (slot = dev_base; slot < dev_limit; slot++) { | 348 | for (slot = dev_base; slot < dev_limit; slot++) { |
| 361 | if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) | 349 | if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) |
| @@ -390,14 +378,14 @@ int __init gart_iommu_hole_init(void) | |||
| 390 | 378 | ||
| 391 | fix = 0; | 379 | fix = 0; |
| 392 | node = 0; | 380 | node = 0; |
| 393 | for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { | 381 | for (i = 0; i < amd_nb_bus_dev_ranges[i].dev_limit; i++) { |
| 394 | int bus; | 382 | int bus; |
| 395 | int dev_base, dev_limit; | 383 | int dev_base, dev_limit; |
| 396 | u32 ctl; | 384 | u32 ctl; |
| 397 | 385 | ||
| 398 | bus = bus_dev_ranges[i].bus; | 386 | bus = amd_nb_bus_dev_ranges[i].bus; |
| 399 | dev_base = bus_dev_ranges[i].dev_base; | 387 | dev_base = amd_nb_bus_dev_ranges[i].dev_base; |
| 400 | dev_limit = bus_dev_ranges[i].dev_limit; | 388 | dev_limit = amd_nb_bus_dev_ranges[i].dev_limit; |
| 401 | 389 | ||
| 402 | for (slot = dev_base; slot < dev_limit; slot++) { | 390 | for (slot = dev_base; slot < dev_limit; slot++) { |
| 403 | if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) | 391 | if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) |
| @@ -505,7 +493,7 @@ out: | |||
| 505 | } | 493 | } |
| 506 | 494 | ||
| 507 | /* Fix up the north bridges */ | 495 | /* Fix up the north bridges */ |
| 508 | for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { | 496 | for (i = 0; i < amd_nb_bus_dev_ranges[i].dev_limit; i++) { |
| 509 | int bus, dev_base, dev_limit; | 497 | int bus, dev_base, dev_limit; |
| 510 | 498 | ||
| 511 | /* | 499 | /* |
| @@ -514,9 +502,9 @@ out: | |||
| 514 | */ | 502 | */ |
| 515 | u32 ctl = DISTLBWALKPRB | aper_order << 1; | 503 | u32 ctl = DISTLBWALKPRB | aper_order << 1; |
| 516 | 504 | ||
| 517 | bus = bus_dev_ranges[i].bus; | 505 | bus = amd_nb_bus_dev_ranges[i].bus; |
| 518 | dev_base = bus_dev_ranges[i].dev_base; | 506 | dev_base = amd_nb_bus_dev_ranges[i].dev_base; |
| 519 | dev_limit = bus_dev_ranges[i].dev_limit; | 507 | dev_limit = amd_nb_bus_dev_ranges[i].dev_limit; |
| 520 | for (slot = dev_base; slot < dev_limit; slot++) { | 508 | for (slot = dev_base; slot < dev_limit; slot++) { |
| 521 | if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) | 509 | if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) |
| 522 | continue; | 510 | continue; |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index a51345ba449e..06c196d7e59c 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
| @@ -684,7 +684,7 @@ static int __init calibrate_APIC_clock(void) | |||
| 684 | lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, | 684 | lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, |
| 685 | lapic_clockevent.shift); | 685 | lapic_clockevent.shift); |
| 686 | lapic_clockevent.max_delta_ns = | 686 | lapic_clockevent.max_delta_ns = |
| 687 | clockevent_delta2ns(0x7FFFFF, &lapic_clockevent); | 687 | clockevent_delta2ns(0x7FFFFFFF, &lapic_clockevent); |
| 688 | lapic_clockevent.min_delta_ns = | 688 | lapic_clockevent.min_delta_ns = |
| 689 | clockevent_delta2ns(0xF, &lapic_clockevent); | 689 | clockevent_delta2ns(0xF, &lapic_clockevent); |
| 690 | 690 | ||
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 89b9f56aaae3..bd16b58b8850 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c | |||
| @@ -378,7 +378,7 @@ struct apic __refdata apic_x2apic_uv_x = { | |||
| 378 | 378 | ||
| 379 | static __cpuinit void set_x2apic_extra_bits(int pnode) | 379 | static __cpuinit void set_x2apic_extra_bits(int pnode) |
| 380 | { | 380 | { |
| 381 | __this_cpu_write(x2apic_extra_bits, (pnode << 6)); | 381 | __this_cpu_write(x2apic_extra_bits, pnode << uvh_apicid.s.pnode_shift); |
| 382 | } | 382 | } |
| 383 | 383 | ||
| 384 | /* | 384 | /* |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index c7149c96d079..763df77343dd 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
| @@ -97,12 +97,12 @@ static DEFINE_PER_CPU(struct task_struct *, idle_thread_array); | |||
| 97 | */ | 97 | */ |
| 98 | static DEFINE_MUTEX(x86_cpu_hotplug_driver_mutex); | 98 | static DEFINE_MUTEX(x86_cpu_hotplug_driver_mutex); |
| 99 | 99 | ||
| 100 | void cpu_hotplug_driver_lock() | 100 | void cpu_hotplug_driver_lock(void) |
| 101 | { | 101 | { |
| 102 | mutex_lock(&x86_cpu_hotplug_driver_mutex); | 102 | mutex_lock(&x86_cpu_hotplug_driver_mutex); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | void cpu_hotplug_driver_unlock() | 105 | void cpu_hotplug_driver_unlock(void) |
| 106 | { | 106 | { |
| 107 | mutex_unlock(&x86_cpu_hotplug_driver_mutex); | 107 | mutex_unlock(&x86_cpu_hotplug_driver_mutex); |
| 108 | } | 108 | } |
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 03d2ea82f35a..823f79a17ad1 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c | |||
| @@ -965,7 +965,7 @@ out: | |||
| 965 | 965 | ||
| 966 | static int __init init_tsc_clocksource(void) | 966 | static int __init init_tsc_clocksource(void) |
| 967 | { | 967 | { |
| 968 | if (!cpu_has_tsc || tsc_disabled > 0) | 968 | if (!cpu_has_tsc || tsc_disabled > 0 || !tsc_khz) |
| 969 | return 0; | 969 | return 0; |
| 970 | 970 | ||
| 971 | if (tsc_clocksource_reliable) | 971 | if (tsc_clocksource_reliable) |
diff --git a/arch/x86/mm/amdtopology_64.c b/arch/x86/mm/amdtopology_64.c index 08a0069b87a5..f21962c435ed 100644 --- a/arch/x86/mm/amdtopology_64.c +++ b/arch/x86/mm/amdtopology_64.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <asm/amd_nb.h> | 27 | #include <asm/amd_nb.h> |
| 28 | 28 | ||
| 29 | static struct bootnode __initdata nodes[8]; | 29 | static struct bootnode __initdata nodes[8]; |
| 30 | static unsigned char __initdata nodeids[8]; | ||
| 30 | static nodemask_t __initdata nodes_parsed = NODE_MASK_NONE; | 31 | static nodemask_t __initdata nodes_parsed = NODE_MASK_NONE; |
| 31 | 32 | ||
| 32 | static __init int find_northbridge(void) | 33 | static __init int find_northbridge(void) |
| @@ -68,19 +69,6 @@ static __init void early_get_boot_cpu_id(void) | |||
| 68 | #endif | 69 | #endif |
| 69 | } | 70 | } |
| 70 | 71 | ||
| 71 | int __init amd_get_nodes(struct bootnode *physnodes) | ||
| 72 | { | ||
| 73 | int i; | ||
| 74 | int ret = 0; | ||
| 75 | |||
| 76 | for_each_node_mask(i, nodes_parsed) { | ||
| 77 | physnodes[ret].start = nodes[i].start; | ||
| 78 | physnodes[ret].end = nodes[i].end; | ||
| 79 | ret++; | ||
| 80 | } | ||
| 81 | return ret; | ||
| 82 | } | ||
| 83 | |||
| 84 | int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) | 72 | int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) |
| 85 | { | 73 | { |
| 86 | unsigned long start = PFN_PHYS(start_pfn); | 74 | unsigned long start = PFN_PHYS(start_pfn); |
| @@ -113,7 +101,7 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) | |||
| 113 | base = read_pci_config(0, nb, 1, 0x40 + i*8); | 101 | base = read_pci_config(0, nb, 1, 0x40 + i*8); |
| 114 | limit = read_pci_config(0, nb, 1, 0x44 + i*8); | 102 | limit = read_pci_config(0, nb, 1, 0x44 + i*8); |
| 115 | 103 | ||
| 116 | nodeid = limit & 7; | 104 | nodeids[i] = nodeid = limit & 7; |
| 117 | if ((base & 3) == 0) { | 105 | if ((base & 3) == 0) { |
| 118 | if (i < numnodes) | 106 | if (i < numnodes) |
| 119 | pr_info("Skipping disabled node %d\n", i); | 107 | pr_info("Skipping disabled node %d\n", i); |
| @@ -193,6 +181,76 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) | |||
| 193 | return 0; | 181 | return 0; |
| 194 | } | 182 | } |
| 195 | 183 | ||
| 184 | #ifdef CONFIG_NUMA_EMU | ||
| 185 | static s16 fake_apicid_to_node[MAX_LOCAL_APIC] __initdata = { | ||
| 186 | [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE | ||
| 187 | }; | ||
| 188 | |||
| 189 | void __init amd_get_nodes(struct bootnode *physnodes) | ||
| 190 | { | ||
| 191 | int i; | ||
| 192 | |||
| 193 | for_each_node_mask(i, nodes_parsed) { | ||
| 194 | physnodes[i].start = nodes[i].start; | ||
| 195 | physnodes[i].end = nodes[i].end; | ||
| 196 | } | ||
| 197 | } | ||
| 198 | |||
| 199 | static int __init find_node_by_addr(unsigned long addr) | ||
| 200 | { | ||
| 201 | int ret = NUMA_NO_NODE; | ||
| 202 | int i; | ||
| 203 | |||
| 204 | for (i = 0; i < 8; i++) | ||
| 205 | if (addr >= nodes[i].start && addr < nodes[i].end) { | ||
| 206 | ret = i; | ||
| 207 | break; | ||
| 208 | } | ||
| 209 | return ret; | ||
| 210 | } | ||
| 211 | |||
| 212 | /* | ||
| 213 | * For NUMA emulation, fake proximity domain (_PXM) to node id mappings must be | ||
| 214 | * setup to represent the physical topology but reflect the emulated | ||
| 215 | * environment. For each emulated node, the real node which it appears on is | ||
| 216 | * found and a fake pxm to nid mapping is created which mirrors the actual | ||
| 217 | * locality. node_distance() then represents the correct distances between | ||
| 218 | * emulated nodes by using the fake acpi mappings to pxms. | ||
| 219 | */ | ||
| 220 | void __init amd_fake_nodes(const struct bootnode *nodes, int nr_nodes) | ||
| 221 | { | ||
| 222 | unsigned int bits; | ||
| 223 | unsigned int cores; | ||
| 224 | unsigned int apicid_base = 0; | ||
| 225 | int i; | ||
| 226 | |||
| 227 | bits = boot_cpu_data.x86_coreid_bits; | ||
| 228 | cores = 1 << bits; | ||
| 229 | early_get_boot_cpu_id(); | ||
| 230 | if (boot_cpu_physical_apicid > 0) | ||
| 231 | apicid_base = boot_cpu_physical_apicid; | ||
| 232 | |||
| 233 | for (i = 0; i < nr_nodes; i++) { | ||
| 234 | int index; | ||
| 235 | int nid; | ||
| 236 | int j; | ||
| 237 | |||
| 238 | nid = find_node_by_addr(nodes[i].start); | ||
| 239 | if (nid == NUMA_NO_NODE) | ||
| 240 | continue; | ||
| 241 | |||
| 242 | index = nodeids[nid] << bits; | ||
| 243 | if (fake_apicid_to_node[index + apicid_base] == NUMA_NO_NODE) | ||
| 244 | for (j = apicid_base; j < cores + apicid_base; j++) | ||
| 245 | fake_apicid_to_node[index + j] = i; | ||
| 246 | #ifdef CONFIG_ACPI_NUMA | ||
| 247 | __acpi_map_pxm_to_node(nid, i); | ||
| 248 | #endif | ||
| 249 | } | ||
| 250 | memcpy(apicid_to_node, fake_apicid_to_node, sizeof(apicid_to_node)); | ||
| 251 | } | ||
| 252 | #endif /* CONFIG_NUMA_EMU */ | ||
| 253 | |||
| 196 | int __init amd_scan_nodes(void) | 254 | int __init amd_scan_nodes(void) |
| 197 | { | 255 | { |
| 198 | unsigned int bits; | 256 | unsigned int bits; |
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index 7762a517d69d..1e72102e80c9 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c | |||
| @@ -260,30 +260,30 @@ void __init numa_init_array(void) | |||
| 260 | #ifdef CONFIG_NUMA_EMU | 260 | #ifdef CONFIG_NUMA_EMU |
| 261 | /* Numa emulation */ | 261 | /* Numa emulation */ |
| 262 | static struct bootnode nodes[MAX_NUMNODES] __initdata; | 262 | static struct bootnode nodes[MAX_NUMNODES] __initdata; |
| 263 | static struct bootnode physnodes[MAX_NUMNODES] __initdata; | 263 | static struct bootnode physnodes[MAX_NUMNODES] __cpuinitdata; |
| 264 | static char *cmdline __initdata; | 264 | static char *cmdline __initdata; |
| 265 | 265 | ||
| 266 | static int __init setup_physnodes(unsigned long start, unsigned long end, | 266 | static int __init setup_physnodes(unsigned long start, unsigned long end, |
| 267 | int acpi, int amd) | 267 | int acpi, int amd) |
| 268 | { | 268 | { |
| 269 | int nr_nodes = 0; | ||
| 270 | int ret = 0; | 269 | int ret = 0; |
| 271 | int i; | 270 | int i; |
| 272 | 271 | ||
| 272 | memset(physnodes, 0, sizeof(physnodes)); | ||
| 273 | #ifdef CONFIG_ACPI_NUMA | 273 | #ifdef CONFIG_ACPI_NUMA |
| 274 | if (acpi) | 274 | if (acpi) |
| 275 | nr_nodes = acpi_get_nodes(physnodes); | 275 | acpi_get_nodes(physnodes, start, end); |
| 276 | #endif | 276 | #endif |
| 277 | #ifdef CONFIG_AMD_NUMA | 277 | #ifdef CONFIG_AMD_NUMA |
| 278 | if (amd) | 278 | if (amd) |
| 279 | nr_nodes = amd_get_nodes(physnodes); | 279 | amd_get_nodes(physnodes); |
| 280 | #endif | 280 | #endif |
| 281 | /* | 281 | /* |
| 282 | * Basic sanity checking on the physical node map: there may be errors | 282 | * Basic sanity checking on the physical node map: there may be errors |
| 283 | * if the SRAT or AMD code incorrectly reported the topology or the mem= | 283 | * if the SRAT or AMD code incorrectly reported the topology or the mem= |
| 284 | * kernel parameter is used. | 284 | * kernel parameter is used. |
| 285 | */ | 285 | */ |
| 286 | for (i = 0; i < nr_nodes; i++) { | 286 | for (i = 0; i < MAX_NUMNODES; i++) { |
| 287 | if (physnodes[i].start == physnodes[i].end) | 287 | if (physnodes[i].start == physnodes[i].end) |
| 288 | continue; | 288 | continue; |
| 289 | if (physnodes[i].start > end) { | 289 | if (physnodes[i].start > end) { |
| @@ -298,17 +298,6 @@ static int __init setup_physnodes(unsigned long start, unsigned long end, | |||
| 298 | physnodes[i].start = start; | 298 | physnodes[i].start = start; |
| 299 | if (physnodes[i].end > end) | 299 | if (physnodes[i].end > end) |
| 300 | physnodes[i].end = end; | 300 | physnodes[i].end = end; |
| 301 | } | ||
| 302 | |||
| 303 | /* | ||
| 304 | * Remove all nodes that have no memory or were truncated because of the | ||
| 305 | * limited address range. | ||
| 306 | */ | ||
| 307 | for (i = 0; i < nr_nodes; i++) { | ||
| 308 | if (physnodes[i].start == physnodes[i].end) | ||
| 309 | continue; | ||
| 310 | physnodes[ret].start = physnodes[i].start; | ||
| 311 | physnodes[ret].end = physnodes[i].end; | ||
| 312 | ret++; | 301 | ret++; |
| 313 | } | 302 | } |
| 314 | 303 | ||
| @@ -324,6 +313,24 @@ static int __init setup_physnodes(unsigned long start, unsigned long end, | |||
| 324 | return ret; | 313 | return ret; |
| 325 | } | 314 | } |
| 326 | 315 | ||
| 316 | static void __init fake_physnodes(int acpi, int amd, int nr_nodes) | ||
| 317 | { | ||
| 318 | int i; | ||
| 319 | |||
| 320 | BUG_ON(acpi && amd); | ||
| 321 | #ifdef CONFIG_ACPI_NUMA | ||
| 322 | if (acpi) | ||
| 323 | acpi_fake_nodes(nodes, nr_nodes); | ||
| 324 | #endif | ||
| 325 | #ifdef CONFIG_AMD_NUMA | ||
| 326 | if (amd) | ||
| 327 | amd_fake_nodes(nodes, nr_nodes); | ||
| 328 | #endif | ||
| 329 | if (!acpi && !amd) | ||
| 330 | for (i = 0; i < nr_cpu_ids; i++) | ||
| 331 | numa_set_node(i, 0); | ||
| 332 | } | ||
| 333 | |||
| 327 | /* | 334 | /* |
| 328 | * Setups up nid to range from addr to addr + size. If the end | 335 | * Setups up nid to range from addr to addr + size. If the end |
| 329 | * boundary is greater than max_addr, then max_addr is used instead. | 336 | * boundary is greater than max_addr, then max_addr is used instead. |
| @@ -352,8 +359,7 @@ static int __init setup_node_range(int nid, u64 *addr, u64 size, u64 max_addr) | |||
| 352 | * Sets up nr_nodes fake nodes interleaved over physical nodes ranging from addr | 359 | * Sets up nr_nodes fake nodes interleaved over physical nodes ranging from addr |
| 353 | * to max_addr. The return value is the number of nodes allocated. | 360 | * to max_addr. The return value is the number of nodes allocated. |
| 354 | */ | 361 | */ |
| 355 | static int __init split_nodes_interleave(u64 addr, u64 max_addr, | 362 | static int __init split_nodes_interleave(u64 addr, u64 max_addr, int nr_nodes) |
| 356 | int nr_phys_nodes, int nr_nodes) | ||
| 357 | { | 363 | { |
| 358 | nodemask_t physnode_mask = NODE_MASK_NONE; | 364 | nodemask_t physnode_mask = NODE_MASK_NONE; |
| 359 | u64 size; | 365 | u64 size; |
| @@ -384,7 +390,7 @@ static int __init split_nodes_interleave(u64 addr, u64 max_addr, | |||
| 384 | return -1; | 390 | return -1; |
| 385 | } | 391 | } |
| 386 | 392 | ||
| 387 | for (i = 0; i < nr_phys_nodes; i++) | 393 | for (i = 0; i < MAX_NUMNODES; i++) |
| 388 | if (physnodes[i].start != physnodes[i].end) | 394 | if (physnodes[i].start != physnodes[i].end) |
| 389 | node_set(i, physnode_mask); | 395 | node_set(i, physnode_mask); |
| 390 | 396 | ||
| @@ -553,11 +559,9 @@ static int __init numa_emulation(unsigned long start_pfn, | |||
| 553 | { | 559 | { |
| 554 | u64 addr = start_pfn << PAGE_SHIFT; | 560 | u64 addr = start_pfn << PAGE_SHIFT; |
| 555 | u64 max_addr = last_pfn << PAGE_SHIFT; | 561 | u64 max_addr = last_pfn << PAGE_SHIFT; |
| 556 | int num_phys_nodes; | ||
| 557 | int num_nodes; | 562 | int num_nodes; |
| 558 | int i; | 563 | int i; |
| 559 | 564 | ||
| 560 | num_phys_nodes = setup_physnodes(addr, max_addr, acpi, amd); | ||
| 561 | /* | 565 | /* |
| 562 | * If the numa=fake command-line contains a 'M' or 'G', it represents | 566 | * If the numa=fake command-line contains a 'M' or 'G', it represents |
| 563 | * the fixed node size. Otherwise, if it is just a single number N, | 567 | * the fixed node size. Otherwise, if it is just a single number N, |
| @@ -572,7 +576,7 @@ static int __init numa_emulation(unsigned long start_pfn, | |||
| 572 | unsigned long n; | 576 | unsigned long n; |
| 573 | 577 | ||
| 574 | n = simple_strtoul(cmdline, NULL, 0); | 578 | n = simple_strtoul(cmdline, NULL, 0); |
| 575 | num_nodes = split_nodes_interleave(addr, max_addr, num_phys_nodes, n); | 579 | num_nodes = split_nodes_interleave(addr, max_addr, n); |
| 576 | } | 580 | } |
| 577 | 581 | ||
| 578 | if (num_nodes < 0) | 582 | if (num_nodes < 0) |
| @@ -595,7 +599,8 @@ static int __init numa_emulation(unsigned long start_pfn, | |||
| 595 | nodes[i].end >> PAGE_SHIFT); | 599 | nodes[i].end >> PAGE_SHIFT); |
| 596 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); | 600 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); |
| 597 | } | 601 | } |
| 598 | acpi_fake_nodes(nodes, num_nodes); | 602 | setup_physnodes(addr, max_addr, acpi, amd); |
| 603 | fake_physnodes(acpi, amd, num_nodes); | ||
| 599 | numa_init_array(); | 604 | numa_init_array(); |
| 600 | return 0; | 605 | return 0; |
| 601 | } | 606 | } |
| @@ -610,8 +615,12 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn, | |||
| 610 | nodes_clear(node_online_map); | 615 | nodes_clear(node_online_map); |
| 611 | 616 | ||
| 612 | #ifdef CONFIG_NUMA_EMU | 617 | #ifdef CONFIG_NUMA_EMU |
| 618 | setup_physnodes(start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT, | ||
| 619 | acpi, amd); | ||
| 613 | if (cmdline && !numa_emulation(start_pfn, last_pfn, acpi, amd)) | 620 | if (cmdline && !numa_emulation(start_pfn, last_pfn, acpi, amd)) |
| 614 | return; | 621 | return; |
| 622 | setup_physnodes(start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT, | ||
| 623 | acpi, amd); | ||
| 615 | nodes_clear(node_possible_map); | 624 | nodes_clear(node_possible_map); |
| 616 | nodes_clear(node_online_map); | 625 | nodes_clear(node_online_map); |
| 617 | #endif | 626 | #endif |
| @@ -767,6 +776,7 @@ void __cpuinit numa_clear_node(int cpu) | |||
| 767 | 776 | ||
| 768 | #ifndef CONFIG_DEBUG_PER_CPU_MAPS | 777 | #ifndef CONFIG_DEBUG_PER_CPU_MAPS |
| 769 | 778 | ||
| 779 | #ifndef CONFIG_NUMA_EMU | ||
| 770 | void __cpuinit numa_add_cpu(int cpu) | 780 | void __cpuinit numa_add_cpu(int cpu) |
| 771 | { | 781 | { |
| 772 | cpumask_set_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); | 782 | cpumask_set_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); |
| @@ -776,34 +786,115 @@ void __cpuinit numa_remove_cpu(int cpu) | |||
| 776 | { | 786 | { |
| 777 | cpumask_clear_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); | 787 | cpumask_clear_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); |
| 778 | } | 788 | } |
| 789 | #else | ||
| 790 | void __cpuinit numa_add_cpu(int cpu) | ||
| 791 | { | ||
| 792 | unsigned long addr; | ||
| 793 | u16 apicid; | ||
| 794 | int physnid; | ||
| 795 | int nid = NUMA_NO_NODE; | ||
| 796 | |||
| 797 | apicid = early_per_cpu(x86_cpu_to_apicid, cpu); | ||
| 798 | if (apicid != BAD_APICID) | ||
| 799 | nid = apicid_to_node[apicid]; | ||
| 800 | if (nid == NUMA_NO_NODE) | ||
| 801 | nid = early_cpu_to_node(cpu); | ||
| 802 | BUG_ON(nid == NUMA_NO_NODE || !node_online(nid)); | ||
| 803 | |||
| 804 | /* | ||
| 805 | * Use the starting address of the emulated node to find which physical | ||
| 806 | * node it is allocated on. | ||
| 807 | */ | ||
| 808 | addr = node_start_pfn(nid) << PAGE_SHIFT; | ||
| 809 | for (physnid = 0; physnid < MAX_NUMNODES; physnid++) | ||
| 810 | if (addr >= physnodes[physnid].start && | ||
| 811 | addr < physnodes[physnid].end) | ||
| 812 | break; | ||
| 813 | |||
| 814 | /* | ||
| 815 | * Map the cpu to each emulated node that is allocated on the physical | ||
| 816 | * node of the cpu's apic id. | ||
| 817 | */ | ||
| 818 | for_each_online_node(nid) { | ||
| 819 | addr = node_start_pfn(nid) << PAGE_SHIFT; | ||
| 820 | if (addr >= physnodes[physnid].start && | ||
| 821 | addr < physnodes[physnid].end) | ||
| 822 | cpumask_set_cpu(cpu, node_to_cpumask_map[nid]); | ||
| 823 | } | ||
| 824 | } | ||
| 825 | |||
| 826 | void __cpuinit numa_remove_cpu(int cpu) | ||
| 827 | { | ||
| 828 | int i; | ||
| 829 | |||
| 830 | for_each_online_node(i) | ||
| 831 | cpumask_clear_cpu(cpu, node_to_cpumask_map[i]); | ||
| 832 | } | ||
| 833 | #endif /* !CONFIG_NUMA_EMU */ | ||
| 779 | 834 | ||
| 780 | #else /* CONFIG_DEBUG_PER_CPU_MAPS */ | 835 | #else /* CONFIG_DEBUG_PER_CPU_MAPS */ |
| 836 | static struct cpumask __cpuinit *debug_cpumask_set_cpu(int cpu, int enable) | ||
| 837 | { | ||
| 838 | int node = early_cpu_to_node(cpu); | ||
| 839 | struct cpumask *mask; | ||
| 840 | char buf[64]; | ||
| 841 | |||
| 842 | mask = node_to_cpumask_map[node]; | ||
| 843 | if (!mask) { | ||
| 844 | pr_err("node_to_cpumask_map[%i] NULL\n", node); | ||
| 845 | dump_stack(); | ||
| 846 | return NULL; | ||
| 847 | } | ||
| 848 | |||
| 849 | cpulist_scnprintf(buf, sizeof(buf), mask); | ||
| 850 | printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n", | ||
| 851 | enable ? "numa_add_cpu" : "numa_remove_cpu", | ||
| 852 | cpu, node, buf); | ||
| 853 | return mask; | ||
| 854 | } | ||
| 781 | 855 | ||
| 782 | /* | 856 | /* |
| 783 | * --------- debug versions of the numa functions --------- | 857 | * --------- debug versions of the numa functions --------- |
| 784 | */ | 858 | */ |
| 859 | #ifndef CONFIG_NUMA_EMU | ||
| 785 | static void __cpuinit numa_set_cpumask(int cpu, int enable) | 860 | static void __cpuinit numa_set_cpumask(int cpu, int enable) |
| 786 | { | 861 | { |
| 787 | int node = early_cpu_to_node(cpu); | ||
| 788 | struct cpumask *mask; | 862 | struct cpumask *mask; |
| 789 | char buf[64]; | ||
| 790 | 863 | ||
| 791 | mask = node_to_cpumask_map[node]; | 864 | mask = debug_cpumask_set_cpu(cpu, enable); |
| 792 | if (mask == NULL) { | 865 | if (!mask) |
| 793 | printk(KERN_ERR "node_to_cpumask_map[%i] NULL\n", node); | ||
| 794 | dump_stack(); | ||
| 795 | return; | 866 | return; |
| 796 | } | ||
| 797 | 867 | ||
| 798 | if (enable) | 868 | if (enable) |
| 799 | cpumask_set_cpu(cpu, mask); | 869 | cpumask_set_cpu(cpu, mask); |
| 800 | else | 870 | else |
| 801 | cpumask_clear_cpu(cpu, mask); | 871 | cpumask_clear_cpu(cpu, mask); |
| 872 | } | ||
| 873 | #else | ||
| 874 | static void __cpuinit numa_set_cpumask(int cpu, int enable) | ||
| 875 | { | ||
| 876 | int node = early_cpu_to_node(cpu); | ||
| 877 | struct cpumask *mask; | ||
| 878 | int i; | ||
| 802 | 879 | ||
| 803 | cpulist_scnprintf(buf, sizeof(buf), mask); | 880 | for_each_online_node(i) { |
| 804 | printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n", | 881 | unsigned long addr; |
| 805 | enable ? "numa_add_cpu" : "numa_remove_cpu", cpu, node, buf); | 882 | |
| 883 | addr = node_start_pfn(i) << PAGE_SHIFT; | ||
| 884 | if (addr < physnodes[node].start || | ||
| 885 | addr >= physnodes[node].end) | ||
| 886 | continue; | ||
| 887 | mask = debug_cpumask_set_cpu(cpu, enable); | ||
| 888 | if (!mask) | ||
| 889 | return; | ||
| 890 | |||
| 891 | if (enable) | ||
| 892 | cpumask_set_cpu(cpu, mask); | ||
| 893 | else | ||
| 894 | cpumask_clear_cpu(cpu, mask); | ||
| 895 | } | ||
| 806 | } | 896 | } |
| 897 | #endif /* CONFIG_NUMA_EMU */ | ||
| 807 | 898 | ||
| 808 | void __cpuinit numa_add_cpu(int cpu) | 899 | void __cpuinit numa_add_cpu(int cpu) |
| 809 | { | 900 | { |
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index 171a0aacb99a..603d285d1daa 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c | |||
| @@ -349,18 +349,19 @@ static int __init nodes_cover_memory(const struct bootnode *nodes) | |||
| 349 | 349 | ||
| 350 | void __init acpi_numa_arch_fixup(void) {} | 350 | void __init acpi_numa_arch_fixup(void) {} |
| 351 | 351 | ||
| 352 | int __init acpi_get_nodes(struct bootnode *physnodes) | 352 | #ifdef CONFIG_NUMA_EMU |
| 353 | void __init acpi_get_nodes(struct bootnode *physnodes, unsigned long start, | ||
| 354 | unsigned long end) | ||
| 353 | { | 355 | { |
| 354 | int i; | 356 | int i; |
| 355 | int ret = 0; | ||
| 356 | 357 | ||
| 357 | for_each_node_mask(i, nodes_parsed) { | 358 | for_each_node_mask(i, nodes_parsed) { |
| 358 | physnodes[ret].start = nodes[i].start; | 359 | cutoff_node(i, start, end); |
| 359 | physnodes[ret].end = nodes[i].end; | 360 | physnodes[i].start = nodes[i].start; |
| 360 | ret++; | 361 | physnodes[i].end = nodes[i].end; |
| 361 | } | 362 | } |
| 362 | return ret; | ||
| 363 | } | 363 | } |
| 364 | #endif /* CONFIG_NUMA_EMU */ | ||
| 364 | 365 | ||
| 365 | /* Use the information discovered above to actually set up the nodes. */ | 366 | /* Use the information discovered above to actually set up the nodes. */ |
| 366 | int __init acpi_scan_nodes(unsigned long start, unsigned long end) | 367 | int __init acpi_scan_nodes(unsigned long start, unsigned long end) |
| @@ -505,8 +506,6 @@ void __init acpi_fake_nodes(const struct bootnode *fake_nodes, int num_nodes) | |||
| 505 | { | 506 | { |
| 506 | int i, j; | 507 | int i, j; |
| 507 | 508 | ||
| 508 | printk(KERN_INFO "Faking PXM affinity for fake nodes on real " | ||
| 509 | "topology.\n"); | ||
| 510 | for (i = 0; i < num_nodes; i++) { | 509 | for (i = 0; i < num_nodes; i++) { |
| 511 | int nid, pxm; | 510 | int nid, pxm; |
| 512 | 511 | ||
| @@ -526,6 +525,17 @@ void __init acpi_fake_nodes(const struct bootnode *fake_nodes, int num_nodes) | |||
| 526 | fake_apicid_to_node[j] == NUMA_NO_NODE) | 525 | fake_apicid_to_node[j] == NUMA_NO_NODE) |
| 527 | fake_apicid_to_node[j] = i; | 526 | fake_apicid_to_node[j] = i; |
| 528 | } | 527 | } |
| 528 | |||
| 529 | /* | ||
| 530 | * If there are apicid-to-node mappings for physical nodes that do not | ||
| 531 | * have a corresponding emulated node, it should default to a guaranteed | ||
| 532 | * value. | ||
| 533 | */ | ||
| 534 | for (i = 0; i < MAX_LOCAL_APIC; i++) | ||
| 535 | if (apicid_to_node[i] != NUMA_NO_NODE && | ||
| 536 | fake_apicid_to_node[i] == NUMA_NO_NODE) | ||
| 537 | fake_apicid_to_node[i] = 0; | ||
| 538 | |||
| 529 | for (i = 0; i < num_nodes; i++) | 539 | for (i = 0; i < num_nodes; i++) |
| 530 | __acpi_map_pxm_to_node(fake_node_to_pxm_map[i], i); | 540 | __acpi_map_pxm_to_node(fake_node_to_pxm_map[i], i); |
| 531 | memcpy(apicid_to_node, fake_apicid_to_node, sizeof(apicid_to_node)); | 541 | memcpy(apicid_to_node, fake_apicid_to_node, sizeof(apicid_to_node)); |
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index fc1e8fe07e5c..e27dffbbb1a7 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #include <linux/cpu.h> | 4 | #include <linux/cpu.h> |
| 5 | #include <linux/range.h> | 5 | #include <linux/range.h> |
| 6 | 6 | ||
| 7 | #include <asm/amd_nb.h> | ||
| 7 | #include <asm/pci_x86.h> | 8 | #include <asm/pci_x86.h> |
| 8 | 9 | ||
| 9 | #include <asm/pci-direct.h> | 10 | #include <asm/pci-direct.h> |
| @@ -378,6 +379,34 @@ static struct notifier_block __cpuinitdata amd_cpu_notifier = { | |||
| 378 | .notifier_call = amd_cpu_notify, | 379 | .notifier_call = amd_cpu_notify, |
| 379 | }; | 380 | }; |
| 380 | 381 | ||
| 382 | static void __init pci_enable_pci_io_ecs(void) | ||
| 383 | { | ||
| 384 | #ifdef CONFIG_AMD_NB | ||
| 385 | unsigned int i, n; | ||
| 386 | |||
| 387 | for (n = i = 0; !n && amd_nb_bus_dev_ranges[i].dev_limit; ++i) { | ||
| 388 | u8 bus = amd_nb_bus_dev_ranges[i].bus; | ||
| 389 | u8 slot = amd_nb_bus_dev_ranges[i].dev_base; | ||
| 390 | u8 limit = amd_nb_bus_dev_ranges[i].dev_limit; | ||
| 391 | |||
| 392 | for (; slot < limit; ++slot) { | ||
| 393 | u32 val = read_pci_config(bus, slot, 3, 0); | ||
| 394 | |||
| 395 | if (!early_is_amd_nb(val)) | ||
| 396 | continue; | ||
| 397 | |||
| 398 | val = read_pci_config(bus, slot, 3, 0x8c); | ||
| 399 | if (!(val & (ENABLE_CF8_EXT_CFG >> 32))) { | ||
| 400 | val |= ENABLE_CF8_EXT_CFG >> 32; | ||
| 401 | write_pci_config(bus, slot, 3, 0x8c, val); | ||
| 402 | } | ||
| 403 | ++n; | ||
| 404 | } | ||
| 405 | } | ||
| 406 | pr_info("Extended Config Space enabled on %u nodes\n", n); | ||
| 407 | #endif | ||
| 408 | } | ||
| 409 | |||
| 381 | static int __init pci_io_ecs_init(void) | 410 | static int __init pci_io_ecs_init(void) |
| 382 | { | 411 | { |
| 383 | int cpu; | 412 | int cpu; |
| @@ -386,6 +415,10 @@ static int __init pci_io_ecs_init(void) | |||
| 386 | if (boot_cpu_data.x86 < 0x10) | 415 | if (boot_cpu_data.x86 < 0x10) |
| 387 | return 0; | 416 | return 0; |
| 388 | 417 | ||
| 418 | /* Try the PCI method first. */ | ||
| 419 | if (early_pci_allowed()) | ||
| 420 | pci_enable_pci_io_ecs(); | ||
| 421 | |||
| 389 | register_cpu_notifier(&amd_cpu_notifier); | 422 | register_cpu_notifier(&amd_cpu_notifier); |
| 390 | for_each_online_cpu(cpu) | 423 | for_each_online_cpu(cpu) |
| 391 | amd_cpu_notify(&amd_cpu_notifier, (unsigned long)CPU_ONLINE, | 424 | amd_cpu_notify(&amd_cpu_notifier, (unsigned long)CPU_ONLINE, |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 2f17b4ccbb58..ab47732d81e0 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
| @@ -518,6 +518,7 @@ | |||
| 518 | #define PCI_DEVICE_ID_AMD_11H_NB_MISC 0x1303 | 518 | #define PCI_DEVICE_ID_AMD_11H_NB_MISC 0x1303 |
| 519 | #define PCI_DEVICE_ID_AMD_11H_NB_LINK 0x1304 | 519 | #define PCI_DEVICE_ID_AMD_11H_NB_LINK 0x1304 |
| 520 | #define PCI_DEVICE_ID_AMD_15H_NB_MISC 0x1603 | 520 | #define PCI_DEVICE_ID_AMD_15H_NB_MISC 0x1603 |
| 521 | #define PCI_DEVICE_ID_AMD_CNB17H_F3 0x1703 | ||
| 521 | #define PCI_DEVICE_ID_AMD_LANCE 0x2000 | 522 | #define PCI_DEVICE_ID_AMD_LANCE 0x2000 |
| 522 | #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 | 523 | #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 |
| 523 | #define PCI_DEVICE_ID_AMD_SCSI 0x2020 | 524 | #define PCI_DEVICE_ID_AMD_SCSI 0x2020 |
