aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/pci/mmconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/pci/mmconfig.c')
-rw-r--r--arch/x86_64/pci/mmconfig.c53
1 files changed, 37 insertions, 16 deletions
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index e616500207e4..a2060e4d5de6 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -9,11 +9,16 @@
9#include <linux/init.h> 9#include <linux/init.h>
10#include <linux/acpi.h> 10#include <linux/acpi.h>
11#include <linux/bitmap.h> 11#include <linux/bitmap.h>
12#include <asm/e820.h>
13
12#include "pci.h" 14#include "pci.h"
13 15
14#define MMCONFIG_APER_SIZE (256*1024*1024) 16#define MMCONFIG_APER_SIZE (256*1024*1024)
17/* Verify the first 16 busses. We assume that systems with more busses
18 get MCFG right. */
19#define MAX_CHECK_BUS 16
15 20
16static DECLARE_BITMAP(fallback_slots, 32); 21static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS);
17 22
18/* Static virtual mapping of the MMCONFIG aperture */ 23/* Static virtual mapping of the MMCONFIG aperture */
19struct mmcfg_virt { 24struct mmcfg_virt {
@@ -55,7 +60,8 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
55static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) 60static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
56{ 61{
57 char __iomem *addr; 62 char __iomem *addr;
58 if (seg == 0 && bus == 0 && test_bit(PCI_SLOT(devfn), fallback_slots)) 63 if (seg == 0 && bus < MAX_CHECK_BUS &&
64 test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
59 return NULL; 65 return NULL;
60 addr = get_virt(seg, bus); 66 addr = get_virt(seg, bus);
61 if (!addr) 67 if (!addr)
@@ -69,8 +75,10 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
69 char __iomem *addr; 75 char __iomem *addr;
70 76
71 /* Why do we have this when nobody checks it. How about a BUG()!? -AK */ 77 /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
72 if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095))) 78 if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
79 *value = -1;
73 return -EINVAL; 80 return -EINVAL;
81 }
74 82
75 addr = pci_dev_base(seg, bus, devfn); 83 addr = pci_dev_base(seg, bus, devfn);
76 if (!addr) 84 if (!addr)
@@ -129,21 +137,26 @@ static struct pci_raw_ops pci_mmcfg = {
129 Normally this can be expressed in the MCFG by not listing them 137 Normally this can be expressed in the MCFG by not listing them
130 and assigning suitable _SEGs, but this isn't implemented in some BIOS. 138 and assigning suitable _SEGs, but this isn't implemented in some BIOS.
131 Instead try to discover all devices on bus 0 that are unreachable using MM 139 Instead try to discover all devices on bus 0 that are unreachable using MM
132 and fallback for them. 140 and fallback for them. */
133 We only do this for bus 0/seg 0 */
134static __init void unreachable_devices(void) 141static __init void unreachable_devices(void)
135{ 142{
136 int i; 143 int i, k;
137 for (i = 0; i < 32; i++) { 144 /* Use the max bus number from ACPI here? */
138 u32 val1; 145 for (k = 0; k < MAX_CHECK_BUS; k++) {
139 char __iomem *addr; 146 for (i = 0; i < 32; i++) {
140 147 u32 val1;
141 pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1); 148 char __iomem *addr;
142 if (val1 == 0xffffffff) 149
143 continue; 150 pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
144 addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0)); 151 if (val1 == 0xffffffff)
145 if (addr == NULL|| readl(addr) != val1) { 152 continue;
146 set_bit(i, fallback_slots); 153 addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
154 if (addr == NULL|| readl(addr) != val1) {
155 set_bit(i + 32*k, fallback_slots);
156 printk(KERN_NOTICE
157 "PCI: No mmconfig possible on device %x:%x\n",
158 k, i);
159 }
147 } 160 }
148 } 161 }
149} 162}
@@ -161,6 +174,14 @@ void __init pci_mmcfg_init(void)
161 (pci_mmcfg_config[0].base_address == 0)) 174 (pci_mmcfg_config[0].base_address == 0))
162 return; 175 return;
163 176
177 if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
178 pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE,
179 E820_RESERVED)) {
180 printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n");
181 printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
182 return;
183 }
184
164 /* RED-PEN i386 doesn't do _nocache right now */ 185 /* RED-PEN i386 doesn't do _nocache right now */
165 pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL); 186 pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
166 if (pci_mmcfg_virt == NULL) { 187 if (pci_mmcfg_virt == NULL) {