diff options
Diffstat (limited to 'arch/i386/pci')
-rw-r--r-- | arch/i386/pci/common.c | 23 | ||||
-rw-r--r-- | arch/i386/pci/fixup.c | 6 | ||||
-rw-r--r-- | arch/i386/pci/irq.c | 5 | ||||
-rw-r--r-- | arch/i386/pci/legacy.c | 2 | ||||
-rw-r--r-- | arch/i386/pci/mmconfig.c | 14 | ||||
-rw-r--r-- | arch/i386/pci/numa.c | 15 | ||||
-rw-r--r-- | arch/i386/pci/pci.h | 43 | ||||
-rw-r--r-- | arch/i386/pci/visws.c | 4 |
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 | |||
459 | struct 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 | } |
48 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx); | 48 | DECLARE_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); | |||
104 | extern int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus, | 104 | extern int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus, |
105 | unsigned int devfn); | 105 | unsigned int devfn); |
106 | extern int __init pci_mmcfg_arch_init(void); | 106 | extern 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 | */ | ||
115 | static 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 | |||
122 | static 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 | |||
129 | static 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 | |||
136 | static inline void mmio_config_writeb(void __iomem *pos, u8 val) | ||
137 | { | ||
138 | asm volatile("movb %%al,(%1)" :: "a" (val), "r" (pos) : "memory"); | ||
139 | } | ||
140 | |||
141 | static inline void mmio_config_writew(void __iomem *pos, u16 val) | ||
142 | { | ||
143 | asm volatile("movw %%ax,(%1)" :: "a" (val), "r" (pos) : "memory"); | ||
144 | } | ||
145 | |||
146 | static 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; |