]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | #include <linux/pci.h> |
2 | #include <linux/acpi.h> | |
3 | #include <linux/init.h> | |
b33fa1f3 | 4 | #include <linux/irq.h> |
69e1a33f | 5 | #include <asm/numa.h> |
1da177e4 LT |
6 | #include "pci.h" |
7 | ||
8 | struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) | |
9 | { | |
69e1a33f | 10 | struct pci_bus *bus; |
08f1c192 MBY |
11 | struct pci_sysdata *sd; |
12 | int pxm; | |
13 | ||
14 | /* Allocate per-root-bus (not per bus) arch-specific data. | |
15 | * TODO: leak; this memory is never freed. | |
16 | * It's arguable whether it's worth the trouble to care. | |
17 | */ | |
18 | sd = kzalloc(sizeof(*sd), GFP_KERNEL); | |
19 | if (!sd) { | |
20 | printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum); | |
21 | return NULL; | |
22 | } | |
69e1a33f | 23 | |
1da177e4 LT |
24 | if (domain != 0) { |
25 | printk(KERN_WARNING "PCI: Multiple domains not supported\n"); | |
08f1c192 | 26 | kfree(sd); |
1da177e4 LT |
27 | return NULL; |
28 | } | |
29 | ||
08f1c192 MBY |
30 | sd->node = -1; |
31 | ||
32 | pxm = acpi_get_pxm(device->handle); | |
33 | #ifdef CONFIG_ACPI_NUMA | |
34 | if (pxm >= 0) | |
35 | sd->node = pxm_to_node(pxm); | |
36 | #endif | |
37 | ||
38 | bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd); | |
39 | if (!bus) | |
40 | kfree(sd); | |
41 | ||
69e1a33f AK |
42 | #ifdef CONFIG_ACPI_NUMA |
43 | if (bus != NULL) { | |
69e1a33f | 44 | if (pxm >= 0) { |
08f1c192 MBY |
45 | printk("bus %d -> pxm %d -> node %d\n", |
46 | busnum, pxm, sd->node); | |
69e1a33f AK |
47 | } |
48 | } | |
49 | #endif | |
50 | ||
51 | return bus; | |
1da177e4 LT |
52 | } |
53 | ||
54 | extern int pci_routeirq; | |
55 | static int __init pci_acpi_init(void) | |
56 | { | |
57 | struct pci_dev *dev = NULL; | |
58 | ||
59 | if (pcibios_scanned) | |
60 | return 0; | |
61 | ||
62 | if (acpi_noirq) | |
63 | return 0; | |
64 | ||
65 | printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); | |
66 | acpi_irq_penalty_init(); | |
67 | pcibios_scanned++; | |
68 | pcibios_enable_irq = acpi_pci_irq_enable; | |
87bec66b | 69 | pcibios_disable_irq = acpi_pci_irq_disable; |
1da177e4 LT |
70 | |
71 | if (pci_routeirq) { | |
72 | /* | |
73 | * PCI IRQ routing is set up by pci_enable_device(), but we | |
74 | * also do it here in case there are still broken drivers that | |
75 | * don't use pci_enable_device(). | |
76 | */ | |
77 | printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n"); | |
fb37fb96 | 78 | for_each_pci_dev(dev) |
1da177e4 LT |
79 | acpi_pci_irq_enable(dev); |
80 | } else | |
81 | printk(KERN_INFO "PCI: If a device doesn't work, try \"pci=routeirq\". If it helps, post a report\n"); | |
82 | ||
83 | #ifdef CONFIG_X86_IO_APIC | |
84 | if (acpi_ioapic) | |
85 | print_IO_APIC(); | |
86 | #endif | |
87 | ||
88 | return 0; | |
89 | } | |
90 | subsys_initcall(pci_acpi_init); |