diff options
Diffstat (limited to 'arch/x86/pci')
-rw-r--r-- | arch/x86/pci/amd_bus.c | 52 | ||||
-rw-r--r-- | arch/x86/pci/i386.c | 9 | ||||
-rw-r--r-- | arch/x86/pci/irq.c | 2 | ||||
-rw-r--r-- | arch/x86/pci/legacy.c | 2 | ||||
-rw-r--r-- | arch/x86/pci/mmconfig-shared.c | 67 |
5 files changed, 101 insertions, 31 deletions
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index dbf532369711..6a0fca78c362 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #include <linux/init.h> | 1 | #include <linux/init.h> |
2 | #include <linux/pci.h> | 2 | #include <linux/pci.h> |
3 | #include <linux/topology.h> | 3 | #include <linux/topology.h> |
4 | #include <linux/cpu.h> | ||
4 | #include "pci.h" | 5 | #include "pci.h" |
5 | 6 | ||
6 | #ifdef CONFIG_X86_64 | 7 | #ifdef CONFIG_X86_64 |
@@ -555,15 +556,17 @@ static int __init early_fill_mp_bus_info(void) | |||
555 | return 0; | 556 | return 0; |
556 | } | 557 | } |
557 | 558 | ||
558 | postcore_initcall(early_fill_mp_bus_info); | 559 | #else /* !CONFIG_X86_64 */ |
559 | 560 | ||
560 | #endif | 561 | static int __init early_fill_mp_bus_info(void) { return 0; } |
562 | |||
563 | #endif /* !CONFIG_X86_64 */ | ||
561 | 564 | ||
562 | /* common 32/64 bit code */ | 565 | /* common 32/64 bit code */ |
563 | 566 | ||
564 | #define ENABLE_CF8_EXT_CFG (1ULL << 46) | 567 | #define ENABLE_CF8_EXT_CFG (1ULL << 46) |
565 | 568 | ||
566 | static void enable_pci_io_ecs_per_cpu(void *unused) | 569 | static void enable_pci_io_ecs(void *unused) |
567 | { | 570 | { |
568 | u64 reg; | 571 | u64 reg; |
569 | rdmsrl(MSR_AMD64_NB_CFG, reg); | 572 | rdmsrl(MSR_AMD64_NB_CFG, reg); |
@@ -573,14 +576,51 @@ static void enable_pci_io_ecs_per_cpu(void *unused) | |||
573 | } | 576 | } |
574 | } | 577 | } |
575 | 578 | ||
576 | static int __init enable_pci_io_ecs(void) | 579 | static int __cpuinit amd_cpu_notify(struct notifier_block *self, |
580 | unsigned long action, void *hcpu) | ||
577 | { | 581 | { |
582 | int cpu = (long)hcpu; | ||
583 | switch(action) { | ||
584 | case CPU_ONLINE: | ||
585 | case CPU_ONLINE_FROZEN: | ||
586 | smp_call_function_single(cpu, enable_pci_io_ecs, NULL, 0); | ||
587 | break; | ||
588 | default: | ||
589 | break; | ||
590 | } | ||
591 | return NOTIFY_OK; | ||
592 | } | ||
593 | |||
594 | static struct notifier_block __cpuinitdata amd_cpu_notifier = { | ||
595 | .notifier_call = amd_cpu_notify, | ||
596 | }; | ||
597 | |||
598 | static int __init pci_io_ecs_init(void) | ||
599 | { | ||
600 | int cpu; | ||
601 | |||
578 | /* assume all cpus from fam10h have IO ECS */ | 602 | /* assume all cpus from fam10h have IO ECS */ |
579 | if (boot_cpu_data.x86 < 0x10) | 603 | if (boot_cpu_data.x86 < 0x10) |
580 | return 0; | 604 | return 0; |
581 | on_each_cpu(enable_pci_io_ecs_per_cpu, NULL, 1); | 605 | |
606 | register_cpu_notifier(&amd_cpu_notifier); | ||
607 | for_each_online_cpu(cpu) | ||
608 | amd_cpu_notify(&amd_cpu_notifier, (unsigned long)CPU_ONLINE, | ||
609 | (void *)(long)cpu); | ||
582 | pci_probe |= PCI_HAS_IO_ECS; | 610 | pci_probe |= PCI_HAS_IO_ECS; |
611 | |||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | static int __init amd_postcore_init(void) | ||
616 | { | ||
617 | if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) | ||
618 | return 0; | ||
619 | |||
620 | early_fill_mp_bus_info(); | ||
621 | pci_io_ecs_init(); | ||
622 | |||
583 | return 0; | 623 | return 0; |
584 | } | 624 | } |
585 | 625 | ||
586 | postcore_initcall(enable_pci_io_ecs); | 626 | postcore_initcall(amd_postcore_init); |
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 5807d1bc73f7..8791fc55e715 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c | |||
@@ -128,8 +128,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) | |||
128 | pr = pci_find_parent_resource(dev, r); | 128 | pr = pci_find_parent_resource(dev, r); |
129 | if (!r->start || !pr || | 129 | if (!r->start || !pr || |
130 | request_resource(pr, r) < 0) { | 130 | request_resource(pr, r) < 0) { |
131 | dev_err(&dev->dev, "BAR %d: can't " | 131 | dev_err(&dev->dev, "BAR %d: can't allocate resource\n", idx); |
132 | "allocate resource\n", idx); | ||
133 | /* | 132 | /* |
134 | * Something is wrong with the region. | 133 | * Something is wrong with the region. |
135 | * Invalidate the resource to prevent | 134 | * Invalidate the resource to prevent |
@@ -164,15 +163,13 @@ static void __init pcibios_allocate_resources(int pass) | |||
164 | else | 163 | else |
165 | disabled = !(command & PCI_COMMAND_MEMORY); | 164 | disabled = !(command & PCI_COMMAND_MEMORY); |
166 | if (pass == disabled) { | 165 | if (pass == disabled) { |
167 | dev_dbg(&dev->dev, "resource %#08llx-%#08llx " | 166 | dev_dbg(&dev->dev, "resource %#08llx-%#08llx (f=%lx, d=%d, p=%d)\n", |
168 | "(f=%lx, d=%d, p=%d)\n", | ||
169 | (unsigned long long) r->start, | 167 | (unsigned long long) r->start, |
170 | (unsigned long long) r->end, | 168 | (unsigned long long) r->end, |
171 | r->flags, disabled, pass); | 169 | r->flags, disabled, pass); |
172 | pr = pci_find_parent_resource(dev, r); | 170 | pr = pci_find_parent_resource(dev, r); |
173 | if (!pr || request_resource(pr, r) < 0) { | 171 | if (!pr || request_resource(pr, r) < 0) { |
174 | dev_err(&dev->dev, "BAR %d: can't " | 172 | dev_err(&dev->dev, "BAR %d: can't allocate resource\n", idx); |
175 | "allocate resource\n", idx); | ||
176 | /* We'll assign a new address later */ | 173 | /* We'll assign a new address later */ |
177 | r->end -= r->start; | 174 | r->end -= r->start; |
178 | r->start = 0; | 175 | r->start = 0; |
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index fec0123b33a9..8e077185e185 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c | |||
@@ -590,6 +590,8 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route | |||
590 | case PCI_DEVICE_ID_INTEL_ICH10_1: | 590 | case PCI_DEVICE_ID_INTEL_ICH10_1: |
591 | case PCI_DEVICE_ID_INTEL_ICH10_2: | 591 | case PCI_DEVICE_ID_INTEL_ICH10_2: |
592 | case PCI_DEVICE_ID_INTEL_ICH10_3: | 592 | case PCI_DEVICE_ID_INTEL_ICH10_3: |
593 | case PCI_DEVICE_ID_INTEL_PCH_0: | ||
594 | case PCI_DEVICE_ID_INTEL_PCH_1: | ||
593 | r->name = "PIIX/ICH"; | 595 | r->name = "PIIX/ICH"; |
594 | r->get = pirq_piix_get; | 596 | r->get = pirq_piix_get; |
595 | r->set = pirq_piix_set; | 597 | r->set = pirq_piix_set; |
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c index ec9ce35e44d6..b722dd481b39 100644 --- a/arch/x86/pci/legacy.c +++ b/arch/x86/pci/legacy.c | |||
@@ -14,7 +14,7 @@ static void __devinit pcibios_fixup_peer_bridges(void) | |||
14 | int n, devfn; | 14 | int n, devfn; |
15 | long node; | 15 | long node; |
16 | 16 | ||
17 | if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff) | 17 | if (pcibios_last_bus <= 0 || pcibios_last_bus > 0xff) |
18 | return; | 18 | return; |
19 | DBG("PCI: Peer bridge fixup\n"); | 19 | DBG("PCI: Peer bridge fixup\n"); |
20 | 20 | ||
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 23faaa890ffc..d9635764ce3d 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c | |||
@@ -293,7 +293,7 @@ static acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl, | |||
293 | return AE_OK; | 293 | return AE_OK; |
294 | } | 294 | } |
295 | 295 | ||
296 | static int __init is_acpi_reserved(unsigned long start, unsigned long end) | 296 | static int __init is_acpi_reserved(u64 start, u64 end, unsigned not_used) |
297 | { | 297 | { |
298 | struct resource mcfg_res; | 298 | struct resource mcfg_res; |
299 | 299 | ||
@@ -310,6 +310,41 @@ static int __init is_acpi_reserved(unsigned long start, unsigned long end) | |||
310 | return mcfg_res.flags; | 310 | return mcfg_res.flags; |
311 | } | 311 | } |
312 | 312 | ||
313 | typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type); | ||
314 | |||
315 | static int __init is_mmconf_reserved(check_reserved_t is_reserved, | ||
316 | u64 addr, u64 size, int i, | ||
317 | typeof(pci_mmcfg_config[0]) *cfg, int with_e820) | ||
318 | { | ||
319 | u64 old_size = size; | ||
320 | int valid = 0; | ||
321 | |||
322 | while (!is_reserved(addr, addr + size - 1, E820_RESERVED)) { | ||
323 | size >>= 1; | ||
324 | if (size < (16UL<<20)) | ||
325 | break; | ||
326 | } | ||
327 | |||
328 | if (size >= (16UL<<20) || size == old_size) { | ||
329 | printk(KERN_NOTICE | ||
330 | "PCI: MCFG area at %Lx reserved in %s\n", | ||
331 | addr, with_e820?"E820":"ACPI motherboard resources"); | ||
332 | valid = 1; | ||
333 | |||
334 | if (old_size != size) { | ||
335 | /* update end_bus_number */ | ||
336 | cfg->end_bus_number = cfg->start_bus_number + ((size>>20) - 1); | ||
337 | printk(KERN_NOTICE "PCI: updated MCFG configuration %d: base %lx " | ||
338 | "segment %hu buses %u - %u\n", | ||
339 | i, (unsigned long)cfg->address, cfg->pci_segment, | ||
340 | (unsigned int)cfg->start_bus_number, | ||
341 | (unsigned int)cfg->end_bus_number); | ||
342 | } | ||
343 | } | ||
344 | |||
345 | return valid; | ||
346 | } | ||
347 | |||
313 | static void __init pci_mmcfg_reject_broken(int early) | 348 | static void __init pci_mmcfg_reject_broken(int early) |
314 | { | 349 | { |
315 | typeof(pci_mmcfg_config[0]) *cfg; | 350 | typeof(pci_mmcfg_config[0]) *cfg; |
@@ -324,21 +359,22 @@ static void __init pci_mmcfg_reject_broken(int early) | |||
324 | 359 | ||
325 | for (i = 0; i < pci_mmcfg_config_num; i++) { | 360 | for (i = 0; i < pci_mmcfg_config_num; i++) { |
326 | int valid = 0; | 361 | int valid = 0; |
327 | u32 size = (cfg->end_bus_number + 1) << 20; | 362 | u64 addr, size; |
363 | |||
328 | cfg = &pci_mmcfg_config[i]; | 364 | cfg = &pci_mmcfg_config[i]; |
365 | addr = cfg->start_bus_number; | ||
366 | addr <<= 20; | ||
367 | addr += cfg->address; | ||
368 | size = cfg->end_bus_number + 1 - cfg->start_bus_number; | ||
369 | size <<= 20; | ||
329 | printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lx " | 370 | printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lx " |
330 | "segment %hu buses %u - %u\n", | 371 | "segment %hu buses %u - %u\n", |
331 | i, (unsigned long)cfg->address, cfg->pci_segment, | 372 | i, (unsigned long)cfg->address, cfg->pci_segment, |
332 | (unsigned int)cfg->start_bus_number, | 373 | (unsigned int)cfg->start_bus_number, |
333 | (unsigned int)cfg->end_bus_number); | 374 | (unsigned int)cfg->end_bus_number); |
334 | 375 | ||
335 | if (!early && | 376 | if (!early) |
336 | is_acpi_reserved(cfg->address, cfg->address + size - 1)) { | 377 | valid = is_mmconf_reserved(is_acpi_reserved, addr, size, i, cfg, 0); |
337 | printk(KERN_NOTICE "PCI: MCFG area at %Lx reserved " | ||
338 | "in ACPI motherboard resources\n", | ||
339 | cfg->address); | ||
340 | valid = 1; | ||
341 | } | ||
342 | 378 | ||
343 | if (valid) | 379 | if (valid) |
344 | continue; | 380 | continue; |
@@ -347,16 +383,11 @@ static void __init pci_mmcfg_reject_broken(int early) | |||
347 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not" | 383 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not" |
348 | " reserved in ACPI motherboard resources\n", | 384 | " reserved in ACPI motherboard resources\n", |
349 | cfg->address); | 385 | cfg->address); |
386 | |||
350 | /* Don't try to do this check unless configuration | 387 | /* Don't try to do this check unless configuration |
351 | type 1 is available. how about type 2 ?*/ | 388 | type 1 is available. how about type 2 ?*/ |
352 | if (raw_pci_ops && e820_all_mapped(cfg->address, | 389 | if (raw_pci_ops) |
353 | cfg->address + size - 1, | 390 | valid = is_mmconf_reserved(e820_all_mapped, addr, size, i, cfg, 1); |
354 | E820_RESERVED)) { | ||
355 | printk(KERN_NOTICE | ||
356 | "PCI: MCFG area at %Lx reserved in E820\n", | ||
357 | cfg->address); | ||
358 | valid = 1; | ||
359 | } | ||
360 | 391 | ||
361 | if (!valid) | 392 | if (!valid) |
362 | goto reject; | 393 | goto reject; |
@@ -365,7 +396,7 @@ static void __init pci_mmcfg_reject_broken(int early) | |||
365 | return; | 396 | return; |
366 | 397 | ||
367 | reject: | 398 | reject: |
368 | printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); | 399 | printk(KERN_INFO "PCI: Not using MMCONFIG.\n"); |
369 | pci_mmcfg_arch_free(); | 400 | pci_mmcfg_arch_free(); |
370 | kfree(pci_mmcfg_config); | 401 | kfree(pci_mmcfg_config); |
371 | pci_mmcfg_config = NULL; | 402 | pci_mmcfg_config = NULL; |