aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMuli Ben-Yehuda <muli@il.ibm.com>2007-07-21 17:23:39 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-21 21:37:14 -0400
commit08f1c192c3c32797068bfe97738babb3295bbf42 (patch)
treee875b7b97b081ddc1eb9db8e4435d5ecf65ebadc
parent7557244ba27f63404236cb27277b98c27d856692 (diff)
x86-64: introduce struct pci_sysdata to facilitate sharing of ->sysdata
This patch introduces struct pci_sysdata to x86 and x86-64, and converts the existing two users (NUMA, Calgary) to use it. This lays the groundwork for having other users of sysdata, such as the PCI domains work. The Calgary bits are tested, the NUMA bits just look ok. Signed-off-by: Jeff Garzik <jeff@garzik.org> Signed-off-by: Muli Ben-Yehuda <muli@il.ibm.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-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)