aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/pci/acpi.c32
-rw-r--r--arch/i386/pci/common.c13
-rw-r--r--arch/x86_64/kernel/pci-calgary.c29
-rw-r--r--arch/x86_64/kernel/tce.c12
-rw-r--r--arch/x86_64/pci/k8-bus.c6
-rw-r--r--include/asm-i386/pci.h5
-rw-r--r--include/asm-i386/topology.h2
-rw-r--r--include/asm-x86_64/pci.h19
-rw-r--r--include/asm-x86_64/topology.h2
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 @@
8struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) 8struct 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[] = {
293struct pci_bus * __devinit pcibios_scan_root(int busnum) 293struct 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
311extern u8 pci_cache_line_size; 322extern 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
722static void __init calgary_reserve_peripheral_mem_1(struct pci_dev *dev) 722static 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)
855static void __init calgary_free_bus(struct pci_dev *dev) 855static 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)
943static void calgary_watchdog(unsigned long data) 944static 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)
1091static void __init calgary_init_one_nontraslated(struct pci_dev *dev) 1092static 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
7struct 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
8struct pci_sysdata {
9 int node; /* NUMA node */
10 void* iommu; /* IOMMU private data */
11};
12
13#ifdef CONFIG_CALGARY_IOMMU
14static inline void* pci_iommu(struct pci_bus *bus)
15{
16 struct pci_sysdata *sd = bus->sysdata;
17 return sd->iommu;
18}
19
20static 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)