diff options
author | Jeff Garzik <jeff@garzik.org> | 2007-10-11 16:58:30 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-10-12 18:03:19 -0400 |
commit | a79e4198d1effbba040e9bf407a95fc9b3418789 (patch) | |
tree | bbfeed15db3a03c3e7f50ae36f18c017fb940b9e | |
parent | 32a2eea795643929a43cbbba00d8c4a176b309bf (diff) |
PCI: X86: Introduce and enable PCI domain support
* fix bug in pci_read() and pci_write() which prevented PCI domain
support from working (hardcoded domain 0).
* unconditionally enable CONFIG_PCI_DOMAINS
* implement pci_domain_nr() and pci_proc_domain(), as required of
all arches when CONFIG_PCI_DOMAINS is enabled.
* store domain in struct pci_sysdata, as assigned by ACPI
* support "pci=nodomains"
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | arch/i386/Kconfig | 5 | ||||
-rw-r--r-- | arch/x86/pci/acpi.c | 13 | ||||
-rw-r--r-- | arch/x86/pci/common.c | 6 | ||||
-rw-r--r-- | arch/x86_64/Kconfig | 5 | ||||
-rw-r--r-- | include/asm-x86/pci_32.h | 12 | ||||
-rw-r--r-- | include/asm-x86/pci_64.h | 12 |
6 files changed, 45 insertions, 8 deletions
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 2d85e4b87307..515abb98d41d 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig | |||
@@ -1137,6 +1137,11 @@ config PCI_MMCONFIG | |||
1137 | depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY) | 1137 | depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY) |
1138 | default y | 1138 | default y |
1139 | 1139 | ||
1140 | config PCI_DOMAINS | ||
1141 | bool | ||
1142 | depends on PCI | ||
1143 | default y | ||
1144 | |||
1140 | source "drivers/pci/pcie/Kconfig" | 1145 | source "drivers/pci/pcie/Kconfig" |
1141 | 1146 | ||
1142 | source "drivers/pci/Kconfig" | 1147 | source "drivers/pci/Kconfig" |
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index c6fd3a6afa42..27a391da9a98 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c | |||
@@ -189,6 +189,12 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do | |||
189 | 189 | ||
190 | dmi_check_system(acpi_pciprobe_dmi_table); | 190 | dmi_check_system(acpi_pciprobe_dmi_table); |
191 | 191 | ||
192 | if (domain && !pci_domains_supported) { | ||
193 | printk(KERN_WARNING "PCI: Multiple domains not supported " | ||
194 | "(dom %d, bus %d)\n", domain, busnum); | ||
195 | return NULL; | ||
196 | } | ||
197 | |||
192 | /* Allocate per-root-bus (not per bus) arch-specific data. | 198 | /* Allocate per-root-bus (not per bus) arch-specific data. |
193 | * TODO: leak; this memory is never freed. | 199 | * TODO: leak; this memory is never freed. |
194 | * It's arguable whether it's worth the trouble to care. | 200 | * It's arguable whether it's worth the trouble to care. |
@@ -199,12 +205,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do | |||
199 | return NULL; | 205 | return NULL; |
200 | } | 206 | } |
201 | 207 | ||
202 | if (domain != 0) { | 208 | sd->domain = domain; |
203 | printk(KERN_WARNING "PCI: Multiple domains not supported\n"); | ||
204 | kfree(sd); | ||
205 | return NULL; | ||
206 | } | ||
207 | |||
208 | sd->node = -1; | 209 | sd->node = -1; |
209 | 210 | ||
210 | pxm = acpi_get_pxm(device->handle); | 211 | pxm = acpi_get_pxm(device->handle); |
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 7d6a9a5aa7cd..2d71bbc411d2 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c | |||
@@ -29,12 +29,14 @@ struct pci_raw_ops *raw_pci_ops; | |||
29 | 29 | ||
30 | static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) | 30 | static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) |
31 | { | 31 | { |
32 | return raw_pci_ops->read(0, bus->number, devfn, where, size, value); | 32 | return raw_pci_ops->read(pci_domain_nr(bus), bus->number, |
33 | devfn, where, size, value); | ||
33 | } | 34 | } |
34 | 35 | ||
35 | static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) | 36 | static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) |
36 | { | 37 | { |
37 | return raw_pci_ops->write(0, bus->number, devfn, where, size, value); | 38 | return raw_pci_ops->write(pci_domain_nr(bus), bus->number, |
39 | devfn, where, size, value); | ||
38 | } | 40 | } |
39 | 41 | ||
40 | struct pci_ops pci_root_ops = { | 42 | struct pci_ops pci_root_ops = { |
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index b1b98e614f7c..04d324cc72d8 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig | |||
@@ -724,6 +724,11 @@ config PCI_MMCONFIG | |||
724 | bool "Support mmconfig PCI config space access" | 724 | bool "Support mmconfig PCI config space access" |
725 | depends on PCI && ACPI | 725 | depends on PCI && ACPI |
726 | 726 | ||
727 | config PCI_DOMAINS | ||
728 | bool | ||
729 | depends on PCI | ||
730 | default y | ||
731 | |||
727 | source "drivers/pci/pcie/Kconfig" | 732 | source "drivers/pci/pcie/Kconfig" |
728 | 733 | ||
729 | source "drivers/pci/Kconfig" | 734 | source "drivers/pci/Kconfig" |
diff --git a/include/asm-x86/pci_32.h b/include/asm-x86/pci_32.h index 4fcacc711385..0d91605cd1e2 100644 --- a/include/asm-x86/pci_32.h +++ b/include/asm-x86/pci_32.h | |||
@@ -5,12 +5,24 @@ | |||
5 | #ifdef __KERNEL__ | 5 | #ifdef __KERNEL__ |
6 | 6 | ||
7 | struct pci_sysdata { | 7 | struct pci_sysdata { |
8 | int domain; /* PCI domain */ | ||
8 | int node; /* NUMA node */ | 9 | int node; /* NUMA node */ |
9 | }; | 10 | }; |
10 | 11 | ||
11 | /* scan a bus after allocating a pci_sysdata for it */ | 12 | /* scan a bus after allocating a pci_sysdata for it */ |
12 | extern struct pci_bus *pci_scan_bus_with_sysdata(int busno); | 13 | extern struct pci_bus *pci_scan_bus_with_sysdata(int busno); |
13 | 14 | ||
15 | static inline int pci_domain_nr(struct pci_bus *bus) | ||
16 | { | ||
17 | struct pci_sysdata *sd = bus->sysdata; | ||
18 | return sd->domain; | ||
19 | } | ||
20 | |||
21 | static inline int pci_proc_domain(struct pci_bus *bus) | ||
22 | { | ||
23 | return pci_domain_nr(bus); | ||
24 | } | ||
25 | |||
14 | #include <linux/mm.h> /* for struct page */ | 26 | #include <linux/mm.h> /* for struct page */ |
15 | 27 | ||
16 | /* Can be used to override the logic in pci_scan_bus for skipping | 28 | /* Can be used to override the logic in pci_scan_bus for skipping |
diff --git a/include/asm-x86/pci_64.h b/include/asm-x86/pci_64.h index 5da8cb0c0599..0a123d6a820f 100644 --- a/include/asm-x86/pci_64.h +++ b/include/asm-x86/pci_64.h | |||
@@ -6,12 +6,24 @@ | |||
6 | #ifdef __KERNEL__ | 6 | #ifdef __KERNEL__ |
7 | 7 | ||
8 | struct pci_sysdata { | 8 | struct pci_sysdata { |
9 | int domain; /* PCI domain */ | ||
9 | int node; /* NUMA node */ | 10 | int node; /* NUMA node */ |
10 | void* iommu; /* IOMMU private data */ | 11 | void* iommu; /* IOMMU private data */ |
11 | }; | 12 | }; |
12 | 13 | ||
13 | extern struct pci_bus *pci_scan_bus_with_sysdata(int busno); | 14 | extern struct pci_bus *pci_scan_bus_with_sysdata(int busno); |
14 | 15 | ||
16 | static inline int pci_domain_nr(struct pci_bus *bus) | ||
17 | { | ||
18 | struct pci_sysdata *sd = bus->sysdata; | ||
19 | return sd->domain; | ||
20 | } | ||
21 | |||
22 | static inline int pci_proc_domain(struct pci_bus *bus) | ||
23 | { | ||
24 | return pci_domain_nr(bus); | ||
25 | } | ||
26 | |||
15 | #ifdef CONFIG_CALGARY_IOMMU | 27 | #ifdef CONFIG_CALGARY_IOMMU |
16 | static inline void* pci_iommu(struct pci_bus *bus) | 28 | static inline void* pci_iommu(struct pci_bus *bus) |
17 | { | 29 | { |