diff options
author | Muli Ben-Yehuda <muli@il.ibm.com> | 2007-07-21 17:23:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-21 21:37:14 -0400 |
commit | 08f1c192c3c32797068bfe97738babb3295bbf42 (patch) | |
tree | e875b7b97b081ddc1eb9db8e4435d5ecf65ebadc | |
parent | 7557244ba27f63404236cb27277b98c27d856692 (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.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) |