mmconfig-shared.c 18.6 KB
Newer Older
1 2 3 4 5
/*
 * mmconfig-shared.c - Low-level direct PCI config space access via
 *                     MMCONFIG - common code between i386 and x86-64.
 *
 * This code does:
6
 * - known chipset handling
7 8 9 10 11 12 13 14 15
 * - ACPI decoding and validation
 *
 * Per-architecture code takes care of the mappings and accesses
 * themselves.
 */

#include <linux/pci.h>
#include <linux/init.h>
#include <linux/acpi.h>
F
Feng Tang 已提交
16
#include <linux/sfi_acpi.h>
17
#include <linux/bitmap.h>
B
Bjorn Helgaas 已提交
18
#include <linux/dmi.h>
19
#include <linux/slab.h>
20 21
#include <linux/mutex.h>
#include <linux/rculist.h>
22
#include <asm/e820.h>
23
#include <asm/pci_x86.h>
F
Feng Tang 已提交
24
#include <asm/acpi.h>
25

26
#define PREFIX "PCI: "
27

28
/* Indicate if the mmcfg resources have been placed into the resource table. */
29
static bool pci_mmcfg_running_state;
30
static bool pci_mmcfg_arch_init_failed;
31
static DEFINE_MUTEX(pci_mmcfg_lock);
32

33 34
LIST_HEAD(pci_mmcfg_list);

35 36 37 38 39 40 41 42
static __init void pci_mmconfig_remove(struct pci_mmcfg_region *cfg)
{
	if (cfg->res.parent)
		release_resource(&cfg->res);
	list_del(&cfg->list);
	kfree(cfg);
}

43 44
static __init void free_all_mmcfg(void)
{
45
	struct pci_mmcfg_region *cfg, *tmp;
46

47
	pci_mmcfg_arch_free();
48 49
	list_for_each_entry_safe(cfg, tmp, &pci_mmcfg_list, list)
		pci_mmconfig_remove(cfg);
50 51
}

52
static __devinit void list_add_sorted(struct pci_mmcfg_region *new)
53 54 55 56
{
	struct pci_mmcfg_region *cfg;

	/* keep list sorted by segment and starting bus number */
57
	list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list) {
58 59 60
		if (cfg->segment > new->segment ||
		    (cfg->segment == new->segment &&
		     cfg->start_bus >= new->start_bus)) {
61
			list_add_tail_rcu(&new->list, &cfg->list);
62 63 64
			return;
		}
	}
65
	list_add_tail_rcu(&new->list, &pci_mmcfg_list);
66 67
}

68 69 70
static __devinit struct pci_mmcfg_region *pci_mmconfig_alloc(int segment,
							     int start,
							     int end, u64 addr)
71
{
72
	struct pci_mmcfg_region *new;
73
	struct resource *res;
74

75 76 77
	if (addr == 0)
		return NULL;

78
	new = kzalloc(sizeof(*new), GFP_KERNEL);
79
	if (!new)
80
		return NULL;
81

82 83 84 85
	new->address = addr;
	new->segment = segment;
	new->start_bus = start;
	new->end_bus = end;
86

87 88
	res = &new->res;
	res->start = addr + PCI_MMCFG_BUS_OFFSET(start);
89
	res->end = addr + PCI_MMCFG_BUS_OFFSET(end + 1) - 1;
90 91 92 93 94
	res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
	snprintf(new->name, PCI_MMCFG_RESOURCE_NAME_LEN,
		 "PCI MMCONFIG %04x [bus %02x-%02x]", segment, start, end);
	res->name = new->name;

95
	return new;
96 97
}

98 99 100 101 102 103
static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
							int end, u64 addr)
{
	struct pci_mmcfg_region *new;

	new = pci_mmconfig_alloc(segment, start, end, addr);
104 105
	if (new) {
		mutex_lock(&pci_mmcfg_lock);
106
		list_add_sorted(new);
107
		mutex_unlock(&pci_mmcfg_lock);
108 109 110 111 112

		printk(KERN_INFO PREFIX
		       "MMCONFIG for domain %04x [bus %02x-%02x] at %pR "
		       "(base %#lx)\n",
		       segment, start, end, &new->res, (unsigned long)addr);
113
	}
114 115 116 117

	return new;
}

