diff options
-rw-r--r-- | arch/i386/pci/acpi.c | 32 | ||||
-rw-r--r-- | arch/i386/pci/common.c | 13 | ||||
-rw-r--r-- | arch/x86_64/kernel/pci-calgary.c | 29 | ||||
-rw-r--r-- | arch/x86_64/kernel/tce.c | 12 | ||||
-rw-r--r-- | arch/x86_64/pci/k8-bus.c | 6 | ||||
-rw-r--r-- | include/asm-i386/pci.h | 5 | ||||
-rw-r--r-- | include/asm-i386/topology.h | 2 | ||||
-rw-r--r-- | include/asm-x86_64/pci.h | 19 | ||||
-rw-r--r-- | include/asm-x86_64/topology.h | 2 |
9 files changed, 89 insertions, 31 deletions
diff --git a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c index b33aea845f58..bc8a44bddaa7 100644 --- a/arch/i386/pci/acpi.c +++ b/arch/i386/pci/acpi.c | |||
@@ -8,20 +8,42 @@ | |||
8 | struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) | 8 | struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) |
9 | { | 9 | { |
10 | struct pci_bus *bus; | 10 | struct pci_bus *bus; |
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 | } | ||
11 | 23 | ||
12 | if (domain != 0) { | 24 | if (domain != 0) { |
13 | printk(KERN_WARNING "PCI: Multiple domains not supported\n"); | 25 | printk(KERN_WARNING "PCI: Multiple domains not supported\n"); |
26 | kfree(sd); | ||
14 | return NULL; | 27 | return NULL; |
15 | } | 28 | } |
16 | 29 | ||
17 | bus = pcibios_scan_root(busnum); | 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 | |||
18 | #ifdef CONFIG_ACPI_NUMA | 42 | #ifdef CONFIG_ACPI_NUMA |
19 | if (bus != NULL) { | 43 | if (bus != NULL) { |
20 | int pxm = acpi_get_pxm(device->handle); | ||
21 | if (pxm >= 0) { | 44 | if (pxm >= 0) { |
22 | bus->sysdata = (void *)(unsigned long)pxm_to_node(pxm); | 45 | printk("bus %d -> pxm %d -> node %d\n", |
23 | printk("bus %d -> pxm %d -> node %ld\n", | 46 | busnum, pxm, sd->node); |
24 | busnum, pxm, (long)(bus->sysdata)); | ||
25 | } | 47 | } |
26 | } | 48 | } |
27 | #endif | 49 | #endif |
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index 3f78d4d8ecf3..85503deeda46 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c | |||
@@ -293,6 +293,7 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { | |||
293 | struct pci_bus * __devinit pcibios_scan_root(int busnum) | 293 | struct pci_bus * __devinit pcibios_scan_root(int busnum) |
294 | { | 294 | { |
295 | struct pci_bus *bus = NULL; | 295 | struct pci_bus *bus = NULL; |
296 | struct pci_sysdata *sd; | ||
296 | 297 | ||
297 | dmi_check_system(pciprobe_dmi_table); | 298 | dmi_check_system(pciprobe_dmi_table); |
298 | 299 | ||
@@ -303,9 +304,19 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum) | |||
303 | } | 304 | } |
304 | } | 305 | } |
305 | 306 | ||
307 | /* Allocate per-root-bus (not per bus) arch-specific data. | ||
308 | * TODO: leak; this memory is never freed. | ||
309 | * It's arguable whether it's worth the trouble to care. | ||
310 | */ | ||
311 | sd = kzalloc(sizeof(*sd), GFP_KERNEL); | ||
312 | if (!sd) { | ||
313 | printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum); | ||
314 | return NULL; | ||
315 | } | ||
316 | |||
306 | printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum); | 317 | printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum); |
307 | 318 | ||
308 | return pci_scan_bus_parented(NULL, busnum, &pci_root_ops, NULL); | 319 | return pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd); |
309 | } | 320 | } |
310 | 321 | ||
311 | extern u8 pci_cache_line_size; | 322 | extern u8 pci_cache_line_size; |
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c index 21ded20a3bf4..ba16c968ca3f 100644 --- a/arch/x86_64/kernel/pci-calgary.c +++ b/arch/x86_64/kernel/pci-calgary.c | |||
@@ -373,7 +373,7 @@ static inline struct iommu_table *find_iommu_table(struct device *dev) | |||
373 | else | 373 | else |
374 | pbus = pdev->bus; | 374 | pbus = pdev->bus; |
375 | 375 | ||
376 | tbl = pbus->self->sysdata; | 376 | tbl = pci_iommu(pbus); |
377 | 377 | ||
378 | BUG_ON(pdev->bus->parent && | 378 | BUG_ON(pdev->bus->parent && |
379 | (tbl->it_busno != pdev->bus->parent->number)); | 379 | (tbl->it_busno != pdev->bus->parent->number)); |
@@ -716,7 +716,7 @@ static void __init calgary_reserve_mem_region(struct pci_dev *dev, u64 start, | |||
716 | limit++; | 716 | limit++; |
717 | 717 | ||
718 | numpages = ((limit - start) >> PAGE_SHIFT); | 718 | numpages = ((limit - start) >> PAGE_SHIFT); |
719 | iommu_range_reserve(dev->sysdata, start, numpages); | 719 | iommu_range_reserve(pci_iommu(dev->bus), start, numpages); |
720 | } | 720 | } |
721 | 721 | ||
722 | static void __init calgary_reserve_peripheral_mem_1(struct pci_dev *dev) | 722 | static void __init calgary_reserve_peripheral_mem_1(struct pci_dev *dev) |
@@ -724,7 +724,7 @@ static void __init calgary_reserve_peripheral_mem_1(struct pci_dev *dev) | |||
724 | void __iomem *target; | 724 | void __iomem *target; |
725 | u64 low, high, sizelow; | 725 | u64 low, high, sizelow; |
726 | u64 start, limit; | 726 | u64 start, limit; |
727 | struct iommu_table *tbl = dev->sysdata; | 727 | struct iommu_table *tbl = pci_iommu(dev->bus); |
728 | unsigned char busnum = dev->bus->number; | 728 | unsigned char busnum = dev->bus->number; |
729 | void __iomem *bbar = tbl->bbar; | 729 | void __iomem *bbar = tbl->bbar; |
730 | 730 | ||
@@ -748,7 +748,7 @@ static void __init calgary_reserve_peripheral_mem_2(struct pci_dev *dev) | |||
748 | u32 val32; | 748 | u32 val32; |
749 | u64 low, high, sizelow, sizehigh; | 749 | u64 low, high, sizelow, sizehigh; |
750 | u64 start, limit; | 750 | u64 start, limit; |
751 | struct iommu_table *tbl = dev->sysdata; | 751 | struct iommu_table *tbl = pci_iommu(dev->bus); |
752 | unsigned char busnum = dev->bus->number; | 752 | unsigned char busnum = dev->bus->number; |
753 | void __iomem *bbar = tbl->bbar; | 753 | void __iomem *bbar = tbl->bbar; |
754 | 754 | ||
@@ -784,7 +784,7 @@ static void __init calgary_reserve_regions(struct pci_dev *dev) | |||
784 | { | 784 | { |
785 | unsigned int npages; | 785 | unsigned int npages; |
786 | u64 start; | 786 | u64 start; |
787 | struct iommu_table *tbl = dev->sysdata; | 787 | struct iommu_table *tbl = pci_iommu(dev->bus); |
788 | 788 | ||
789 | /* reserve EMERGENCY_PAGES from bad_dma_address and up */ | 789 | /* reserve EMERGENCY_PAGES from bad_dma_address and up */ |
790 | iommu_range_reserve(tbl, bad_dma_address, EMERGENCY_PAGES); | 790 | iommu_range_reserve(tbl, bad_dma_address, EMERGENCY_PAGES); |
@@ -818,7 +818,7 @@ static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar) | |||
818 | if (ret) | 818 | if (ret) |
819 | return ret; | 819 | return ret; |
820 | 820 | ||
821 | tbl = dev->sysdata; | 821 | tbl = pci_iommu(dev->bus); |
822 | tbl->it_base = (unsigned long)bus_info[dev->bus->number].tce_space; | 822 | tbl->it_base = (unsigned long)bus_info[dev->bus->number].tce_space; |
823 | tce_free(tbl, 0, tbl->it_size); | 823 | tce_free(tbl, 0, tbl->it_size); |
824 | 824 | ||
@@ -855,7 +855,7 @@ static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar) | |||
855 | static void __init calgary_free_bus(struct pci_dev *dev) | 855 | static void __init calgary_free_bus(struct pci_dev *dev) |
856 | { | 856 | { |
857 | u64 val64; | 857 | u64 val64; |
858 | struct iommu_table *tbl = dev->sysdata; | 858 | struct iommu_table *tbl = pci_iommu(dev->bus); |
859 | void __iomem *target; | 859 | void __iomem *target; |
860 | unsigned int bitmapsz; | 860 | unsigned int bitmapsz; |
861 | 861 | ||
@@ -870,7 +870,8 @@ static void __init calgary_free_bus(struct pci_dev *dev) | |||
870 | tbl->it_map = NULL; | 870 | tbl->it_map = NULL; |
871 | 871 | ||
872 | kfree(tbl); | 872 | kfree(tbl); |
873 | dev->sysdata = NULL; | 873 | |
874 | set_pci_iommu(dev->bus, NULL); | ||
874 | 875 | ||
875 | /* Can't free bootmem allocated memory after system is up :-( */ | 876 | /* Can't free bootmem allocated memory after system is up :-( */ |
876 | bus_info[dev->bus->number].tce_space = NULL; | 877 | bus_info[dev->bus->number].tce_space = NULL; |
@@ -943,7 +944,7 @@ static void calioc2_dump_error_regs(struct iommu_table *tbl) | |||
943 | static void calgary_watchdog(unsigned long data) | 944 | static void calgary_watchdog(unsigned long data) |
944 | { | 945 | { |
945 | struct pci_dev *dev = (struct pci_dev *)data; | 946 | struct pci_dev *dev = (struct pci_dev *)data; |
946 | struct iommu_table *tbl = dev->sysdata; | 947 | struct iommu_table *tbl = pci_iommu(dev->bus); |
947 | void __iomem *bbar = tbl->bbar; | 948 | void __iomem *bbar = tbl->bbar; |
948 | u32 val32; | 949 | u32 val32; |
949 | void __iomem *target; | 950 | void __iomem *target; |
@@ -1041,7 +1042,7 @@ static void __init calgary_enable_translation(struct pci_dev *dev) | |||
1041 | struct iommu_table *tbl; | 1042 | struct iommu_table *tbl; |
1042 | 1043 | ||
1043 | busnum = dev->bus->number; | 1044 | busnum = dev->bus->number; |
1044 | tbl = dev->sysdata; | 1045 | tbl = pci_iommu(dev->bus); |
1045 | bbar = tbl->bbar; | 1046 | bbar = tbl->bbar; |
1046 | 1047 | ||
1047 | /* enable TCE in PHB Config Register */ | 1048 | /* enable TCE in PHB Config Register */ |
@@ -1073,7 +1074,7 @@ static void __init calgary_disable_translation(struct pci_dev *dev) | |||
1073 | struct iommu_table *tbl; | 1074 | struct iommu_table *tbl; |
1074 | 1075 | ||
1075 | busnum = dev->bus->number; | 1076 | busnum = dev->bus->number; |
1076 | tbl = dev->sysdata; | 1077 | tbl = pci_iommu(dev->bus); |
1077 | bbar = tbl->bbar; | 1078 | bbar = tbl->bbar; |
1078 | 1079 | ||
1079 | /* disable TCE in PHB Config Register */ | 1080 | /* disable TCE in PHB Config Register */ |
@@ -1091,7 +1092,7 @@ static void __init calgary_disable_translation(struct pci_dev *dev) | |||
1091 | static void __init calgary_init_one_nontraslated(struct pci_dev *dev) | 1092 | static void __init calgary_init_one_nontraslated(struct pci_dev *dev) |
1092 | { | 1093 | { |
1093 | pci_dev_get(dev); | 1094 | pci_dev_get(dev); |
1094 | dev->sysdata = NULL; | 1095 | set_pci_iommu(dev->bus, NULL); |
1095 | 1096 | ||
1096 | /* is the device behind a bridge? */ | 1097 | /* is the device behind a bridge? */ |
1097 | if (dev->bus->parent) | 1098 | if (dev->bus->parent) |
@@ -1123,7 +1124,7 @@ static int __init calgary_init_one(struct pci_dev *dev) | |||
1123 | } else | 1124 | } else |
1124 | dev->bus->self = dev; | 1125 | dev->bus->self = dev; |
1125 | 1126 | ||
1126 | tbl = dev->sysdata; | 1127 | tbl = pci_iommu(dev->bus); |
1127 | tbl->chip_ops->handle_quirks(tbl, dev); | 1128 | tbl->chip_ops->handle_quirks(tbl, dev); |
1128 | 1129 | ||
1129 | calgary_enable_translation(dev); | 1130 | calgary_enable_translation(dev); |
@@ -1520,7 +1521,7 @@ static void __init calgary_fixup_one_tce_space(struct pci_dev *dev) | |||
1520 | unsigned int npages; | 1521 | unsigned int npages; |
1521 | int i; | 1522 | int i; |
1522 | 1523 | ||
1523 | tbl = dev->sysdata; | 1524 | tbl = pci_iommu(dev->bus); |
1524 | 1525 | ||
1525 | for (i = 0; i < 4; i++) { | 1526 | for (i = 0; i < 4; i++) { |
1526 | struct resource *r = &dev->resource[PCI_BRIDGE_RESOURCES + i]; | 1527 | struct resource *r = &dev->resource[PCI_BRIDGE_RESOURCES + i]; |
diff --git a/arch/x86_64/kernel/tce.c b/arch/x86_64/kernel/tce.c index f61fb8e4f129..3aeae2fa2e24 100644 --- a/arch/x86_64/kernel/tce.c +++ b/arch/x86_64/kernel/tce.c | |||
@@ -136,9 +136,9 @@ int build_tce_table(struct pci_dev *dev, void __iomem *bbar) | |||
136 | struct iommu_table *tbl; | 136 | struct iommu_table *tbl; |
137 | int ret; | 137 | int ret; |
138 | 138 | ||
139 | if (dev->sysdata) { | 139 | if (pci_iommu(dev->bus)) { |
140 | printk(KERN_ERR "Calgary: dev %p has sysdata %p\n", | 140 | printk(KERN_ERR "Calgary: dev %p has sysdata->iommu %p\n", |
141 | dev, dev->sysdata); | 141 | dev, pci_iommu(dev->bus)); |
142 | BUG(); | 142 | BUG(); |
143 | } | 143 | } |
144 | 144 | ||
@@ -155,11 +155,7 @@ int build_tce_table(struct pci_dev *dev, void __iomem *bbar) | |||
155 | 155 | ||
156 | tbl->bbar = bbar; | 156 | tbl->bbar = bbar; |
157 | 157 | ||
158 | /* | 158 | set_pci_iommu(dev->bus, tbl); |
159 | * NUMA is already using the bus's sysdata pointer, so we use | ||
160 | * the bus's pci_dev's sysdata instead. | ||
161 | */ | ||
162 | dev->sysdata = tbl; | ||
163 | 159 | ||
164 | return 0; | 160 | return 0; |
165 | 161 | ||
diff --git a/arch/x86_64/pci/k8-bus.c b/arch/x86_64/pci/k8-bus.c index 3acf60ded2a0..9cc813e29706 100644 --- a/arch/x86_64/pci/k8-bus.c +++ b/arch/x86_64/pci/k8-bus.c | |||
@@ -59,6 +59,8 @@ fill_mp_bus_to_cpumask(void) | |||
59 | j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus); | 59 | j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus); |
60 | j++) { | 60 | j++) { |
61 | struct pci_bus *bus; | 61 | struct pci_bus *bus; |
62 | struct pci_sysdata *sd; | ||
63 | |||
62 | long node = NODE_ID(nid); | 64 | long node = NODE_ID(nid); |
63 | /* Algorithm a bit dumb, but | 65 | /* Algorithm a bit dumb, but |
64 | it shouldn't matter here */ | 66 | it shouldn't matter here */ |
@@ -67,7 +69,9 @@ fill_mp_bus_to_cpumask(void) | |||
67 | continue; | 69 | continue; |
68 | if (!node_online(node)) | 70 | if (!node_online(node)) |
69 | node = 0; | 71 | node = 0; |
70 | bus->sysdata = (void *)node; | 72 | |
73 | sd = bus->sysdata; | ||
74 | sd->node = node; | ||
71 | } | 75 | } |
72 | } | 76 | } |
73 | } | 77 | } |
diff --git a/include/asm-i386/pci.h b/include/asm-i386/pci.h index 392d3fe5d45e..d790343e9982 100644 --- a/include/asm-i386/pci.h +++ b/include/asm-i386/pci.h | |||
@@ -3,6 +3,11 @@ | |||
3 | 3 | ||
4 | 4 | ||
5 | #ifdef __KERNEL__ | 5 | #ifdef __KERNEL__ |
6 | |||
7 | struct pci_sysdata { | ||
8 | int node; /* NUMA node */ | ||
9 | }; | ||
10 | |||
6 | #include <linux/mm.h> /* for struct page */ | 11 | #include <linux/mm.h> /* for struct page */ |
7 | 12 | ||
8 | /* Can be used to override the logic in pci_scan_bus for skipping | 13 | /* Can be used to override the logic in pci_scan_bus for skipping |
diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h index 7fc512d90ea8..19b2dafd0c81 100644 --- a/include/asm-i386/topology.h +++ b/include/asm-i386/topology.h | |||
@@ -67,7 +67,7 @@ static inline int node_to_first_cpu(int node) | |||
67 | return first_cpu(mask); | 67 | return first_cpu(mask); |
68 | } | 68 | } |
69 | 69 | ||
70 | #define pcibus_to_node(bus) ((long) (bus)->sysdata) | 70 | #define pcibus_to_node(bus) ((struct pci_sysdata *)((bus)->sysdata))->node |
71 | #define pcibus_to_cpumask(bus) node_to_cpumask(pcibus_to_node(bus)) | 71 | #define pcibus_to_cpumask(bus) node_to_cpumask(pcibus_to_node(bus)) |
72 | 72 | ||
73 | /* sched_domains SD_NODE_INIT for NUMAQ machines */ | 73 | /* sched_domains SD_NODE_INIT for NUMAQ machines */ |
diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h index bda94fd5176f..88926eb44f5c 100644 --- a/include/asm-x86_64/pci.h +++ b/include/asm-x86_64/pci.h | |||
@@ -5,6 +5,25 @@ | |||
5 | 5 | ||
6 | #ifdef __KERNEL__ | 6 | #ifdef __KERNEL__ |
7 | 7 | ||
8 | struct pci_sysdata { | ||
9 | int node; /* NUMA node */ | ||
10 | void* iommu; /* IOMMU private data */ | ||
11 | }; | ||
12 | |||
13 | #ifdef CONFIG_CALGARY_IOMMU | ||
14 | static inline void* pci_iommu(struct pci_bus *bus) | ||
15 | { | ||
16 | struct pci_sysdata *sd = bus->sysdata; | ||
17 | return sd->iommu; | ||
18 | } | ||
19 | |||
20 | static inline void set_pci_iommu(struct pci_bus *bus, void *val) | ||
21 | { | ||
22 | struct pci_sysdata *sd = bus->sysdata; | ||
23 | sd->iommu = val; | ||
24 | } | ||
25 | #endif /* CONFIG_CALGARY_IOMMU */ | ||
26 | |||
8 | #include <linux/mm.h> /* for struct page */ | 27 | #include <linux/mm.h> /* for struct page */ |
9 | 28 | ||
10 | /* Can be used to override the logic in pci_scan_bus for skipping | 29 | /* Can be used to override the logic in pci_scan_bus for skipping |
diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h index 4fd6fb23953e..36e52fba7960 100644 --- a/include/asm-x86_64/topology.h +++ b/include/asm-x86_64/topology.h | |||
@@ -22,7 +22,7 @@ extern int __node_distance(int, int); | |||
22 | #define parent_node(node) (node) | 22 | #define parent_node(node) (node) |
23 | #define node_to_first_cpu(node) (first_cpu(node_to_cpumask[node])) | 23 | #define node_to_first_cpu(node) (first_cpu(node_to_cpumask[node])) |
24 | #define node_to_cpumask(node) (node_to_cpumask[node]) | 24 | #define node_to_cpumask(node) (node_to_cpumask[node]) |
25 | #define pcibus_to_node(bus) ((long)(bus->sysdata)) | 25 | #define pcibus_to_node(bus) ((struct pci_sysdata *)((bus)->sysdata))->node |
26 | #define pcibus_to_cpumask(bus) node_to_cpumask(pcibus_to_node(bus)); | 26 | #define pcibus_to_cpumask(bus) node_to_cpumask(pcibus_to_node(bus)); |
27 | 27 | ||
28 | #define numa_node_id() read_pda(nodenumber) | 28 | #define numa_node_id() read_pda(nodenumber) |