aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/pci
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/pci')
-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/mmconfig.c14
-rw-r--r--arch/i386/pci/numa.c15
-rw-r--r--arch/i386/pci/pci.h43
-rw-r--r--arch/i386/pci/visws.c4
8 files changed, 90 insertions, 22 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/mmconfig.c b/arch/i386/pci/mmconfig.c
index bb1afd9e589d..1bf5816d34c8 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -82,16 +82,15 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
82 82
83 switch (len) { 83 switch (len) {
84 case 1: 84 case 1:
85 *value = readb(mmcfg_virt_addr + reg); 85 *value = mmio_config_readb(mmcfg_virt_addr + reg);
86 break; 86 break;
87 case 2: 87 case 2:
88 *value = readw(mmcfg_virt_addr + reg); 88 *value = mmio_config_readw(mmcfg_virt_addr + reg);
89 break; 89 break;
90 case 4: 90 case 4:
91 *value = readl(mmcfg_virt_addr + reg); 91 *value = mmio_config_readl(mmcfg_virt_addr + reg);
92 break; 92 break;
93 } 93 }
94
95 spin_unlock_irqrestore(&pci_config_lock, flags); 94 spin_unlock_irqrestore(&pci_config_lock, flags);
96 95
97 return 0; 96 return 0;
@@ -116,16 +115,15 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
116 115
117 switch (len) { 116 switch (len) {
118 case 1: 117 case 1:
119 writeb(value, mmcfg_virt_addr + reg); 118 mmio_config_writeb(mmcfg_virt_addr + reg, value);
120 break; 119 break;
121 case 2: 120 case 2:
122 writew(value, mmcfg_virt_addr + reg); 121 mmio_config_writew(mmcfg_virt_addr + reg, value);
123 break; 122 break;
124 case 4: 123 case 4:
125 writel(value, mmcfg_virt_addr + reg); 124 mmio_config_writel(mmcfg_virt_addr + reg, value);
126 break; 125 break;
127 } 126 }
128
129 spin_unlock_irqrestore(&pci_config_lock, flags); 127 spin_unlock_irqrestore(&pci_config_lock, flags);
130 128
131 return 0; 129 return 0;
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/pci.h b/arch/i386/pci/pci.h
index e58bae2076ad..8c66f275756f 100644
--- a/arch/i386/pci/pci.h
+++ b/arch/i386/pci/pci.h
@@ -104,3 +104,46 @@ extern DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
104extern int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus, 104extern int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
105 unsigned int devfn); 105 unsigned int devfn);
106extern int __init pci_mmcfg_arch_init(void); 106extern int __init pci_mmcfg_arch_init(void);
107
108/*
109 * AMD Fam10h CPUs are buggy, and cannot access MMIO config space
110 * on their northbrige except through the * %eax register. As such, you MUST
111 * NOT use normal IOMEM accesses, you need to only use the magic mmio-config
112 * accessor functions.
113 * In fact just use pci_config_*, nothing else please.
114 */
115static inline unsigned char mmio_config_readb(void __iomem *pos)
116{
117 u8 val;
118 asm volatile("movb (%1),%%al" : "=a" (val) : "r" (pos));
119 return val;
120}
121
122static inline unsigned short mmio_config_readw(void __iomem *pos)
123{
124 u16 val;
125 asm volatile("movw (%1),%%ax" : "=a" (val) : "r" (pos));
126 return val;
127}
128
129static inline unsigned int mmio_config_readl(void __iomem *pos)
130{
131 u32 val;
132 asm volatile("movl (%1),%%eax" : "=a" (val) : "r" (pos));
133 return val;
134}
135
136static inline void mmio_config_writeb(void __iomem *pos, u8 val)
137{
138 asm volatile("movb %%al,(%1)" :: "a" (val), "r" (pos) : "memory");
139}
140
141static inline void mmio_config_writew(void __iomem *pos, u16 val)
142{
143 asm volatile("movw %%ax,(%1)" :: "a" (val), "r" (pos) : "memory");
144}
145
146static inline void mmio_config_writel(void __iomem *pos, u32 val)
147{
148 asm volatile("movl %%eax,(%1)" :: "a" (val), "r" (pos) : "memory");
149}
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;