118 119 120 121
struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus)
{
	struct pci_mmcfg_region *cfg;

122
	list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list)
123 124 125 126 127 128 129
		if (cfg->segment == segment &&
		    cfg->start_bus <= bus && bus <= cfg->end_bus)
			return cfg;

	return NULL;
}

130
static const char __init *pci_mmcfg_e7520(void)
131 132
{
	u32 win;
133
	raw_pci_ops->read(0, 0, PCI_DEVFN(0, 0), 0xce, 2, &win);
134

135
	win = win & 0xf000;
136 137 138
	if (win == 0x0000 || win == 0xf000)
		return NULL;

139
	if (pci_mmconfig_add(0, 0, 255, win << 16) == NULL)
140 141
		return NULL;

142 143 144
	return "Intel Corporation E7520 Memory Controller Hub";
}

145
static const char __init *pci_mmcfg_intel_945(void)
146 147 148
{
	u32 pciexbar, mask = 0, len = 0;

149
	raw_pci_ops->read(0, 0, PCI_DEVFN(0, 0), 0x48, 4, &pciexbar);
150 151 152

	/* Enable bit */
	if (!(pciexbar & 1))
153
		return NULL;
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169

	/* Size bits */
	switch ((pciexbar >> 1) & 3) {
	case 0:
		mask = 0xf0000000U;
		len  = 0x10000000U;
		break;
	case 1:
		mask = 0xf8000000U;
		len  = 0x08000000U;
		break;
	case 2:
		mask = 0xfc000000U;
		len  = 0x04000000U;
		break;
	default:
170
		return NULL;
171 172 173 174 175 176
	}

	/* Errata #2, things break when not aligned on a 256Mb boundary */
	/* Can only happen in 64M/128M mode */

	if ((pciexbar & mask) & 0x0fffffffU)
177
		return NULL;
178

179 180
	/* Don't hit the APIC registers and their friends */
	if ((pciexbar & mask) >= 0xf0000000U)
181 182
		return NULL;

183
	if (pci_mmconfig_add(0, 0, (len >> 20) - 1, pciexbar & mask) == NULL)
184 185
		return NULL;

186 187 188
	return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
}

189 190 191 192 193
static const char __init *pci_mmcfg_amd_fam10h(void)
{
	u32 low, high, address;
	u64 base, msr;
	int i;
194
	unsigned segnbits = 0, busnbits, end_bus;
195

196 197 198
	if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF))
		return NULL;

199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
	address = MSR_FAM10H_MMIO_CONF_BASE;
	if (rdmsr_safe(address, &low, &high))
		return NULL;

	msr = high;
	msr <<= 32;
	msr |= low;

	/* mmconfig is not enable */
	if (!(msr & FAM10H_MMIO_CONF_ENABLE))
		return NULL;

	base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT);

	busnbits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
			 FAM10H_MMIO_CONF_BUSRANGE_MASK;

	/*
	 * only handle bus 0 ?
	 * need to skip it
	 */
	if (!busnbits)
		return NULL;

	if (busnbits > 8) {
		segnbits = busnbits - 8;
		busnbits = 8;
	}

228
	end_bus = (1 << busnbits) - 1;
229
	for (i = 0; i < (1 << segnbits); i++)
230 231 232 233 234
		if (pci_mmconfig_add(i, 0, end_bus,
				     base + (1<<28) * i) == NULL) {
			free_all_mmcfg();
			return NULL;
		}
235 236 237 238

	return "AMD Family 10h NB";
}

