diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2007-10-11 11:16:36 +0200 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2007-10-11 11:16:36 +0200 |
commit | fb9aa6f1d4a1e11e66a680460b2c2b2b10b62f79 (patch) | |
tree | e0ad51f39b48a342244cef62099bd1a8a93927db /arch/x86/pci/acpi.c | |
parent | 4b60eb8380a0b588a03b6052d7ac93e1964c75b8 (diff) | |
download | lwn-fb9aa6f1d4a1e11e66a680460b2c2b2b10b62f79.tar.gz lwn-fb9aa6f1d4a1e11e66a680460b2c2b2b10b62f79.zip |
i386: move pci
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/pci/acpi.c')
-rw-r--r-- | arch/x86/pci/acpi.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c new file mode 100644 index 000000000000..bc8a44bddaa7 --- /dev/null +++ b/arch/x86/pci/acpi.c @@ -0,0 +1,90 @@ +#include <linux/pci.h> +#include <linux/acpi.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <asm/numa.h> +#include "pci.h" + +struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) +{ + struct pci_bus *bus; + struct pci_sysdata *sd; + int pxm; + + /* Allocate per-root-bus (not per bus) arch-specific data. + * TODO: leak; this memory is never freed. + * It's arguable whether it's worth the trouble to care. + */ + sd = kzalloc(sizeof(*sd), GFP_KERNEL); + if (!sd) { + printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum); + return NULL; + } + + if (domain != 0) { + printk(KERN_WARNING "PCI: Multiple domains not supported\n"); + kfree(sd); + return NULL; + } + + sd->node = -1; + + pxm = acpi_get_pxm(device->handle); +#ifdef CONFIG_ACPI_NUMA + if (pxm >= 0) + sd->node = pxm_to_node(pxm); +#endif + + bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd); + if (!bus) + kfree(sd); + +#ifdef CONFIG_ACPI_NUMA + if (bus != NULL) { + if (pxm >= 0) { + printk("bus %d -> pxm %d -> node %d\n", + busnum, pxm, sd->node); + } + } +#endif + + return bus; +} + +extern int pci_routeirq; +static int __init pci_acpi_init(void) +{ + struct pci_dev *dev = NULL; + + if (pcibios_scanned) + return 0; + + if (acpi_noirq) + return 0; + + printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); + acpi_irq_penalty_init(); + pcibios_scanned++; + pcibios_enable_irq = acpi_pci_irq_enable; + pcibios_disable_irq = acpi_pci_irq_disable; + + if (pci_routeirq) { + /* + * PCI IRQ routing is set up by pci_enable_device(), but we + * also do it here in case there are still broken drivers that + * don't use pci_enable_device(). + */ + printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n"); + for_each_pci_dev(dev) + acpi_pci_irq_enable(dev); + } else + printk(KERN_INFO "PCI: If a device doesn't work, try \"pci=routeirq\". If it helps, post a report\n"); + +#ifdef CONFIG_X86_IO_APIC + if (acpi_ioapic) + print_IO_APIC(); +#endif + + return 0; +} +subsys_initcall(pci_acpi_init); |