aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/pci/mmconfig-shared.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/pci/mmconfig-shared.c')
-rw-r--r--arch/x86/pci/mmconfig-shared.c356
1 files changed, 171 insertions, 185 deletions
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 602c172d3bd5..39b9ebe8f886 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -15,48 +15,99 @@
15#include <linux/acpi.h> 15#include <linux/acpi.h>
16#include <linux/sfi_acpi.h> 16#include <linux/sfi_acpi.h>
17#include <linux/bitmap.h> 17#include <linux/bitmap.h>
18#include <linux/sort.h> 18#include <linux/dmi.h>
19#include <linux/slab.h>
19#include <asm/e820.h> 20#include <asm/e820.h>
20#include <asm/pci_x86.h> 21#include <asm/pci_x86.h>
21#include <asm/acpi.h> 22#include <asm/acpi.h>
22 23
23#define PREFIX "PCI: " 24#define PREFIX "PCI: "
24 25
25/* aperture is up to 256MB but BIOS may reserve less */
26#define MMCONFIG_APER_MIN (2 * 1024*1024)
27#define MMCONFIG_APER_MAX (256 * 1024*1024)
28
29/* Indicate if the mmcfg resources have been placed into the resource table. */ 26/* Indicate if the mmcfg resources have been placed into the resource table. */
30static int __initdata pci_mmcfg_resources_inserted; 27static int __initdata pci_mmcfg_resources_inserted;
31 28
32static __init int extend_mmcfg(int num) 29LIST_HEAD(pci_mmcfg_list);
30
31static __init void pci_mmconfig_remove(struct pci_mmcfg_region *cfg)
33{ 32{
34 struct acpi_mcfg_allocation *new; 33 if (cfg->res.parent)
35 int new_num = pci_mmcfg_config_num + num; 34 release_resource(&cfg->res);
35 list_del(&cfg->list);
36 kfree(cfg);
37}
36 38
37 new = kzalloc(sizeof(pci_mmcfg_config[0]) * new_num, GFP_KERNEL); 39static __init void free_all_mmcfg(void)
38 if (!new) 40{
39 return -1; 41 struct pci_mmcfg_region *cfg, *tmp;
42
43 pci_mmcfg_arch_free();
44 list_for_each_entry_safe(cfg, tmp, &pci_mmcfg_list, list)
45 pci_mmconfig_remove(cfg);
46}
40 47
41 if (pci_mmcfg_config) { 48static __init void list_add_sorted(struct pci_mmcfg_region *new)
42 memcpy(new, pci_mmcfg_config, 49{
43 sizeof(pci_mmcfg_config[0]) * new_num); 50 struct pci_mmcfg_region *cfg;
44 kfree(pci_mmcfg_config); 51
52 /* keep list sorted by segment and starting bus number */
53 list_for_each_entry(cfg, &pci_mmcfg_list, list) {
54 if (cfg->segment > new->segment ||
55 (cfg->segment == new->segment &&
56 cfg->start_bus >= new->start_bus)) {
57 list_add_tail(&new->list, &cfg->list);
58 return;
59 }
45 } 60 }
46 pci_mmcfg_config = new; 61 list_add_tail(&new->list, &pci_mmcfg_list);
62}
47 63
48 return 0; 64static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
65 int end, u64 addr)
66{
67 struct pci_mmcfg_region *new;
68 int num_buses;
69 struct resource *res;
70
71 if (addr == 0)
72 return NULL;
73
74 new = kzalloc(sizeof(*new), GFP_KERNEL);
75 if (!new)
76 return NULL;
77
78 new->address = addr;
79 new->segment = segment;
80 new->start_bus = start;
81 new->end_bus = end;
82
83 list_add_sorted(new);
84
85 num_buses = end - start + 1;
86 res = &new->res;
87 res->start = addr + PCI_MMCFG_BUS_OFFSET(start);
88 res->end = addr + PCI_MMCFG_BUS_OFFSET(num_buses) - 1;
89 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
90 snprintf(new->name, PCI_MMCFG_RESOURCE_NAME_LEN,
91 "PCI MMCONFIG %04x [bus %02x-%02x]", segment, start, end);
92 res->name = new->name;
93
94 printk(KERN_INFO PREFIX "MMCONFIG for domain %04x [bus %02x-%02x] at "
95 "%pR (base %#lx)\n", segment, start, end, &new->res,
96 (unsigned long) addr);
97
98 return new;
49} 99}
50 100
51static __init void fill_one_mmcfg(u64 addr, int segment, int start, int end) 101struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus)
52{ 102{
53 int i = pci_mmcfg_config_num; 103 struct pci_mmcfg_region *cfg;
54 104
55 pci_mmcfg_config_num++; 105 list_for_each_entry(cfg, &pci_mmcfg_list, list)
56 pci_mmcfg_config[i].address = addr; 106 if (cfg->segment == segment &&
57 pci_mmcfg_config[i].pci_segment = segment; 107 cfg->start_bus <= bus && bus <= cfg->end_bus)
58 pci_mmcfg_config[i].start_bus_number = start; 108 return cfg;
59 pci_mmcfg_config[i].end_bus_number = end; 109
110 return NULL;
60} 111}
61 112
62static const char __init *pci_mmcfg_e7520(void) 113static const char __init *pci_mmcfg_e7520(void)
@@ -68,11 +119,9 @@ static const char __init *pci_mmcfg_e7520(void)
68 if (win == 0x0000 || win == 0xf000) 119 if (win == 0x0000 || win == 0xf000)
69 return NULL; 120 return NULL;
70 121
71 if (extend_mmcfg(1) == -1) 122 if (pci_mmconfig_add(0, 0, 255, win << 16) == NULL)
72 return NULL; 123 return NULL;
73 124
74 fill_one_mmcfg(win << 16, 0, 0, 255);
75
76 return "Intel Corporation E7520 Memory Controller Hub"; 125 return "Intel Corporation E7520 Memory Controller Hub";
77} 126}
78 127
@@ -114,11 +163,9 @@ static const char __init *pci_mmcfg_intel_945(void)
114 if ((pciexbar & mask) >= 0xf0000000U) 163 if ((pciexbar & mask) >= 0xf0000000U)
115 return NULL; 164 return NULL;
116 165
117 if (extend_mmcfg(1) == -1) 166 if (pci_mmconfig_add(0, 0, (len >> 20) - 1, pciexbar & mask) == NULL)
118 return NULL; 167 return NULL;
119 168
120 fill_one_mmcfg(pciexbar & mask, 0, 0, (len >> 20) - 1);
121
122 return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub"; 169 return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
123} 170}
124 171
@@ -127,7 +174,7 @@ static const char __init *pci_mmcfg_amd_fam10h(void)
127 u32 low, high, address; 174 u32 low, high, address;
128 u64 base, msr; 175 u64 base, msr;
129 int i; 176 int i;
130 unsigned segnbits = 0, busnbits; 177 unsigned segnbits = 0, busnbits, end_bus;
131 178
132 if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF)) 179 if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF))
133 return NULL; 180 return NULL;
@@ -161,11 +208,13 @@ static const char __init *pci_mmcfg_amd_fam10h(void)
161 busnbits = 8; 208 busnbits = 8;
162 } 209 }
163 210
164 if (extend_mmcfg(1 << segnbits) == -1) 211 end_bus = (1 << busnbits) - 1;
165 return NULL;
166
167 for (i = 0; i < (1 << segnbits); i++) 212 for (i = 0; i < (1 << segnbits); i++)
168 fill_one_mmcfg(base + (1<<28) * i, i, 0, (1 << busnbits) - 1); 213 if (pci_mmconfig_add(i, 0, end_bus,
214 base + (1<<28) * i) == NULL) {
215 free_all_mmcfg();
216 return NULL;
217 }
169 218
170 return "AMD Family 10h NB"; 219 return "AMD Family 10h NB";
171} 220}
@@ -190,7 +239,7 @@ static const char __init *pci_mmcfg_nvidia_mcp55(void)
190 /* 239 /*
191 * do check if amd fam10h already took over 240 * do check if amd fam10h already took over
192 */ 241 */
193 if (!acpi_disabled || pci_mmcfg_config_num || mcp55_checked) 242 if (!acpi_disabled || !list_empty(&pci_mmcfg_list) || mcp55_checked)
194 return NULL; 243 return NULL;
195 244
196 mcp55_checked = true; 245 mcp55_checked = true;
@@ -213,16 +262,14 @@ static const char __init *pci_mmcfg_nvidia_mcp55(void)
213 if (!(extcfg & extcfg_enable_mask)) 262 if (!(extcfg & extcfg_enable_mask))
214 continue; 263 continue;
215 264
216 if (extend_mmcfg(1) == -1)
217 continue;
218
219 size_index = (extcfg & extcfg_size_mask) >> extcfg_size_shift; 265 size_index = (extcfg & extcfg_size_mask) >> extcfg_size_shift;
220 base = extcfg & extcfg_base_mask[size_index]; 266 base = extcfg & extcfg_base_mask[size_index];
221 /* base could > 4G */ 267 /* base could > 4G */
222 base <<= extcfg_base_lshift; 268 base <<= extcfg_base_lshift;
223 start = (extcfg & extcfg_start_mask) >> extcfg_start_shift; 269 start = (extcfg & extcfg_start_mask) >> extcfg_start_shift;
224 end = start + extcfg_sizebus[size_index] - 1; 270 end = start + extcfg_sizebus[size_index] - 1;
225 fill_one_mmcfg(base, 0, start, end); 271 if (pci_mmconfig_add(0, start, end, base) == NULL)
272 continue;
226 mcp55_mmconf_found++; 273 mcp55_mmconf_found++;
227 } 274 }
228 275
@@ -253,45 +300,22 @@ static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
253 0x0369, pci_mmcfg_nvidia_mcp55 }, 300 0x0369, pci_mmcfg_nvidia_mcp55 },
254}; 301};
255 302
256static int __init cmp_mmcfg(const void *x1, const void *x2)
257{
258 const typeof(pci_mmcfg_config[0]) *m1 = x1;
259 const typeof(pci_mmcfg_config[0]) *m2 = x2;
260 int start1, start2;
261
262 start1 = m1->start_bus_number;
263 start2 = m2->start_bus_number;
264
265 return start1 - start2;
266}
267
268static void __init pci_mmcfg_check_end_bus_number(void) 303static void __init pci_mmcfg_check_end_bus_number(void)
269{ 304{
270 int i; 305 struct pci_mmcfg_region *cfg, *cfgx;
271 typeof(pci_mmcfg_config[0]) *cfg, *cfgx;
272
273 /* sort them at first */
274 sort(pci_mmcfg_config, pci_mmcfg_config_num,
275 sizeof(pci_mmcfg_config[0]), cmp_mmcfg, NULL);
276
277 /* last one*/
278 if (pci_mmcfg_config_num > 0) {
279 i = pci_mmcfg_config_num - 1;
280 cfg = &pci_mmcfg_config[i];
281 if (cfg->end_bus_number < cfg->start_bus_number)
282 cfg->end_bus_number = 255;
283 }
284 306
285 /* don't overlap please */ 307 /* Fixup overlaps */
286 for (i = 0; i < pci_mmcfg_config_num - 1; i++) { 308 list_for_each_entry(cfg, &pci_mmcfg_list, list) {
287 cfg = &pci_mmcfg_config[i]; 309 if (cfg->end_bus < cfg->start_bus)
288 cfgx = &pci_mmcfg_config[i+1]; 310 cfg->end_bus = 255;
289 311
290 if (cfg->end_bus_number < cfg->start_bus_number) 312 /* Don't access the list head ! */
291 cfg->end_bus_number = 255; 313 if (cfg->list.next == &pci_mmcfg_list)
314 break;
292 315
293 if (cfg->end_bus_number >= cfgx->start_bus_number) 316 cfgx = list_entry(cfg->list.next, typeof(*cfg), list);
294 cfg->end_bus_number = cfgx->start_bus_number - 1; 317 if (cfg->end_bus >= cfgx->start_bus)
318 cfg->end_bus = cfgx->start_bus - 1;
295 } 319 }
296} 320}
297 321
@@ -306,8 +330,7 @@ static int __init pci_mmcfg_check_hostbridge(void)
306 if (!raw_pci_ops) 330 if (!raw_pci_ops)
307 return 0; 331 return 0;
308 332
309 pci_mmcfg_config_num = 0; 333 free_all_mmcfg();
310 pci_mmcfg_config = NULL;
311 334
312 for (i = 0; i < ARRAY_SIZE(pci_mmcfg_probes); i++) { 335 for (i = 0; i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
313 bus = pci_mmcfg_probes[i].bus; 336 bus = pci_mmcfg_probes[i].bus;
@@ -322,45 +345,22 @@ static int __init pci_mmcfg_check_hostbridge(void)
322 name = pci_mmcfg_probes[i].probe(); 345 name = pci_mmcfg_probes[i].probe();
323 346
324 if (name) 347 if (name)
325 printk(KERN_INFO "PCI: Found %s with MMCONFIG support.\n", 348 printk(KERN_INFO PREFIX "%s with MMCONFIG support\n",
326 name); 349 name);
327 } 350 }
328 351
329 /* some end_bus_number is crazy, fix it */ 352 /* some end_bus_number is crazy, fix it */
330 pci_mmcfg_check_end_bus_number(); 353 pci_mmcfg_check_end_bus_number();
331 354
332 return pci_mmcfg_config_num != 0; 355 return !list_empty(&pci_mmcfg_list);
333} 356}
334 357
335static void __init pci_mmcfg_insert_resources(void) 358static void __init pci_mmcfg_insert_resources(void)
336{ 359{
337#define PCI_MMCFG_RESOURCE_NAME_LEN 24 360 struct pci_mmcfg_region *cfg;
338 int i;
339 struct resource *res;
340 char *names;
341 unsigned num_buses;
342
343 res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res),
344 pci_mmcfg_config_num, GFP_KERNEL);
345 if (!res) {
346 printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n");
347 return;
348 }
349 361
350 names = (void *)&res[pci_mmcfg_config_num]; 362 list_for_each_entry(cfg, &pci_mmcfg_list, list)
351 for (i = 0; i < pci_mmcfg_config_num; i++, res++) { 363 insert_resource(&iomem_resource, &cfg->res);
352 struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[i];
353 num_buses = cfg->end_bus_number - cfg->start_bus_number + 1;
354 res->name = names;
355 snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN,
356 "PCI MMCONFIG %u [%02x-%02x]", cfg->pci_segment,
357 cfg->start_bus_number, cfg->end_bus_number);
358 res->start = cfg->address + (cfg->start_bus_number << 20);
359 res->end = res->start + (num_buses << 20) - 1;
360 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
361 insert_resource(&iomem_resource, res);
362 names += PCI_MMCFG_RESOURCE_NAME_LEN;
363 }
364 364
365 /* Mark that the resources have been inserted. */ 365 /* Mark that the resources have been inserted. */
366 pci_mmcfg_resources_inserted = 1; 366 pci_mmcfg_resources_inserted = 1;
@@ -437,11 +437,12 @@ static int __init is_acpi_reserved(u64 start, u64 end, unsigned not_used)
437typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type); 437typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type);
438 438
439static int __init is_mmconf_reserved(check_reserved_t is_reserved, 439static int __init is_mmconf_reserved(check_reserved_t is_reserved,
440 u64 addr, u64 size, int i, 440 struct pci_mmcfg_region *cfg, int with_e820)
441 typeof(pci_mmcfg_config[0]) *cfg, int with_e820)
442{ 441{
442 u64 addr = cfg->res.start;
443 u64 size = resource_size(&cfg->res);
443 u64 old_size = size; 444 u64 old_size = size;
444 int valid = 0; 445 int valid = 0, num_buses;
445 446
446 while (!is_reserved(addr, addr + size, E820_RESERVED)) { 447 while (!is_reserved(addr, addr + size, E820_RESERVED)) {
447 size >>= 1; 448 size >>= 1;
@@ -450,19 +451,25 @@ static int __init is_mmconf_reserved(check_reserved_t is_reserved,
450 } 451 }
451 452
452 if (size >= (16UL<<20) || size == old_size) { 453 if (size >= (16UL<<20) || size == old_size) {
453 printk(KERN_NOTICE 454 printk(KERN_INFO PREFIX "MMCONFIG at %pR reserved in %s\n",
454 "PCI: MCFG area at %Lx reserved in %s\n", 455 &cfg->res,
455 addr, with_e820?"E820":"ACPI motherboard resources"); 456 with_e820 ? "E820" : "ACPI motherboard resources");
456 valid = 1; 457 valid = 1;
457 458
458 if (old_size != size) { 459 if (old_size != size) {
459 /* update end_bus_number */ 460 /* update end_bus */
460 cfg->end_bus_number = cfg->start_bus_number + ((size>>20) - 1); 461 cfg->end_bus = cfg->start_bus + ((size>>20) - 1);
461 printk(KERN_NOTICE "PCI: updated MCFG configuration %d: base %lx " 462 num_buses = cfg->end_bus - cfg->start_bus + 1;
462 "segment %hu buses %u - %u\n", 463 cfg->res.end = cfg->res.start +
463 i, (unsigned long)cfg->address, cfg->pci_segment, 464 PCI_MMCFG_BUS_OFFSET(num_buses) - 1;
464 (unsigned int)cfg->start_bus_number, 465 snprintf(cfg->name, PCI_MMCFG_RESOURCE_NAME_LEN,
465 (unsigned int)cfg->end_bus_number); 466 "PCI MMCONFIG %04x [bus %02x-%02x]",
467 cfg->segment, cfg->start_bus, cfg->end_bus);
468 printk(KERN_INFO PREFIX
469 "MMCONFIG for %04x [bus%02x-%02x] "
470 "at %pR (base %#lx) (size reduced!)\n",
471 cfg->segment, cfg->start_bus, cfg->end_bus,
472 &cfg->res, (unsigned long) cfg->address);
466 } 473 }
467 } 474 }
468 475
@@ -471,45 +478,26 @@ static int __init is_mmconf_reserved(check_reserved_t is_reserved,
471 478
472static void __init pci_mmcfg_reject_broken(int early) 479static void __init pci_mmcfg_reject_broken(int early)
473{ 480{
474 typeof(pci_mmcfg_config[0]) *cfg; 481 struct pci_mmcfg_region *cfg;
475 int i;
476 482
477 if ((pci_mmcfg_config_num == 0) || 483 list_for_each_entry(cfg, &pci_mmcfg_list, list) {
478 (pci_mmcfg_config == NULL) ||
479 (pci_mmcfg_config[0].address == 0))
480 return;
481
482 for (i = 0; i < pci_mmcfg_config_num; i++) {
483 int valid = 0; 484 int valid = 0;
484 u64 addr, size;
485
486 cfg = &pci_mmcfg_config[i];
487 addr = cfg->start_bus_number;
488 addr <<= 20;
489 addr += cfg->address;
490 size = cfg->end_bus_number + 1 - cfg->start_bus_number;
491 size <<= 20;
492 printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lx "
493 "segment %hu buses %u - %u\n",
494 i, (unsigned long)cfg->address, cfg->pci_segment,
495 (unsigned int)cfg->start_bus_number,
496 (unsigned int)cfg->end_bus_number);
497 485
498 if (!early && !acpi_disabled) 486 if (!early && !acpi_disabled)
499 valid = is_mmconf_reserved(is_acpi_reserved, addr, size, i, cfg, 0); 487 valid = is_mmconf_reserved(is_acpi_reserved, cfg, 0);
500 488
501 if (valid) 489 if (valid)
502 continue; 490 continue;
503 491
504 if (!early) 492 if (!early)
505 printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not" 493 printk(KERN_ERR FW_BUG PREFIX
506 " reserved in ACPI motherboard resources\n", 494 "MMCONFIG at %pR not reserved in "
507 cfg->address); 495 "ACPI motherboard resources\n", &cfg->res);
508 496
509 /* Don't try to do this check unless configuration 497 /* Don't try to do this check unless configuration
510 type 1 is available. how about type 2 ?*/ 498 type 1 is available. how about type 2 ?*/
511 if (raw_pci_ops) 499 if (raw_pci_ops)
512 valid = is_mmconf_reserved(e820_all_mapped, addr, size, i, cfg, 1); 500 valid = is_mmconf_reserved(e820_all_mapped, cfg, 1);
513 501
514 if (!valid) 502 if (!valid)
515 goto reject; 503 goto reject;
@@ -518,34 +506,41 @@ static void __init pci_mmcfg_reject_broken(int early)
518 return; 506 return;
519 507
520reject: 508reject:
521 printk(KERN_INFO "PCI: Not using MMCONFIG.\n"); 509 printk(KERN_INFO PREFIX "not using MMCONFIG\n");
522 pci_mmcfg_arch_free(); 510 free_all_mmcfg();
523 kfree(pci_mmcfg_config);
524 pci_mmcfg_config = NULL;
525 pci_mmcfg_config_num = 0;
526} 511}
527 512
528static int __initdata known_bridge; 513static int __initdata known_bridge;
529 514
530static int acpi_mcfg_64bit_base_addr __initdata = FALSE; 515static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg,
516 struct acpi_mcfg_allocation *cfg)
517{
518 int year;
531 519
532/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */ 520 if (cfg->address < 0xFFFFFFFF)
533struct acpi_mcfg_allocation *pci_mmcfg_config; 521 return 0;
534int pci_mmcfg_config_num;
535 522
536static int __init acpi_mcfg_oem_check(struct acpi_table_mcfg *mcfg)
537{
538 if (!strcmp(mcfg->header.oem_id, "SGI")) 523 if (!strcmp(mcfg->header.oem_id, "SGI"))
539 acpi_mcfg_64bit_base_addr = TRUE; 524 return 0;
540 525
541 return 0; 526 if (mcfg->header.revision >= 1) {
527 if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) &&
528 year >= 2010)
529 return 0;
530 }
531
532 printk(KERN_ERR PREFIX "MCFG region for %04x [bus %02x-%02x] at %#llx "
533 "is above 4GB, ignored\n", cfg->pci_segment,
534 cfg->start_bus_number, cfg->end_bus_number, cfg->address);
535 return -EINVAL;
542} 536}
543 537
544static int __init pci_parse_mcfg(struct acpi_table_header *header) 538static int __init pci_parse_mcfg(struct acpi_table_header *header)
545{ 539{
546 struct acpi_table_mcfg *mcfg; 540 struct acpi_table_mcfg *mcfg;
541 struct acpi_mcfg_allocation *cfg_table, *cfg;
547 unsigned long i; 542 unsigned long i;
548 int config_size; 543 int entries;
549 544
550 if (!header) 545 if (!header)
551 return -EINVAL; 546 return -EINVAL;
@@ -553,38 +548,33 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header)
553 mcfg = (struct acpi_table_mcfg *)header; 548 mcfg = (struct acpi_table_mcfg *)header;
554 549
555 /* how many config structures do we have */ 550 /* how many config structures do we have */
556 pci_mmcfg_config_num = 0; 551 free_all_mmcfg();
552 entries = 0;
557 i = header->length - sizeof(struct acpi_table_mcfg); 553 i = header->length - sizeof(struct acpi_table_mcfg);
558 while (i >= sizeof(struct acpi_mcfg_allocation)) { 554 while (i >= sizeof(struct acpi_mcfg_allocation)) {
559 ++pci_mmcfg_config_num; 555 entries++;
560 i -= sizeof(struct acpi_mcfg_allocation); 556 i -= sizeof(struct acpi_mcfg_allocation);
561 }; 557 };
562 if (pci_mmcfg_config_num == 0) { 558 if (entries == 0) {
563 printk(KERN_ERR PREFIX "MMCONFIG has no entries\n"); 559 printk(KERN_ERR PREFIX "MMCONFIG has no entries\n");
564 return -ENODEV; 560 return -ENODEV;
565 } 561 }
566 562
567 config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config); 563 cfg_table = (struct acpi_mcfg_allocation *) &mcfg[1];
568 pci_mmcfg_config = kmalloc(config_size, GFP_KERNEL); 564 for (i = 0; i < entries; i++) {
569 if (!pci_mmcfg_config) { 565 cfg = &cfg_table[i];
570 printk(KERN_WARNING PREFIX 566 if (acpi_mcfg_check_entry(mcfg, cfg)) {
571 "No memory for MCFG config tables\n"); 567 free_all_mmcfg();
572 return -ENOMEM;
573 }
574
575 memcpy(pci_mmcfg_config, &mcfg[1], config_size);
576
577 acpi_mcfg_oem_check(mcfg);
578
579 for (i = 0; i < pci_mmcfg_config_num; ++i) {
580 if ((pci_mmcfg_config[i].address > 0xFFFFFFFF) &&
581 !acpi_mcfg_64bit_base_addr) {
582 printk(KERN_ERR PREFIX
583 "MMCONFIG not in low 4GB of memory\n");
584 kfree(pci_mmcfg_config);
585 pci_mmcfg_config_num = 0;
586 return -ENODEV; 568 return -ENODEV;
587 } 569 }
570
571 if (pci_mmconfig_add(cfg->pci_segment, cfg->start_bus_number,
572 cfg->end_bus_number, cfg->address) == NULL) {
573 printk(KERN_WARNING PREFIX
574 "no memory for MCFG entries\n");
575 free_all_mmcfg();
576 return -ENOMEM;
577 }
588 } 578 }
589 579
590 return 0; 580 return 0;
@@ -614,9 +604,7 @@ static void __init __pci_mmcfg_init(int early)
614 604
615 pci_mmcfg_reject_broken(early); 605 pci_mmcfg_reject_broken(early);
616 606
617 if ((pci_mmcfg_config_num == 0) || 607 if (list_empty(&pci_mmcfg_list))
618 (pci_mmcfg_config == NULL) ||
619 (pci_mmcfg_config[0].address == 0))
620 return; 608 return;
621 609
622 if (pci_mmcfg_arch_init()) 610 if (pci_mmcfg_arch_init())
@@ -648,9 +636,7 @@ static int __init pci_mmcfg_late_insert_resources(void)
648 */ 636 */
649 if ((pci_mmcfg_resources_inserted == 1) || 637 if ((pci_mmcfg_resources_inserted == 1) ||
650 (pci_probe & PCI_PROBE_MMCONF) == 0 || 638 (pci_probe & PCI_PROBE_MMCONF) == 0 ||
651 (pci_mmcfg_config_num == 0) || 639 list_empty(&pci_mmcfg_list))
652 (pci_mmcfg_config == NULL) ||
653 (pci_mmcfg_config[0].address == 0))
654 return 1; 640 return 1;
655 641
656 /* 642 /*