239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
static bool __initdata mcp55_checked;
static const char __init *pci_mmcfg_nvidia_mcp55(void)
{
	int bus;
	int mcp55_mmconf_found = 0;

	static const u32 extcfg_regnum		= 0x90;
	static const u32 extcfg_regsize		= 4;
	static const u32 extcfg_enable_mask	= 1<<31;
	static const u32 extcfg_start_mask	= 0xff<<16;
	static const int extcfg_start_shift	= 16;
	static const u32 extcfg_size_mask	= 0x3<<28;
	static const int extcfg_size_shift	= 28;
	static const int extcfg_sizebus[]	= {0x100, 0x80, 0x40, 0x20};
	static const u32 extcfg_base_mask[]	= {0x7ff8, 0x7ffc, 0x7ffe, 0x7fff};
	static const int extcfg_base_lshift	= 25;

	/*
	 * do check if amd fam10h already took over
	 */
259
	if (!acpi_disabled || !list_empty(&pci_mmcfg_list) || mcp55_checked)
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
		return NULL;

	mcp55_checked = true;
	for (bus = 0; bus < 256; bus++) {
		u64 base;
		u32 l, extcfg;
		u16 vendor, device;
		int start, size_index, end;

		raw_pci_ops->read(0, bus, PCI_DEVFN(0, 0), 0, 4, &l);
		vendor = l & 0xffff;
		device = (l >> 16) & 0xffff;

		if (PCI_VENDOR_ID_NVIDIA != vendor || 0x0369 != device)
			continue;

		raw_pci_ops->read(0, bus, PCI_DEVFN(0, 0), extcfg_regnum,
				  extcfg_regsize, &extcfg);

		if (!(extcfg & extcfg_enable_mask))
			continue;

		size_index = (extcfg & extcfg_size_mask) >> extcfg_size_shift;
		base = extcfg & extcfg_base_mask[size_index];
		/* base could > 4G */
		base <<= extcfg_base_lshift;
		start = (extcfg & extcfg_start_mask) >> extcfg_start_shift;
		end = start + extcfg_sizebus[size_index] - 1;
288 289
		if (pci_mmconfig_add(0, start, end, base) == NULL)
			continue;
290 291 292 293 294 295 296 297 298
		mcp55_mmconf_found++;
	}

	if (!mcp55_mmconf_found)
		return NULL;

	return "nVidia MCP55";
}

299
struct pci_mmcfg_hostbridge_probe {
300 301
	u32 bus;
	u32 devfn;
302 303 304 305 306
	u32 vendor;
	u32 device;
	const char *(*probe)(void);
};

