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