[PATCH] mmconfig: Reject a broken MCFG tables on Asus etc
[pandora-kernel.git] / arch / i386 / pci / mmconfig-shared.c
1 /*
2  * mmconfig-shared.c - Low-level direct PCI config space access via
3  *                     MMCONFIG - common code between i386 and x86-64.
4  *
5  * This code does:
6  * - known chipset handling
7  * - ACPI decoding and validation
8  *
9  * Per-architecture code takes care of the mappings and accesses
10  * themselves.
11  */
12
13 #include <linux/pci.h>
14 #include <linux/init.h>
15 #include <linux/acpi.h>
16 #include <linux/bitmap.h>
17 #include <asm/e820.h>
18
19 #include "pci.h"
20
21 /* aperture is up to 256MB but BIOS may reserve less */
22 #define MMCONFIG_APER_MIN       (2 * 1024*1024)
23 #define MMCONFIG_APER_MAX       (256 * 1024*1024)
24
25 /* Verify the first 16 busses. We assume that systems with more busses
26    get MCFG right. */
27 #define PCI_MMCFG_MAX_CHECK_BUS 16
28
29 DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
30
31 /* K8 systems have some devices (typically in the builtin northbridge)
32    that are only accessible using type1
33    Normally this can be expressed in the MCFG by not listing them
34    and assigning suitable _SEGs, but this isn't implemented in some BIOS.
35    Instead try to discover all devices on bus 0 that are unreachable using MM
36    and fallback for them. */
37 static __init void unreachable_devices(void)
38 {
39         int i, k;
40         /* Use the max bus number from ACPI here? */
41         for (k = 0; k < PCI_MMCFG_MAX_CHECK_BUS; k++) {
42                 for (i = 0; i < 32; i++) {
43                         u32 val1, val2;
44
45                         pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
46                         if (val1 == 0xffffffff)
47                                 continue;
48
49                         raw_pci_ops->read(0, k, PCI_DEVFN(i, 0), 0, 4, &val2);
50                         if (val1 != val2) {
51                                 set_bit(i + 32*k, pci_mmcfg_fallback_slots);
52                                 printk(KERN_NOTICE "PCI: No mmconfig possible"
53                                        " on device %02x:%02x\n", k, i);
54                         }
55                 }
56         }
57 }
58
59 static __init const char *pci_mmcfg_e7520(void)
60 {
61         u32 win;
62         pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
63
64         pci_mmcfg_config_num = 1;
65         pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
66         if (!pci_mmcfg_config)
67                 return NULL;
68         pci_mmcfg_config[0].address = (win & 0xf000) << 16;
69         pci_mmcfg_config[0].pci_segment = 0;
70         pci_mmcfg_config[0].start_bus_number = 0;
71         pci_mmcfg_config[0].end_bus_number = 255;
72
73         return "Intel Corporation E7520 Memory Controller Hub";
74 }
75
76 static __init const char *pci_mmcfg_intel_945(void)
77 {
78         u32 pciexbar, mask = 0, len = 0;
79
80         pci_mmcfg_config_num = 1;
81
82         pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
83
84         /* Enable bit */
85         if (!(pciexbar & 1))
86                 pci_mmcfg_config_num = 0;
87
88         /* Size bits */
89         switch ((pciexbar >> 1) & 3) {
90         case 0:
91                 mask = 0xf0000000U;
92                 len  = 0x10000000U;
93                 break;
94         case 1:
95                 mask = 0xf8000000U;
96                 len  = 0x08000000U;
97                 break;
98         case 2:
99                 mask = 0xfc000000U;
100                 len  = 0x04000000U;
101                 break;
102         default:
103                 pci_mmcfg_config_num = 0;
104         }
105
106         /* Errata #2, things break when not aligned on a 256Mb boundary */
107         /* Can only happen in 64M/128M mode */
108
109         if ((pciexbar & mask) & 0x0fffffffU)
110                 pci_mmcfg_config_num = 0;
111
112         if (pci_mmcfg_config_num) {
113                 pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
114                 if (!pci_mmcfg_config)
115                         return NULL;
116                 pci_mmcfg_config[0].address = pciexbar & mask;
117                 pci_mmcfg_config[0].pci_segment = 0;
118                 pci_mmcfg_config[0].start_bus_number = 0;
119                 pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1;
120         }
121
122         return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
123 }
124
125 struct pci_mmcfg_hostbridge_probe {
126         u32 vendor;
127         u32 device;
128         const char *(*probe)(void);
129 };
130
131 static __initdata struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] = {
132         { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
133         { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
134 };
135
136 static int __init pci_mmcfg_check_hostbridge(void)
137 {
138         u32 l;
139         u16 vendor, device;
140         int i;
141         const char *name;
142
143         pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
144         vendor = l & 0xffff;
145         device = (l >> 16) & 0xffff;
146
147         pci_mmcfg_config_num = 0;
148         pci_mmcfg_config = NULL;
149         name = NULL;
150
151         for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++)
152                 if ((pci_mmcfg_probes[i].vendor == PCI_ANY_ID ||
153                      pci_mmcfg_probes[i].vendor == vendor) &&
154                     (pci_mmcfg_probes[i].device == PCI_ANY_ID ||
155                      pci_mmcfg_probes[i].device == device))
156                         name = pci_mmcfg_probes[i].probe();
157
158         if (name) {
159                 if (pci_mmcfg_config_num)
160                         printk(KERN_INFO "PCI: Found %s with MMCONFIG support.\n", name);
161                 else
162                         printk(KERN_INFO "PCI: Found %s without MMCONFIG support.\n",
163                                name);
164         }
165
166         return name != NULL;
167 }
168
169 static __init void pci_mmcfg_insert_resources(void)
170 {
171 #define PCI_MMCFG_RESOURCE_NAME_LEN 19
172         int i;
173         struct resource *res;
174         char *names;
175         unsigned num_buses;
176
177         res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res),
178                         pci_mmcfg_config_num, GFP_KERNEL);
179
180         if (!res) {
181                 printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n");
182                 return;
183         }
184
185         names = (void *)&res[pci_mmcfg_config_num];
186         for (i = 0; i < pci_mmcfg_config_num; i++, res++) {
187                 num_buses = pci_mmcfg_config[i].end_bus_number -
188                     pci_mmcfg_config[i].start_bus_number + 1;
189                 res->name = names;
190                 snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
191                         pci_mmcfg_config[i].pci_segment);
192                 res->start = pci_mmcfg_config[i].address;
193                 res->end = res->start + (num_buses << 20) - 1;
194                 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
195                 insert_resource(&iomem_resource, res);
196                 names += PCI_MMCFG_RESOURCE_NAME_LEN;
197         }
198 }
199
200 static void __init pci_mmcfg_reject_broken(void)
201 {
202         typeof(pci_mmcfg_config[0]) *cfg = &pci_mmcfg_config[0];
203
204         /*
205          * Handle more broken MCFG tables on Asus etc.
206          * They only contain a single entry for bus 0-0.
207          */
208         if (pci_mmcfg_config_num == 1 &&
209             cfg->pci_segment == 0 &&
210             (cfg->start_bus_number | cfg->end_bus_number) == 0) {
211                 kfree(pci_mmcfg_config);
212                 pci_mmcfg_config = NULL;
213                 pci_mmcfg_config_num = 0;
214
215                 printk(KERN_ERR "PCI: start and end of bus number is 0. "
216                        "Rejected as broken MCFG.");
217         }
218 }
219
220 void __init pci_mmcfg_init(int type)
221 {
222         int known_bridge = 0;
223
224         if ((pci_probe & PCI_PROBE_MMCONF) == 0)
225                 return;
226
227         if (type == 1 && pci_mmcfg_check_hostbridge())
228                 known_bridge = 1;
229
230         if (!known_bridge) {
231                 acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
232                 pci_mmcfg_reject_broken();
233         }
234
235         if ((pci_mmcfg_config_num == 0) ||
236             (pci_mmcfg_config == NULL) ||
237             (pci_mmcfg_config[0].address == 0))
238                 return;
239
240         /* Only do this check when type 1 works. If it doesn't work
241            assume we run on a Mac and always use MCFG */
242         if (type == 1 && !known_bridge &&
243             !e820_all_mapped(pci_mmcfg_config[0].address,
244                              pci_mmcfg_config[0].address + MMCONFIG_APER_MIN,
245                              E820_RESERVED)) {
246                 printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not E820-reserved\n",
247                                 pci_mmcfg_config[0].address);
248                 printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
249                 return;
250         }
251
252         if (pci_mmcfg_arch_init()) {
253                 if (type == 1)
254                         unreachable_devices();
255                 if (known_bridge)
256                         pci_mmcfg_insert_resources();
257                 pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
258         }
259 }