307
static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
308 309 310 311 312 313 314 315
	{ 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL,
	  PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
	{ 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL,
	  PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
	{ 0, PCI_DEVFN(0x18, 0), PCI_VENDOR_ID_AMD,
	  0x1200, pci_mmcfg_amd_fam10h },
	{ 0xff, PCI_DEVFN(0, 0), PCI_VENDOR_ID_AMD,
	  0x1200, pci_mmcfg_amd_fam10h },
316 317
	{ 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_NVIDIA,
	  0x0369, pci_mmcfg_nvidia_mcp55 },
318 319
};

320 321
static void __init pci_mmcfg_check_end_bus_number(void)
{
322
	struct pci_mmcfg_region *cfg, *cfgx;
323

324
	/* Fixup overlaps */
325
	list_for_each_entry(cfg, &pci_mmcfg_list, list) {
326 327
		if (cfg->end_bus < cfg->start_bus)
			cfg->end_bus = 255;
328

329 330 331 332
		/* Don't access the list head ! */
		if (cfg->list.next == &pci_mmcfg_list)
			break;

333
		cfgx = list_entry(cfg->list.next, typeof(*cfg), list);
334
		if (cfg->end_bus >= cfgx->start_bus)
335
			cfg->end_bus = cfgx->start_bus - 1;
336 337 338
	}
}

339 340 341
static int __init pci_mmcfg_check_hostbridge(void)
{
	u32 l;
342
	u32 bus, devfn;
343 344 345 346
	u16 vendor, device;
	int i;
	const char *name;

347 348 349
	if (!raw_pci_ops)
		return 0;

350
	free_all_mmcfg();
351

352
	for (i = 0; i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
353 354
		bus =  pci_mmcfg_probes[i].bus;
		devfn = pci_mmcfg_probes[i].devfn;
355
		raw_pci_ops->read(0, bus, devfn, 0, 4, &l);
356 357 358
		vendor = l & 0xffff;
		device = (l >> 16) & 0xffff;

359
		name = NULL;
360 361
		if (pci_mmcfg_probes[i].vendor == vendor &&
		    pci_mmcfg_probes[i].device == device)
362 363
			name = pci_mmcfg_probes[i].probe();

364
		if (name)
365
			printk(KERN_INFO PREFIX "%s with MMCONFIG support\n",
366
			       name);
367 368
	}

369 370 371
	/* some end_bus_number is crazy, fix it */
	pci_mmcfg_check_end_bus_number();

372
	return !list_empty(&pci_mmcfg_list);
373 374
}

375 376
static acpi_status __devinit check_mcfg_resource(struct acpi_resource *res,
						 void *data)
377 378 379 380 381 382 383 384 385 386 387
{
	struct resource *mcfg_res = data;
	struct acpi_resource_address64 address;
	acpi_status status;

	if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
		struct acpi_resource_fixed_memory32 *fixmem32 =
			&res->data.fixed_memory32;
		if (!fixmem32)
			return AE_OK;
		if ((mcfg_res->start >= fixmem32->address) &&
388
		    (mcfg_res->end < (fixmem32->address +
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
				      fixmem32->address_length))) {
			mcfg_res->flags = 1;
			return AE_CTRL_TERMINATE;
		}
	}
	if ((res->type != ACPI_RESOURCE_TYPE_ADDRESS32) &&
	    (res->type != ACPI_RESOURCE_TYPE_ADDRESS64))
		return AE_OK;

	status = acpi_resource_to_address64(res, &address);
	if (ACPI_FAILURE(status) ||
	   (address.address_length <= 0) ||
	   (address.resource_type != ACPI_MEMORY_RANGE))
		return AE_OK;

	if ((mcfg_res->start >= address.minimum) &&
405
	    (mcfg_res->end < (address.minimum + address.address_length))) {
406 407 408 409 410 411
		mcfg_res->flags = 1;
		return AE_CTRL_TERMINATE;
	}
	return AE_OK;
}

412 413
static acpi_status __devinit find_mboard_resource(acpi_handle handle, u32 lvl,
						  void *context, void **rv)
414 415 416 417 418 419 420 421 422 423 424 425
{
	struct resource *mcfg_res = context;

	acpi_walk_resources(handle, METHOD_NAME__CRS,
			    check_mcfg_resource, context);

	if (mcfg_res->flags)
		return AE_CTRL_TERMINATE;

	return AE_OK;
}

426
static int __devinit is_acpi_reserved(u64 start, u64 end, unsigned not_used)
427 428 429 430
{
	struct resource mcfg_res;

	mcfg_res.start = start;
431
	mcfg_res.end = end - 1;
432 433 434 435 436 437 438 439 440 441 442
	mcfg_res.flags = 0;

	acpi_get_devices("PNP0C01", find_mboard_resource, &mcfg_res, NULL);

	if (!mcfg_res.flags)
		acpi_get_devices("PNP0C02", find_mboard_resource, &mcfg_res,
				 NULL);

	return mcfg_res.flags;
}

443 444
typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type);

445 446 447
static int __ref is_mmconf_reserved(check_reserved_t is_reserved,
				    struct pci_mmcfg_region *cfg,
				    struct device *dev, int with_e820)
