mmconfig-shared.c revision a83fe32fa668c0a17b3f99a1480b006f7d649924
1b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert/* 2b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert * mmconfig-shared.c - Low-level direct PCI config space access via 3b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert * MMCONFIG - common code between i386 and x86-64. 4b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert * 5b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert * This code does: 69358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert * - known chipset handling 7b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert * - ACPI decoding and validation 8b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert * 9b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert * Per-architecture code takes care of the mappings and accesses 10b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert * themselves. 11b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert */ 12b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert 13b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert#include <linux/pci.h> 14b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert#include <linux/init.h> 15b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert#include <linux/acpi.h> 16b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert#include <linux/bitmap.h> 17b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert#include <asm/e820.h> 18b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert 19b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert#include "pci.h" 20b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert 21b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert/* aperture is up to 256MB but BIOS may reserve less */ 22b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert#define MMCONFIG_APER_MIN (2 * 1024*1024) 23b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert#define MMCONFIG_APER_MAX (256 * 1024*1024) 24b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert 25a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin/* Indicate if the mmcfg resources have been placed into the resource table. */ 26a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbinstatic int __initdata pci_mmcfg_resources_inserted; 27a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin 28429d512e532ec9c969aa6f66ddbc542f3a5fe4daOGAWA Hirofumistatic const char __init *pci_mmcfg_e7520(void) 299358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert{ 309358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert u32 win; 31bb63b4219976d48ed6d22ac33c18be334fb5a78cYinghai Lu raw_pci_ops->read(0, 0, PCI_DEVFN(0, 0), 0xce, 2, &win); 329358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 33b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert win = win & 0xf000; 34b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert if(win == 0x0000 || win == 0xf000) 35b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert pci_mmcfg_config_num = 0; 36b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert else { 37b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert pci_mmcfg_config_num = 1; 38b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL); 39b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert if (!pci_mmcfg_config) 40b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert return NULL; 41b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert pci_mmcfg_config[0].address = win << 16; 42b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert pci_mmcfg_config[0].pci_segment = 0; 43b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert pci_mmcfg_config[0].start_bus_number = 0; 44b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert pci_mmcfg_config[0].end_bus_number = 255; 45b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert } 469358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 479358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert return "Intel Corporation E7520 Memory Controller Hub"; 489358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert} 499358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 50429d512e532ec9c969aa6f66ddbc542f3a5fe4daOGAWA Hirofumistatic const char __init *pci_mmcfg_intel_945(void) 519358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert{ 529358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert u32 pciexbar, mask = 0, len = 0; 539358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 549358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert pci_mmcfg_config_num = 1; 559358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 56bb63b4219976d48ed6d22ac33c18be334fb5a78cYinghai Lu raw_pci_ops->read(0, 0, PCI_DEVFN(0, 0), 0x48, 4, &pciexbar); 579358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 589358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert /* Enable bit */ 599358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert if (!(pciexbar & 1)) 609358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert pci_mmcfg_config_num = 0; 619358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 629358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert /* Size bits */ 639358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert switch ((pciexbar >> 1) & 3) { 649358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert case 0: 659358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert mask = 0xf0000000U; 669358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert len = 0x10000000U; 679358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert break; 689358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert case 1: 699358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert mask = 0xf8000000U; 709358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert len = 0x08000000U; 719358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert break; 729358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert case 2: 739358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert mask = 0xfc000000U; 749358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert len = 0x04000000U; 759358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert break; 769358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert default: 779358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert pci_mmcfg_config_num = 0; 789358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert } 799358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 809358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert /* Errata #2, things break when not aligned on a 256Mb boundary */ 819358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert /* Can only happen in 64M/128M mode */ 829358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 839358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert if ((pciexbar & mask) & 0x0fffffffU) 849358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert pci_mmcfg_config_num = 0; 859358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 86b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert /* Don't hit the APIC registers and their friends */ 87b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert if ((pciexbar & mask) >= 0xf0000000U) 88b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert pci_mmcfg_config_num = 0; 89b5229dbb857f61d77d8d4048d9033387a5411b8eOlivier Galibert 909358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert if (pci_mmcfg_config_num) { 919358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL); 929358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert if (!pci_mmcfg_config) 939358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert return NULL; 949358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert pci_mmcfg_config[0].address = pciexbar & mask; 959358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert pci_mmcfg_config[0].pci_segment = 0; 969358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert pci_mmcfg_config[0].start_bus_number = 0; 979358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1; 989358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert } 999358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 1009358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub"; 1019358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert} 1029358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 1037fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lustatic const char __init *pci_mmcfg_amd_fam10h(void) 1047fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu{ 1057fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu u32 low, high, address; 1067fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu u64 base, msr; 1077fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu int i; 1087fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu unsigned segnbits = 0, busnbits; 1097fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu 1105f0b2976cb2b62668a076f54419c24b8ab677167Yinghai Lu if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF)) 1115f0b2976cb2b62668a076f54419c24b8ab677167Yinghai Lu return NULL; 1125f0b2976cb2b62668a076f54419c24b8ab677167Yinghai Lu 1137fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu address = MSR_FAM10H_MMIO_CONF_BASE; 1147fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu if (rdmsr_safe(address, &low, &high)) 1157fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu return NULL; 1167fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu 1177fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu msr = high; 1187fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu msr <<= 32; 1197fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu msr |= low; 1207fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu 1217fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu /* mmconfig is not enable */ 1227fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu if (!(msr & FAM10H_MMIO_CONF_ENABLE)) 1237fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu return NULL; 1247fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu 1257fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT); 1267fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu 1277fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu busnbits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) & 1287fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu FAM10H_MMIO_CONF_BUSRANGE_MASK; 1297fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu 1307fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu /* 1317fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu * only handle bus 0 ? 1327fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu * need to skip it 1337fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu */ 1347fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu if (!busnbits) 1357fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu return NULL; 1367fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu 1377fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu if (busnbits > 8) { 1387fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu segnbits = busnbits - 8; 1397fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu busnbits = 8; 1407fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu } 1417fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu 1427fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu pci_mmcfg_config_num = (1 << segnbits); 1437fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]) * 1447fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu pci_mmcfg_config_num, GFP_KERNEL); 1457fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu if (!pci_mmcfg_config) 1467fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu return NULL; 1477fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu 1487fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu for (i = 0; i < (1 << segnbits); i++) { 1497fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu pci_mmcfg_config[i].address = base + (1<<28) * i; 1507fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu pci_mmcfg_config[i].pci_segment = i; 1517fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu pci_mmcfg_config[i].start_bus_number = 0; 1527fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu pci_mmcfg_config[i].end_bus_number = (1 << busnbits) - 1; 1537fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu } 1547fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu 1557fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu return "AMD Family 10h NB"; 1567fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu} 1577fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu 1589358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibertstruct pci_mmcfg_hostbridge_probe { 1597fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu u32 bus; 1607fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu u32 devfn; 1619358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert u32 vendor; 1629358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert u32 device; 1639358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert const char *(*probe)(void); 1649358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert}; 1659358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 166429d512e532ec9c969aa6f66ddbc542f3a5fe4daOGAWA Hirofumistatic struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = { 1677fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL, 1687fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 }, 1697fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL, 1707fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 }, 1717fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu { 0, PCI_DEVFN(0x18, 0), PCI_VENDOR_ID_AMD, 1727fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu 0x1200, pci_mmcfg_amd_fam10h }, 1737fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu { 0xff, PCI_DEVFN(0, 0), PCI_VENDOR_ID_AMD, 1747fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu 0x1200, pci_mmcfg_amd_fam10h }, 1759358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert}; 1769358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 1779358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibertstatic int __init pci_mmcfg_check_hostbridge(void) 1789358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert{ 1799358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert u32 l; 1807fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu u32 bus, devfn; 1819358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert u16 vendor, device; 1829358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert int i; 1839358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert const char *name; 1849358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 185bb63b4219976d48ed6d22ac33c18be334fb5a78cYinghai Lu if (!raw_pci_ops) 186bb63b4219976d48ed6d22ac33c18be334fb5a78cYinghai Lu return 0; 187bb63b4219976d48ed6d22ac33c18be334fb5a78cYinghai Lu 1889358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert pci_mmcfg_config_num = 0; 1899358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert pci_mmcfg_config = NULL; 1909358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert name = NULL; 1919358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 192429d512e532ec9c969aa6f66ddbc542f3a5fe4daOGAWA Hirofumi for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) { 1937fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu bus = pci_mmcfg_probes[i].bus; 1947fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu devfn = pci_mmcfg_probes[i].devfn; 195bb63b4219976d48ed6d22ac33c18be334fb5a78cYinghai Lu raw_pci_ops->read(0, bus, devfn, 0, 4, &l); 1967fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu vendor = l & 0xffff; 1977fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu device = (l >> 16) & 0xffff; 1987fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4Yinghai Lu 199429d512e532ec9c969aa6f66ddbc542f3a5fe4daOGAWA Hirofumi if (pci_mmcfg_probes[i].vendor == vendor && 200429d512e532ec9c969aa6f66ddbc542f3a5fe4daOGAWA Hirofumi pci_mmcfg_probes[i].device == device) 2019358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert name = pci_mmcfg_probes[i].probe(); 202429d512e532ec9c969aa6f66ddbc542f3a5fe4daOGAWA Hirofumi } 2039358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 2049358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert if (name) { 205429d512e532ec9c969aa6f66ddbc542f3a5fe4daOGAWA Hirofumi printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n", 206429d512e532ec9c969aa6f66ddbc542f3a5fe4daOGAWA Hirofumi name, pci_mmcfg_config_num ? "with" : "without"); 2079358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert } 2089358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 2099358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert return name != NULL; 2109358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert} 2119358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 212a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbinstatic void __init pci_mmcfg_insert_resources(unsigned long resource_flags) 2136a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert{ 2146a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert#define PCI_MMCFG_RESOURCE_NAME_LEN 19 2156a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert int i; 2166a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert struct resource *res; 2176a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert char *names; 2186a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert unsigned num_buses; 2196a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert 2206a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res), 2216a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert pci_mmcfg_config_num, GFP_KERNEL); 2226a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert if (!res) { 2236a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n"); 2246a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert return; 2256a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert } 2266a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert 2276a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert names = (void *)&res[pci_mmcfg_config_num]; 2286a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert for (i = 0; i < pci_mmcfg_config_num; i++, res++) { 229429d512e532ec9c969aa6f66ddbc542f3a5fe4daOGAWA Hirofumi struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[i]; 230429d512e532ec9c969aa6f66ddbc542f3a5fe4daOGAWA Hirofumi num_buses = cfg->end_bus_number - cfg->start_bus_number + 1; 2316a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert res->name = names; 2326a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u", 233429d512e532ec9c969aa6f66ddbc542f3a5fe4daOGAWA Hirofumi cfg->pci_segment); 234429d512e532ec9c969aa6f66ddbc542f3a5fe4daOGAWA Hirofumi res->start = cfg->address; 2356a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert res->end = res->start + (num_buses << 20) - 1; 236a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin res->flags = IORESOURCE_MEM | resource_flags; 2376a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert insert_resource(&iomem_resource, res); 2386a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert names += PCI_MMCFG_RESOURCE_NAME_LEN; 2396a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert } 240a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin 241a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin /* Mark that the resources have been inserted. */ 242a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin pci_mmcfg_resources_inserted = 1; 2436a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert} 2446a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert 2457752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancockstatic acpi_status __init check_mcfg_resource(struct acpi_resource *res, 2467752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock void *data) 2477752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock{ 2487752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock struct resource *mcfg_res = data; 2497752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock struct acpi_resource_address64 address; 2507752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock acpi_status status; 2517752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock 2527752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) { 2537752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock struct acpi_resource_fixed_memory32 *fixmem32 = 2547752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock &res->data.fixed_memory32; 2557752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock if (!fixmem32) 2567752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock return AE_OK; 2577752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock if ((mcfg_res->start >= fixmem32->address) && 2587752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock (mcfg_res->end < (fixmem32->address + 2597752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock fixmem32->address_length))) { 2607752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock mcfg_res->flags = 1; 2617752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock return AE_CTRL_TERMINATE; 2627752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock } 2637752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock } 2647752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock if ((res->type != ACPI_RESOURCE_TYPE_ADDRESS32) && 2657752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock (res->type != ACPI_RESOURCE_TYPE_ADDRESS64)) 2667752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock return AE_OK; 2677752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock 2687752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock status = acpi_resource_to_address64(res, &address); 2697752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock if (ACPI_FAILURE(status) || 2707752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock (address.address_length <= 0) || 2717752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock (address.resource_type != ACPI_MEMORY_RANGE)) 2727752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock return AE_OK; 2737752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock 2747752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock if ((mcfg_res->start >= address.minimum) && 2757752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock (mcfg_res->end < (address.minimum + address.address_length))) { 2767752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock mcfg_res->flags = 1; 2777752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock return AE_CTRL_TERMINATE; 2787752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock } 2797752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock return AE_OK; 2807752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock} 2817752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock 2827752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancockstatic acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl, 2837752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock void *context, void **rv) 2847752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock{ 2857752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock struct resource *mcfg_res = context; 2867752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock 2877752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock acpi_walk_resources(handle, METHOD_NAME__CRS, 2887752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock check_mcfg_resource, context); 2897752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock 2907752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock if (mcfg_res->flags) 2917752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock return AE_CTRL_TERMINATE; 2927752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock 2937752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock return AE_OK; 2947752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock} 2957752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock 296a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lustatic int __init is_acpi_reserved(u64 start, u64 end, unsigned not_used) 2977752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock{ 2987752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock struct resource mcfg_res; 2997752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock 3007752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock mcfg_res.start = start; 3017752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock mcfg_res.end = end; 3027752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock mcfg_res.flags = 0; 3037752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock 3047752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock acpi_get_devices("PNP0C01", find_mboard_resource, &mcfg_res, NULL); 3057752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock 3067752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock if (!mcfg_res.flags) 3077752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock acpi_get_devices("PNP0C02", find_mboard_resource, &mcfg_res, 3087752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock NULL); 3097752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock 3107752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock return mcfg_res.flags; 3117752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock} 3127752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock 313a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lutypedef int (*check_reserved_t)(u64 start, u64 end, unsigned type); 314a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu 315a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lustatic int __init is_mmconf_reserved(check_reserved_t is_reserved, 316a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu u64 addr, u64 size, int i, 317a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu typeof(pci_mmcfg_config[0]) *cfg, int with_e820) 318a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu{ 319a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu u64 old_size = size; 320a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu int valid = 0; 321a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu 322a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu while (!is_reserved(addr, addr + size - 1, E820_RESERVED)) { 323a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu size >>= 1; 324a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu if (size < (16UL<<20)) 325a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu break; 326a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu } 327a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu 328a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu if (size >= (16UL<<20) || size == old_size) { 329a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu printk(KERN_NOTICE 330a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu "PCI: MCFG area at %Lx reserved in %s\n", 331a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu addr, with_e820?"E820":"ACPI motherboard resources"); 332a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu valid = 1; 333a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu 334a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu if (old_size != size) { 335a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu /* update end_bus_number */ 336a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu cfg->end_bus_number = cfg->start_bus_number + ((size>>20) - 1); 337a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu printk(KERN_NOTICE "PCI: updated MCFG configuration %d: base %lx " 338a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu "segment %hu buses %u - %u\n", 339a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu i, (unsigned long)cfg->address, cfg->pci_segment, 340a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu (unsigned int)cfg->start_bus_number, 341a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu (unsigned int)cfg->end_bus_number); 342a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu } 343a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu } 344a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu 345a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu return valid; 346a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu} 347a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu 348bb63b4219976d48ed6d22ac33c18be334fb5a78cYinghai Lustatic void __init pci_mmcfg_reject_broken(int early) 34944de0203fab205417b24322272c53ee0883c36e7OGAWA Hirofumi{ 35026054ed02bb20f5b2e02d92cb6f0be0e2b0196d5OGAWA Hirofumi typeof(pci_mmcfg_config[0]) *cfg; 3517752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock int i; 35226054ed02bb20f5b2e02d92cb6f0be0e2b0196d5OGAWA Hirofumi 35326054ed02bb20f5b2e02d92cb6f0be0e2b0196d5OGAWA Hirofumi if ((pci_mmcfg_config_num == 0) || 35426054ed02bb20f5b2e02d92cb6f0be0e2b0196d5OGAWA Hirofumi (pci_mmcfg_config == NULL) || 35526054ed02bb20f5b2e02d92cb6f0be0e2b0196d5OGAWA Hirofumi (pci_mmcfg_config[0].address == 0)) 35626054ed02bb20f5b2e02d92cb6f0be0e2b0196d5OGAWA Hirofumi return; 35726054ed02bb20f5b2e02d92cb6f0be0e2b0196d5OGAWA Hirofumi 35826054ed02bb20f5b2e02d92cb6f0be0e2b0196d5OGAWA Hirofumi cfg = &pci_mmcfg_config[0]; 35944de0203fab205417b24322272c53ee0883c36e7OGAWA Hirofumi 3607752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock for (i = 0; i < pci_mmcfg_config_num; i++) { 36105c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu int valid = 0; 362a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu u64 addr, size; 363a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu 3647752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock cfg = &pci_mmcfg_config[i]; 365a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu addr = cfg->start_bus_number; 366a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu addr <<= 20; 367a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu addr += cfg->address; 368a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu size = cfg->end_bus_number + 1 - cfg->start_bus_number; 369a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu size <<= 20; 37005c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lx " 3717752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock "segment %hu buses %u - %u\n", 3727752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock i, (unsigned long)cfg->address, cfg->pci_segment, 3737752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock (unsigned int)cfg->start_bus_number, 3747752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock (unsigned int)cfg->end_bus_number); 37505c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu 376a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu if (!early) 377a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu valid = is_mmconf_reserved(is_acpi_reserved, addr, size, i, cfg, 0); 37805c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu 37905c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu if (valid) 38005c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu continue; 38105c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu 38205c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu if (!early) 3837752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not" 3847752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock " reserved in ACPI motherboard resources\n", 3857752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock cfg->address); 386a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu 38705c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu /* Don't try to do this check unless configuration 388bb63b4219976d48ed6d22ac33c18be334fb5a78cYinghai Lu type 1 is available. how about type 2 ?*/ 389a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu if (raw_pci_ops) 390a83fe32fa668c0a17b3f99a1480b006f7d649924Yinghai Lu valid = is_mmconf_reserved(e820_all_mapped, addr, size, i, cfg, 1); 39105c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu 39205c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu if (!valid) 39305c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu goto reject; 39444de0203fab205417b24322272c53ee0883c36e7OGAWA Hirofumi } 3957752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock 39626054ed02bb20f5b2e02d92cb6f0be0e2b0196d5OGAWA Hirofumi return; 39726054ed02bb20f5b2e02d92cb6f0be0e2b0196d5OGAWA Hirofumi 39826054ed02bb20f5b2e02d92cb6f0be0e2b0196d5OGAWA Hirofumireject: 39926054ed02bb20f5b2e02d92cb6f0be0e2b0196d5OGAWA Hirofumi printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); 4000b64ad7123eb013c3de26750f2d4c356cd566231Yinghai Lu pci_mmcfg_arch_free(); 40126054ed02bb20f5b2e02d92cb6f0be0e2b0196d5OGAWA Hirofumi kfree(pci_mmcfg_config); 40226054ed02bb20f5b2e02d92cb6f0be0e2b0196d5OGAWA Hirofumi pci_mmcfg_config = NULL; 40326054ed02bb20f5b2e02d92cb6f0be0e2b0196d5OGAWA Hirofumi pci_mmcfg_config_num = 0; 40444de0203fab205417b24322272c53ee0883c36e7OGAWA Hirofumi} 40544de0203fab205417b24322272c53ee0883c36e7OGAWA Hirofumi 40605c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lustatic int __initdata known_bridge; 4077752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock 408968cbfad1a727b5689ae620f4d970abf6ce73340Thomas Gleixnerstatic void __init __pci_mmcfg_init(int early) 409b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert{ 4107752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock /* MMCONFIG disabled */ 411b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert if ((pci_probe & PCI_PROBE_MMCONF) == 0) 412b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert return; 413b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert 4147752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock /* MMCONFIG already enabled */ 41505c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu if (!early && !(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF)) 4167752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock return; 4179358c693c5ac1afde28f24ac651f7903d32a850cOlivier Galibert 41805c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu /* for late to exit */ 41905c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu if (known_bridge) 42005c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu return; 4217752d5cfe3d11ca0bb9c673ec38bd78ba6578f8eRobert Hancock 422bb63b4219976d48ed6d22ac33c18be334fb5a78cYinghai Lu if (early) { 42305c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu if (pci_mmcfg_check_hostbridge()) 42405c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu known_bridge = 1; 42505c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu } 42605c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu 42705c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu if (!known_bridge) { 42805c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg); 429bb63b4219976d48ed6d22ac33c18be334fb5a78cYinghai Lu pci_mmcfg_reject_broken(early); 43005c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu } 431b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert 432b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert if ((pci_mmcfg_config_num == 0) || 433b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert (pci_mmcfg_config == NULL) || 434b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert (pci_mmcfg_config[0].address == 0)) 435b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert return; 436b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert 437b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert if (pci_mmcfg_arch_init()) { 4386a0668fc41fa479df617151c2d4e297299a4ffe2Olivier Galibert if (known_bridge) 439a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin pci_mmcfg_insert_resources(IORESOURCE_BUSY); 440b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; 441a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin } else { 442a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin /* 443a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin * Signal not to attempt to insert mmcfg resources because 444a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin * the architecture mmcfg setup could not initialize. 445a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin */ 446a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin pci_mmcfg_resources_inserted = 1; 447b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert } 448b78673944b22b662b270c8bba5c198f19e4ee4e1Olivier Galibert} 449a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin 450bb63b4219976d48ed6d22ac33c18be334fb5a78cYinghai Luvoid __init pci_mmcfg_early_init(void) 45105c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu{ 452bb63b4219976d48ed6d22ac33c18be334fb5a78cYinghai Lu __pci_mmcfg_init(1); 45305c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu} 45405c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu 45505c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Luvoid __init pci_mmcfg_late_init(void) 45605c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu{ 457bb63b4219976d48ed6d22ac33c18be334fb5a78cYinghai Lu __pci_mmcfg_init(0); 45805c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu} 45905c58b8ac77639c17205f0b2a2d9eb1971dc47adYinghai Lu 460a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbinstatic int __init pci_mmcfg_late_insert_resources(void) 461a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin{ 462a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin /* 463a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin * If resources are already inserted or we are not using MMCONFIG, 464a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin * don't insert the resources. 465a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin */ 466a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin if ((pci_mmcfg_resources_inserted == 1) || 467a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin (pci_probe & PCI_PROBE_MMCONF) == 0 || 468a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin (pci_mmcfg_config_num == 0) || 469a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin (pci_mmcfg_config == NULL) || 470a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin (pci_mmcfg_config[0].address == 0)) 471a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin return 1; 472a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin 473a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin /* 474a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin * Attempt to insert the mmcfg resources but not with the busy flag 475a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin * marked so it won't cause request errors when __request_region is 476a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin * called. 477a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin */ 478a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin pci_mmcfg_insert_resources(0); 479a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin 480a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin return 0; 481a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin} 482a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin 483a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin/* 484a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin * Perform MMCONFIG resource insertion after PCI initialization to allow for 485a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin * misprogrammed MCFG tables that state larger sizes but actually conflict 486a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin * with other system resources. 487a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbin */ 488a5ba7971045a90a36cef8f7d5a3075600b475b74Aaron Durbinlate_initcall(pci_mmcfg_late_insert_resources); 489