aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMuli Ben-Yehuda <muli@il.ibm.com>2007-08-10 16:01:19 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-08-11 18:47:42 -0400
commit73c59afc65cfa50c3362b9ce1ec151a79c41dd8e (patch)
treeaef70231e894fcbd28d94a29e306c2856dbc9e3a
parentf0b85c0cfdad8977d82fed88e846fc2245585d0e (diff)
finish i386 and x86-64 sysdata conversion
This patch finishes the i386 and x86-64 ->sysdata conversion and hopefully also fixes Riku's and Andy's observed bugs. It is based on Yinghai Lu's and Andy Whitcroft's patches (thanks!) with some changes: - introduce pci_scan_bus_with_sysdata() and use it instead of pci_scan_bus() where appropriate. pci_scan_bus_with_sysdata() will allocate the sysdata structure and then call pci_scan_bus(). - always allocate pci_sysdata dynamically. The whole point of this sysdata work is to make it easy to do root-bus specific things (e.g., support PCI domains and IOMMU's). I dislike using a default struct pci_sysdata in some places and a dynamically allocated pci_sysdata elsewhere - the potential for someone indavertantly changing the default structure is too high. - this patch only makes the minimal changes necessary, i.e., the NUMA node is always initialized to -1. Patches to do the right thing with regards to the NUMA node can build on top of this (either add a 'node' parameter to pci_scan_bus_with_sysdata() or just update the node when it becomes known). The patch was compile tested with various configurations (e.g., NUMAQ, VISWS) and run-time tested on i386 and x86-64. Unfortunately none of my machines exhibited the bugs so caveat emptor. Andy, could you please see if this fixes the NUMA issues you've seen? Riku, does this fix "pci=noacpi" on your laptop? Signed-off-by: Muli Ben-Yehuda <muli@il.ibm.com> Cc: Yinghai Lu <yhlu.kernel@gmail.com> Cc: Andi Kleen <ak@suse.de> Cc: Chuck Ebbert <cebbert@redhat.com> Cc: <riku.seppala@kymp.net> Cc: Andy Whitcroft <apw@shadowen.org> Cc: Jeff Garzik <jeff@garzik.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/i386/pci/common.c23
-rw-r--r--arch/i386/pci/fixup.c6
-rw-r--r--arch/i386/pci/irq.c5
-rw-r--r--arch/i386/pci/legacy.c2
-rw-r--r--arch/i386/pci/numa.c15
-rw-r--r--arch/i386/pci/visws.c4
-rw-r--r--include/asm-i386/pci.h3
-rw-r--r--include/asm-x86_64/pci.h2
8 files changed, 46 insertions, 14 deletions
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index 85503deeda46..ebc6f3c66340 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -455,3 +455,26 @@ void pcibios_disable_device (struct pci_dev *dev)
455 if (!dev->msi_enabled && pcibios_disable_irq) 455 if (!dev->msi_enabled && pcibios_disable_irq)
456 pcibios_disable_irq(dev); 456 pcibios_disable_irq(dev);
457} 457}
458
459struct pci_bus *pci_scan_bus_with_sysdata(int busno)
460{
461 struct pci_bus *bus = NULL;
462 struct pci_sysdata *sd;
463
464 /*
465 * Allocate per-root-bus (not per bus) arch-specific data.
466 * TODO: leak; this memory is never freed.
467 * It's arguable whether it's worth the trouble to care.
468 */
469 sd = kzalloc(sizeof(*sd), GFP_KERNEL);
470 if (!sd) {
471 printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busno);
472 return NULL;
473 }
474 sd->node = -1;
475 bus = pci_scan_bus(busno, &pci_root_ops, sd);
476 if (!bus)
477 kfree(sd);
478
479 return bus;
480}
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
index e7306dbf6c42..c82cbf4c7226 100644
--- a/arch/i386/pci/fixup.c
+++ b/arch/i386/pci/fixup.c
@@ -25,9 +25,9 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
25 pci_read_config_byte(d, reg++, &subb); 25 pci_read_config_byte(d, reg++, &subb);
26 DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb); 26 DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
27 if (busno) 27 if (busno)
28 pci_scan_bus(busno, &pci_root_ops, NULL); /* Bus A */ 28 pci_scan_bus_with_sysdata(busno); /* Bus A */
29 if (suba < subb) 29 if (suba < subb)
30 pci_scan_bus(suba+1, &pci_root_ops, NULL); /* Bus B */ 30 pci_scan_bus_with_sysdata(suba+1); /* Bus B */
31 } 31 }
32 pcibios_last_bus = -1; 32 pcibios_last_bus = -1;
33} 33}
@@ -42,7 +42,7 @@ static void __devinit pci_fixup_i450gx(struct pci_dev *d)
42 u8 busno; 42 u8 busno;
43 pci_read_config_byte(d, 0x4a, &busno); 43 pci_read_config_byte(d, 0x4a, &busno);
44 printk(KERN_INFO "PCI: i440KX/GX host bridge %s: secondary bus %02x\n", pci_name(d), busno); 44 printk(KERN_INFO "PCI: i440KX/GX host bridge %s: secondary bus %02x\n", pci_name(d), busno);
45 pci_scan_bus(busno, &pci_root_ops, NULL); 45 pci_scan_bus_with_sysdata(busno);
46 pcibios_last_bus = -1; 46 pcibios_last_bus = -1;
47} 47}
48DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx); 48DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx);
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index f2cb942f8281..665db063a40a 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -138,8 +138,9 @@ static void __init pirq_peer_trick(void)
138 for(i = 1; i < 256; i++) { 138 for(i = 1; i < 256; i++) {
139 if (!busmap[i] || pci_find_bus(0, i)) 139 if (!busmap[i] || pci_find_bus(0, i))
140 continue; 140 continue;
141 if (pci_scan_bus(i, &pci_root_ops, NULL)) 141 if (pci_scan_bus_with_sysdata(i))
142 printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i); 142 printk(KERN_INFO "PCI: Discovered primary peer "
143 "bus %02x [IRQ]\n", i);
143 } 144 }
144 pcibios_last_bus = -1; 145 pcibios_last_bus = -1;
145} 146}
diff --git a/arch/i386/pci/legacy.c b/arch/i386/pci/legacy.c
index 149a9588c256..5565d7016b75 100644
--- a/arch/i386/pci/legacy.c
+++ b/arch/i386/pci/legacy.c
@@ -26,7 +26,7 @@ static void __devinit pcibios_fixup_peer_bridges(void)
26 l != 0x0000 && l != 0xffff) { 26 l != 0x0000 && l != 0xffff) {
27 DBG("Found device at %02x:%02x [%04x]\n", n, devfn, l); 27 DBG("Found device at %02x:%02x [%04x]\n", n, devfn, l);
28 printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n); 28 printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
29 pci_scan_bus(n, &pci_root_ops, NULL); 29 pci_scan_bus_with_sysdata(n);
30 break; 30 break;
31 } 31 }
32 } 32 }
diff --git a/arch/i386/pci/numa.c b/arch/i386/pci/numa.c
index adbe17a38f6f..f5f165f69e0c 100644
--- a/arch/i386/pci/numa.c
+++ b/arch/i386/pci/numa.c
@@ -96,10 +96,14 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
96 pci_read_config_byte(d, reg++, &suba); 96 pci_read_config_byte(d, reg++, &suba);
97 pci_read_config_byte(d, reg++, &subb); 97 pci_read_config_byte(d, reg++, &subb);
98 DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb); 98 DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
99 if (busno) 99 if (busno) {
100 pci_scan_bus(QUADLOCAL2BUS(quad,busno), &pci_root_ops, NULL); /* Bus A */ 100 /* Bus A */
101 if (suba < subb) 101 pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, busno));
102 pci_scan_bus(QUADLOCAL2BUS(quad,suba+1), &pci_root_ops, NULL); /* Bus B */ 102 }
103 if (suba < subb) {
104 /* Bus B */
105 pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, suba+1));
106 }
103 } 107 }
104 pcibios_last_bus = -1; 108 pcibios_last_bus = -1;
105} 109}
@@ -123,8 +127,7 @@ static int __init pci_numa_init(void)
123 continue; 127 continue;
124 printk("Scanning PCI bus %d for quad %d\n", 128 printk("Scanning PCI bus %d for quad %d\n",
125 QUADLOCAL2BUS(quad,0), quad); 129 QUADLOCAL2BUS(quad,0), quad);
126 pci_scan_bus(QUADLOCAL2BUS(quad,0), 130 pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, 0));
127 &pci_root_ops, NULL);
128 } 131 }
129 return 0; 132 return 0;
130} 133}
diff --git a/arch/i386/pci/visws.c b/arch/i386/pci/visws.c
index f1b486d4190b..8ecb1c722594 100644
--- a/arch/i386/pci/visws.c
+++ b/arch/i386/pci/visws.c
@@ -101,8 +101,8 @@ static int __init pcibios_init(void)
101 "bridge B (PIIX4) bus: %u\n", pci_bus1, pci_bus0); 101 "bridge B (PIIX4) bus: %u\n", pci_bus1, pci_bus0);
102 102
103 raw_pci_ops = &pci_direct_conf1; 103 raw_pci_ops = &pci_direct_conf1;
104 pci_scan_bus(pci_bus0, &pci_root_ops, NULL); 104 pci_scan_bus_with_sysdata(pci_bus0);
105 pci_scan_bus(pci_bus1, &pci_root_ops, NULL); 105 pci_scan_bus_with_sysdata(pci_bus1);
106 pci_fixup_irqs(visws_swizzle, visws_map_irq); 106 pci_fixup_irqs(visws_swizzle, visws_map_irq);
107 pcibios_resource_survey(); 107 pcibios_resource_survey();
108 return 0; 108 return 0;
diff --git a/include/asm-i386/pci.h b/include/asm-i386/pci.h
index d790343e9982..4fcacc711385 100644
--- a/include/asm-i386/pci.h
+++ b/include/asm-i386/pci.h
@@ -8,6 +8,9 @@ struct pci_sysdata {
8 int node; /* NUMA node */ 8 int node; /* NUMA node */
9}; 9};
10 10
11/* scan a bus after allocating a pci_sysdata for it */
12extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);
13
11#include <linux/mm.h> /* for struct page */ 14#include <linux/mm.h> /* for struct page */
12 15
13/* Can be used to override the logic in pci_scan_bus for skipping 16/* Can be used to override the logic in pci_scan_bus for skipping
diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h
index 88926eb44f5c..5da8cb0c0599 100644
--- a/include/asm-x86_64/pci.h
+++ b/include/asm-x86_64/pci.h
@@ -10,6 +10,8 @@ struct pci_sysdata {
10 void* iommu; /* IOMMU private data */ 10 void* iommu; /* IOMMU private data */
11}; 11};
12 12
13extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);
14
13#ifdef CONFIG_CALGARY_IOMMU 15#ifdef CONFIG_CALGARY_IOMMU
14static inline void* pci_iommu(struct pci_bus *bus) 16static inline void* pci_iommu(struct pci_bus *bus)
15{ 17{