448
{
449 450
	u64 addr = cfg->res.start;
	u64 size = resource_size(&cfg->res);
451
	u64 old_size = size;
452 453
	int num_buses;
	char *method = with_e820 ? "E820" : "ACPI motherboard resources";
454

455
	while (!is_reserved(addr, addr + size, E820_RESERVED)) {
456 457 458 459 460
		size >>= 1;
		if (size < (16UL<<20))
			break;
	}

461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
	if (size < (16UL<<20) && size != old_size)
		return 0;

	if (dev)
		dev_info(dev, "MMCONFIG at %pR reserved in %s\n",
			 &cfg->res, method);
	else
		printk(KERN_INFO PREFIX
		       "MMCONFIG at %pR reserved in %s\n",
		       &cfg->res, method);

	if (old_size != size) {
		/* update end_bus */
		cfg->end_bus = cfg->start_bus + ((size>>20) - 1);
		num_buses = cfg->end_bus - cfg->start_bus + 1;
		cfg->res.end = cfg->res.start +
		    PCI_MMCFG_BUS_OFFSET(num_buses) - 1;
		snprintf(cfg->name, PCI_MMCFG_RESOURCE_NAME_LEN,
			 "PCI MMCONFIG %04x [bus %02x-%02x]",
			 cfg->segment, cfg->start_bus, cfg->end_bus);

		if (dev)
			dev_info(dev,
				"MMCONFIG "
				"at %pR (base %#lx) (size reduced!)\n",
				&cfg->res, (unsigned long) cfg->address);
		else
488
			printk(KERN_INFO PREFIX
489 490 491 492
				"MMCONFIG for %04x [bus%02x-%02x] "
				"at %pR (base %#lx) (size reduced!)\n",
				cfg->segment, cfg->start_bus, cfg->end_bus,
				&cfg->res, (unsigned long) cfg->address);
493 494
	}

495
	return 1;
496 497
}

498 499
static int __ref pci_mmcfg_check_reserved(struct device *dev,
		  struct pci_mmcfg_region *cfg, int early)
500 501
{
	if (!early && !acpi_disabled) {
502
		if (is_mmconf_reserved(is_acpi_reserved, cfg, dev, 0))
503
			return 1;
504 505 506 507 508 509

		if (dev)
			dev_info(dev, FW_INFO
				 "MMCONFIG at %pR not reserved in "
				 "ACPI motherboard resources\n",
				 &cfg->res);
510
		else
511
			printk(KERN_INFO FW_INFO PREFIX
512 513 514 515 516
			       "MMCONFIG at %pR not reserved in "
			       "ACPI motherboard resources\n",
			       &cfg->res);
	}

517 518 519 520 521 522 523 524 525
	/*
	 * e820_all_mapped() is marked as __init.
	 * All entries from ACPI MCFG table have been checked at boot time.
	 * For MCFG information constructed from hotpluggable host bridge's
	 * _CBA method, just assume it's reserved.
	 */
	if (pci_mmcfg_running_state)
		return 1;

526 527 528
	/* Don't try to do this check unless configuration
	   type 1 is available. how about type 2 ?*/
	if (raw_pci_ops)
529
		return is_mmconf_reserved(e820_all_mapped, cfg, dev, 1);
530 531 532 533

	return 0;
}

534
static void __init pci_mmcfg_reject_broken(int early)
535
{
536
	struct pci_mmcfg_region *cfg;
537

538
	list_for_each_entry(cfg, &pci_mmcfg_list, list) {
539
		if (pci_mmcfg_check_reserved(NULL, cfg, early) == 0) {
540 541 542
			printk(KERN_INFO PREFIX "not using MMCONFIG\n");
			free_all_mmcfg();
			return;
543
		}
544 545 546
	}
}

Y
Yinghai Lu 已提交
547
static int __initdata known_bridge;
548

B
Bjorn Helgaas 已提交
549 550
static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg,
					struct acpi_mcfg_allocation *cfg)
551
{
B
Bjorn Helgaas 已提交
552 553 554 555 556
	int year;

	if (cfg->address < 0xFFFFFFFF)
		return 0;

557 558
	if (!strcmp(mcfg->header.oem_id, "SGI") ||
			!strcmp(mcfg->header.oem_id, "SGI2"))
B
Bjorn Helgaas 已提交
559
		return 0;
560

B
Bjorn Helgaas 已提交
561 562 563 564 565 566
	if (mcfg->header.revision >= 1) {
		if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) &&
		    year >= 2010)
			return 0;
	}

567
	printk(KERN_ERR PREFIX "MCFG region for %04x [bus %02x-%02x] at %#llx "
B
Bjorn Helgaas 已提交
568 569 570
	       "is above 4GB, ignored\n", cfg->pci_segment,
	       cfg->start_bus_number, cfg->end_bus_number, cfg->address);
	return -EINVAL;
571 572 573 574 575
}

static int __init pci_parse_mcfg(struct acpi_table_header *header)
{
	struct acpi_table_mcfg *mcfg;
576
	struct acpi_mcfg_allocation *cfg_table, *cfg;
577
	unsigned long i;
578
	int entries;
579 580 581 582 583 584 585

	if (!header)
		return -EINVAL;

	mcfg = (struct acpi_table_mcfg *)header;

	/* how many config structures do we have */
586
	free_all_mmcfg();
587
	entries = 0;
588 589
	i = header->length - sizeof(struct acpi_table_mcfg);
	while (i >= sizeof(struct acpi_mcfg_allocation)) {
590
		entries++;
591 592
		i -= sizeof(struct acpi_mcfg_allocation);
	};
593
	if (entries == 0) {
594 595 596 597
		printk(KERN_ERR PREFIX "MMCONFIG has no entries\n");
		return -ENODEV;
	}

598
	cfg_table = (struct acpi_mcfg_allocation *) &mcfg[1];
599
	for (i = 0; i < entries; i++) {
600 601
		cfg = &cfg_table[i];
		if (acpi_mcfg_check_entry(mcfg, cfg)) {
602
			free_all_mmcfg();
603 604
			return -ENODEV;
		}
605 606 607 608 609 610 611 612

		if (pci_mmconfig_add(cfg->pci_segment, cfg->start_bus_number,
				   cfg->end_bus_number, cfg->address) == NULL) {
			printk(KERN_WARNING PREFIX
			       "no memory for MCFG entries\n");
			free_all_mmcfg();
			return -ENOMEM;
		}
613 614 615 616 617
	}

	return 0;
}

618
static void __init __pci_mmcfg_init(int early)
619
{
620
	/* MMCONFIG disabled */
621 622 623
	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
		return;

624
	/* MMCONFIG already enabled */
Y
Yinghai Lu 已提交
625
	if (!early && !(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
626
		return;
627

Y
Yinghai Lu 已提交
628 629 630
	/* for late to exit */
	if (known_bridge)
		return;
631

632
	if (early) {
Y
Yinghai Lu 已提交
633 634 635 636
		if (pci_mmcfg_check_hostbridge())
			known_bridge = 1;
	}

637
	if (!known_bridge)
F
Feng Tang 已提交
638
		acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
639 640

	pci_mmcfg_reject_broken(early);
641

642
	if (list_empty(&pci_mmcfg_list))
643 644
		return;

645 646 647 648 649 650 651 652 653 654
	if (pcibios_last_bus < 0) {
		const struct pci_mmcfg_region *cfg;

		list_for_each_entry(cfg, &pci_mmcfg_list, list) {
			if (cfg->segment)
				break;
			pcibios_last_bus = cfg->end_bus;
		}
	}

655
	if (pci_mmcfg_arch_init())
656
		pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
657
	else {
658
		free_all_mmcfg();
659
		pci_mmcfg_arch_init_failed = true;
660 661
	}
}
662

663
void __init pci_mmcfg_early_init(void)
Y
Yinghai Lu 已提交
664
{
665
	__pci_mmcfg_init(1);
Y
Yinghai Lu 已提交
666 667 668 669
}

void __init pci_mmcfg_late_init(void)
{
670
	__pci_mmcfg_init(0);
Y
Yinghai Lu 已提交
671 672
}

673 674
static int __init pci_mmcfg_late_insert_resources(void)
{
675 676
	struct pci_mmcfg_region *cfg;

677 678
	pci_mmcfg_running_state = true;

679 680
	/* If we are not using MMCONFIG, don't insert the resources. */
	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
681 682 683 684 685 686 687
		return 1;

	/*
	 * Attempt to insert the mmcfg resources but not with the busy flag
	 * marked so it won't cause request errors when __request_region is
	 * called.
	 */
688 689 690
	list_for_each_entry(cfg, &pci_mmcfg_list, list)
		if (!cfg->res.parent)
			insert_resource(&iomem_resource, &cfg->res);
691 692 693 694 695 696 697 698 699 700

	return 0;
}

/*
 * Perform MMCONFIG resource insertion after PCI initialization to allow for
 * misprogrammed MCFG tables that state larger sizes but actually conflict
 * with other system resources.
 */
late_initcall(pci_mmcfg_late_insert_resources);
701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798

/* Add MMCFG information for host bridges */
int __devinit pci_mmconfig_insert(struct device *dev,
				  u16 seg, u8 start, u8 end,
				  phys_addr_t addr)
{
	int rc;
	struct resource *tmp = NULL;
	struct pci_mmcfg_region *cfg;

	if (!(pci_probe & PCI_PROBE_MMCONF) || pci_mmcfg_arch_init_failed)
		return -ENODEV;

	if (start > end)
		return -EINVAL;

	mutex_lock(&pci_mmcfg_lock);
	cfg = pci_mmconfig_lookup(seg, start);
	if (cfg) {
		if (cfg->end_bus < end)
			dev_info(dev, FW_INFO
				 "MMCONFIG for "
				 "domain %04x [bus %02x-%02x] "
				 "only partially covers this bridge\n",
				  cfg->segment, cfg->start_bus, cfg->end_bus);
		mutex_unlock(&pci_mmcfg_lock);
		return -EEXIST;
	}

	if (!addr) {
		mutex_unlock(&pci_mmcfg_lock);
		return -EINVAL;
	}

	rc = -EBUSY;
	cfg = pci_mmconfig_alloc(seg, start, end, addr);
	if (cfg == NULL) {
		dev_warn(dev, "fail to add MMCONFIG (out of memory)\n");
		rc = -ENOMEM;
	} else if (!pci_mmcfg_check_reserved(dev, cfg, 0)) {
		dev_warn(dev, FW_BUG "MMCONFIG %pR isn't reserved\n",
			 &cfg->res);
	} else {
		/* Insert resource if it's not in boot stage */
		if (pci_mmcfg_running_state)
			tmp = insert_resource_conflict(&iomem_resource,
						       &cfg->res);

		if (tmp) {
			dev_warn(dev,
				 "MMCONFIG %pR conflicts with "
				 "%s %pR\n",
				 &cfg->res, tmp->name, tmp);
		} else if (pci_mmcfg_arch_map(cfg)) {
			dev_warn(dev, "fail to map MMCONFIG %pR.\n",
				 &cfg->res);
		} else {
			list_add_sorted(cfg);
			dev_info(dev, "MMCONFIG at %pR (base %#lx)\n",
				 &cfg->res, (unsigned long)addr);
			cfg = NULL;
			rc = 0;
		}
	}

	if (cfg) {
		if (cfg->res.parent)
			release_resource(&cfg->res);
		kfree(cfg);
	}

	mutex_unlock(&pci_mmcfg_lock);

	return rc;
}

/* Delete MMCFG information for host bridges */
int pci_mmconfig_delete(u16 seg, u8 start, u8 end)
{
	struct pci_mmcfg_region *cfg;

	mutex_lock(&pci_mmcfg_lock);
	list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list)
		if (cfg->segment == seg && cfg->start_bus == start &&
		    cfg->end_bus == end) {
			list_del_rcu(&cfg->list);
			synchronize_rcu();
			pci_mmcfg_arch_unmap(cfg);
			if (cfg->res.parent)
				release_resource(&cfg->res);
			mutex_unlock(&pci_mmcfg_lock);
			kfree(cfg);
			return 0;
		}
	mutex_unlock(&pci_mmcfg_lock);

	return -ENOENT;
}