1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2fb9aa6f1SThomas Gleixner /* 3fb9aa6f1SThomas Gleixner * Low-Level PCI Support for PC 4fb9aa6f1SThomas Gleixner * 5fb9aa6f1SThomas Gleixner * (c) 1999--2000 Martin Mares <mj@ucw.cz> 6fb9aa6f1SThomas Gleixner */ 7fb9aa6f1SThomas Gleixner 8fb9aa6f1SThomas Gleixner #include <linux/sched.h> 9fb9aa6f1SThomas Gleixner #include <linux/pci.h> 1089016506SJiang Liu #include <linux/pci-acpi.h> 11fb9aa6f1SThomas Gleixner #include <linux/ioport.h> 12fb9aa6f1SThomas Gleixner #include <linux/init.h> 13fb9aa6f1SThomas Gleixner #include <linux/dmi.h> 145a0e3ad6STejun Heo #include <linux/slab.h> 15fb9aa6f1SThomas Gleixner 16fb9aa6f1SThomas Gleixner #include <asm/acpi.h> 17fb9aa6f1SThomas Gleixner #include <asm/segment.h> 18fb9aa6f1SThomas Gleixner #include <asm/io.h> 19fb9aa6f1SThomas Gleixner #include <asm/smp.h> 2082487711SJaswinder Singh Rajput #include <asm/pci_x86.h> 21f9a37be0SMatthew Garrett #include <asm/setup.h> 222c681e6bSThomas Gleixner #include <asm/irqdomain.h> 23fb9aa6f1SThomas Gleixner 24fb9aa6f1SThomas Gleixner unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | 25fb9aa6f1SThomas Gleixner PCI_PROBE_MMCONF; 26fb9aa6f1SThomas Gleixner 27fb9aa6f1SThomas Gleixner static int pci_bf_sort; 28fb9aa6f1SThomas Gleixner int pci_routeirq; 29a9322f64SStefan Assmann int noioapicquirk; 3041b9eb26SStefan Assmann #ifdef CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS 3141b9eb26SStefan Assmann int noioapicreroute = 0; 3241b9eb26SStefan Assmann #else 339197979bSStefan Assmann int noioapicreroute = 1; 3441b9eb26SStefan Assmann #endif 35fb9aa6f1SThomas Gleixner int pcibios_last_bus = -1; 36fb9aa6f1SThomas Gleixner unsigned long pirq_table_addr; 3772da0b07SJan Beulich const struct pci_raw_ops *__read_mostly raw_pci_ops; 3872da0b07SJan Beulich const struct pci_raw_ops *__read_mostly raw_pci_ext_ops; 39b6ce068aSMatthew Wilcox 40b6ce068aSMatthew Wilcox int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn, 41b6ce068aSMatthew Wilcox int reg, int len, u32 *val) 42b6ce068aSMatthew Wilcox { 43beef3129SMatthew Wilcox if (domain == 0 && reg < 256 && raw_pci_ops) 44b6ce068aSMatthew Wilcox return raw_pci_ops->read(domain, bus, devfn, reg, len, val); 45b6ce068aSMatthew Wilcox if (raw_pci_ext_ops) 46b6ce068aSMatthew Wilcox return raw_pci_ext_ops->read(domain, bus, devfn, reg, len, val); 47b6ce068aSMatthew Wilcox return -EINVAL; 48b6ce068aSMatthew Wilcox } 49b6ce068aSMatthew Wilcox 50b6ce068aSMatthew Wilcox int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn, 51b6ce068aSMatthew Wilcox int reg, int len, u32 val) 52b6ce068aSMatthew Wilcox { 53beef3129SMatthew Wilcox if (domain == 0 && reg < 256 && raw_pci_ops) 54b6ce068aSMatthew Wilcox return raw_pci_ops->write(domain, bus, devfn, reg, len, val); 55b6ce068aSMatthew Wilcox if (raw_pci_ext_ops) 56b6ce068aSMatthew Wilcox return raw_pci_ext_ops->write(domain, bus, devfn, reg, len, val); 57b6ce068aSMatthew Wilcox return -EINVAL; 58b6ce068aSMatthew Wilcox } 59fb9aa6f1SThomas Gleixner 60fb9aa6f1SThomas Gleixner static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) 61fb9aa6f1SThomas Gleixner { 62b6ce068aSMatthew Wilcox return raw_pci_read(pci_domain_nr(bus), bus->number, 63a79e4198SJeff Garzik devfn, where, size, value); 64fb9aa6f1SThomas Gleixner } 65fb9aa6f1SThomas Gleixner 66fb9aa6f1SThomas Gleixner static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) 67fb9aa6f1SThomas Gleixner { 68b6ce068aSMatthew Wilcox return raw_pci_write(pci_domain_nr(bus), bus->number, 69a79e4198SJeff Garzik devfn, where, size, value); 70fb9aa6f1SThomas Gleixner } 71fb9aa6f1SThomas Gleixner 72fb9aa6f1SThomas Gleixner struct pci_ops pci_root_ops = { 73fb9aa6f1SThomas Gleixner .read = pci_read, 74fb9aa6f1SThomas Gleixner .write = pci_write, 75fb9aa6f1SThomas Gleixner }; 76fb9aa6f1SThomas Gleixner 77fb9aa6f1SThomas Gleixner /* 78df65c1bcSThomas Gleixner * This interrupt-safe spinlock protects all accesses to PCI configuration 79df65c1bcSThomas Gleixner * space, except for the mmconfig (ECAM) based operations. 80fb9aa6f1SThomas Gleixner */ 81d19f61f0SThomas Gleixner DEFINE_RAW_SPINLOCK(pci_config_lock); 82fb9aa6f1SThomas Gleixner 834ac9cbfaSMathias Krause static int __init can_skip_ioresource_align(const struct dmi_system_id *d) 8413a6ddb0SYinghai Lu { 8513a6ddb0SYinghai Lu pci_probe |= PCI_CAN_SKIP_ISA_ALIGN; 8613a6ddb0SYinghai Lu printk(KERN_INFO "PCI: %s detected, can skip ISA alignment\n", d->ident); 8713a6ddb0SYinghai Lu return 0; 8813a6ddb0SYinghai Lu } 8913a6ddb0SYinghai Lu 904ac9cbfaSMathias Krause static const struct dmi_system_id can_skip_pciprobe_dmi_table[] __initconst = { 9113a6ddb0SYinghai Lu /* 9213a6ddb0SYinghai Lu * Systems where PCI IO resource ISA alignment can be skipped 9313a6ddb0SYinghai Lu * when the ISA enable bit in the bridge control is not set 9413a6ddb0SYinghai Lu */ 9513a6ddb0SYinghai Lu { 9613a6ddb0SYinghai Lu .callback = can_skip_ioresource_align, 9713a6ddb0SYinghai Lu .ident = "IBM System x3800", 9813a6ddb0SYinghai Lu .matches = { 9913a6ddb0SYinghai Lu DMI_MATCH(DMI_SYS_VENDOR, "IBM"), 10013a6ddb0SYinghai Lu DMI_MATCH(DMI_PRODUCT_NAME, "x3800"), 10113a6ddb0SYinghai Lu }, 10213a6ddb0SYinghai Lu }, 10313a6ddb0SYinghai Lu { 10413a6ddb0SYinghai Lu .callback = can_skip_ioresource_align, 10513a6ddb0SYinghai Lu .ident = "IBM System x3850", 10613a6ddb0SYinghai Lu .matches = { 10713a6ddb0SYinghai Lu DMI_MATCH(DMI_SYS_VENDOR, "IBM"), 10813a6ddb0SYinghai Lu DMI_MATCH(DMI_PRODUCT_NAME, "x3850"), 10913a6ddb0SYinghai Lu }, 11013a6ddb0SYinghai Lu }, 11113a6ddb0SYinghai Lu { 11213a6ddb0SYinghai Lu .callback = can_skip_ioresource_align, 11313a6ddb0SYinghai Lu .ident = "IBM System x3950", 11413a6ddb0SYinghai Lu .matches = { 11513a6ddb0SYinghai Lu DMI_MATCH(DMI_SYS_VENDOR, "IBM"), 11613a6ddb0SYinghai Lu DMI_MATCH(DMI_PRODUCT_NAME, "x3950"), 11713a6ddb0SYinghai Lu }, 11813a6ddb0SYinghai Lu }, 11913a6ddb0SYinghai Lu {} 12013a6ddb0SYinghai Lu }; 12113a6ddb0SYinghai Lu 12213a6ddb0SYinghai Lu void __init dmi_check_skip_isa_align(void) 12313a6ddb0SYinghai Lu { 12413a6ddb0SYinghai Lu dmi_check_system(can_skip_pciprobe_dmi_table); 12513a6ddb0SYinghai Lu } 12613a6ddb0SYinghai Lu 127a18e3690SGreg Kroah-Hartman static void pcibios_fixup_device_resources(struct pci_dev *dev) 128bb71ad88SGary Hade { 129bb71ad88SGary Hade struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE]; 1307bd1c365SMike Habeck struct resource *bar_r; 1317bd1c365SMike Habeck int bar; 1327bd1c365SMike Habeck 1337bd1c365SMike Habeck if (pci_probe & PCI_NOASSIGN_BARS) { 1347bd1c365SMike Habeck /* 1357bd1c365SMike Habeck * If the BIOS did not assign the BAR, zero out the 136386ed2abSAndrea Gelmini * resource so the kernel doesn't attempt to assign 1377bd1c365SMike Habeck * it later on in pci_assign_unassigned_resources 1387bd1c365SMike Habeck */ 139c9c13ba4SDenis Efremov for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { 1407bd1c365SMike Habeck bar_r = &dev->resource[bar]; 1417bd1c365SMike Habeck if (bar_r->start == 0 && bar_r->end != 0) { 1427bd1c365SMike Habeck bar_r->flags = 0; 1437bd1c365SMike Habeck bar_r->end = 0; 1447bd1c365SMike Habeck } 1457bd1c365SMike Habeck } 1467bd1c365SMike Habeck } 147bb71ad88SGary Hade 148bb71ad88SGary Hade if (pci_probe & PCI_NOASSIGN_ROMS) { 149bb71ad88SGary Hade if (rom_r->parent) 150bb71ad88SGary Hade return; 151bb71ad88SGary Hade if (rom_r->start) { 152bb71ad88SGary Hade /* we deal with BIOS assigned ROM later */ 153bb71ad88SGary Hade return; 154bb71ad88SGary Hade } 155bb71ad88SGary Hade rom_r->start = rom_r->end = rom_r->flags = 0; 156bb71ad88SGary Hade } 157bb71ad88SGary Hade } 158bb71ad88SGary Hade 159fb9aa6f1SThomas Gleixner /* 160fb9aa6f1SThomas Gleixner * Called after each bus is probed, but before its children 161fb9aa6f1SThomas Gleixner * are examined. 162fb9aa6f1SThomas Gleixner */ 163fb9aa6f1SThomas Gleixner 164a18e3690SGreg Kroah-Hartman void pcibios_fixup_bus(struct pci_bus *b) 165fb9aa6f1SThomas Gleixner { 166bb71ad88SGary Hade struct pci_dev *dev; 167bb71ad88SGary Hade 168237865f1SBjorn Helgaas pci_read_bridge_bases(b); 169bb71ad88SGary Hade list_for_each_entry(dev, &b->devices, bus_list) 170bb71ad88SGary Hade pcibios_fixup_device_resources(dev); 171fb9aa6f1SThomas Gleixner } 172fb9aa6f1SThomas Gleixner 17389016506SJiang Liu void pcibios_add_bus(struct pci_bus *bus) 17489016506SJiang Liu { 17589016506SJiang Liu acpi_pci_add_bus(bus); 17689016506SJiang Liu } 17789016506SJiang Liu 17889016506SJiang Liu void pcibios_remove_bus(struct pci_bus *bus) 17989016506SJiang Liu { 18089016506SJiang Liu acpi_pci_remove_bus(bus); 18189016506SJiang Liu } 18289016506SJiang Liu 183fb9aa6f1SThomas Gleixner /* 184fb9aa6f1SThomas Gleixner * Only use DMI information to set this if nothing was passed 185fb9aa6f1SThomas Gleixner * on the kernel command line (which was parsed earlier). 186fb9aa6f1SThomas Gleixner */ 187fb9aa6f1SThomas Gleixner 1884ac9cbfaSMathias Krause static int __init set_bf_sort(const struct dmi_system_id *d) 189fb9aa6f1SThomas Gleixner { 190fb9aa6f1SThomas Gleixner if (pci_bf_sort == pci_bf_sort_default) { 191fb9aa6f1SThomas Gleixner pci_bf_sort = pci_dmi_bf; 192fb9aa6f1SThomas Gleixner printk(KERN_INFO "PCI: %s detected, enabling pci=bfsort.\n", d->ident); 193fb9aa6f1SThomas Gleixner } 194fb9aa6f1SThomas Gleixner return 0; 195fb9aa6f1SThomas Gleixner } 196fb9aa6f1SThomas Gleixner 1974ac9cbfaSMathias Krause static void __init read_dmi_type_b1(const struct dmi_header *dm, 1986e8af08dSNarendra_K@Dell.com void *private_data) 1996e8af08dSNarendra_K@Dell.com { 200f5ab3b70SJean Delvare u8 *data = (u8 *)dm + 4; 2016e8af08dSNarendra_K@Dell.com 2026e8af08dSNarendra_K@Dell.com if (dm->type != 0xB1) 2036e8af08dSNarendra_K@Dell.com return; 204f5ab3b70SJean Delvare if ((((*(u32 *)data) >> 9) & 0x03) == 0x01) 205f5ab3b70SJean Delvare set_bf_sort((const struct dmi_system_id *)private_data); 2066e8af08dSNarendra_K@Dell.com } 2076e8af08dSNarendra_K@Dell.com 2084ac9cbfaSMathias Krause static int __init find_sort_method(const struct dmi_system_id *d) 2096e8af08dSNarendra_K@Dell.com { 210f5ab3b70SJean Delvare dmi_walk(read_dmi_type_b1, (void *)d); 2116e8af08dSNarendra_K@Dell.com return 0; 2126e8af08dSNarendra_K@Dell.com } 2136e8af08dSNarendra_K@Dell.com 214fb9aa6f1SThomas Gleixner /* 215fb9aa6f1SThomas Gleixner * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus) 216fb9aa6f1SThomas Gleixner */ 217fb9aa6f1SThomas Gleixner #ifdef __i386__ 2184ac9cbfaSMathias Krause static int __init assign_all_busses(const struct dmi_system_id *d) 219fb9aa6f1SThomas Gleixner { 220fb9aa6f1SThomas Gleixner pci_probe |= PCI_ASSIGN_ALL_BUSSES; 221fb9aa6f1SThomas Gleixner printk(KERN_INFO "%s detected: enabling PCI bus# renumbering" 222fb9aa6f1SThomas Gleixner " (pci=assign-busses)\n", d->ident); 223fb9aa6f1SThomas Gleixner return 0; 224fb9aa6f1SThomas Gleixner } 225fb9aa6f1SThomas Gleixner #endif 226fb9aa6f1SThomas Gleixner 2274ac9cbfaSMathias Krause static int __init set_scan_all(const struct dmi_system_id *d) 228284f5f9dSBjorn Helgaas { 229284f5f9dSBjorn Helgaas printk(KERN_INFO "PCI: %s detected, enabling pci=pcie_scan_all\n", 230284f5f9dSBjorn Helgaas d->ident); 231284f5f9dSBjorn Helgaas pci_add_flags(PCI_SCAN_ALL_PCIE_DEVS); 232284f5f9dSBjorn Helgaas return 0; 233284f5f9dSBjorn Helgaas } 234284f5f9dSBjorn Helgaas 2354ac9cbfaSMathias Krause static const struct dmi_system_id pciprobe_dmi_table[] __initconst = { 236fb9aa6f1SThomas Gleixner #ifdef __i386__ 237fb9aa6f1SThomas Gleixner /* 238fb9aa6f1SThomas Gleixner * Laptops which need pci=assign-busses to see Cardbus cards 239fb9aa6f1SThomas Gleixner */ 240fb9aa6f1SThomas Gleixner { 241fb9aa6f1SThomas Gleixner .callback = assign_all_busses, 242fb9aa6f1SThomas Gleixner .ident = "Samsung X20 Laptop", 243fb9aa6f1SThomas Gleixner .matches = { 244fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"), 245fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "SX20S"), 246fb9aa6f1SThomas Gleixner }, 247fb9aa6f1SThomas Gleixner }, 248fb9aa6f1SThomas Gleixner #endif /* __i386__ */ 249fb9aa6f1SThomas Gleixner { 250fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 251fb9aa6f1SThomas Gleixner .ident = "Dell PowerEdge 1950", 252fb9aa6f1SThomas Gleixner .matches = { 253fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Dell"), 254fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"), 255fb9aa6f1SThomas Gleixner }, 256fb9aa6f1SThomas Gleixner }, 257fb9aa6f1SThomas Gleixner { 258fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 259fb9aa6f1SThomas Gleixner .ident = "Dell PowerEdge 1955", 260fb9aa6f1SThomas Gleixner .matches = { 261fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Dell"), 262fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1955"), 263fb9aa6f1SThomas Gleixner }, 264fb9aa6f1SThomas Gleixner }, 265fb9aa6f1SThomas Gleixner { 266fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 267fb9aa6f1SThomas Gleixner .ident = "Dell PowerEdge 2900", 268fb9aa6f1SThomas Gleixner .matches = { 269fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Dell"), 270fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2900"), 271fb9aa6f1SThomas Gleixner }, 272fb9aa6f1SThomas Gleixner }, 273fb9aa6f1SThomas Gleixner { 274fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 275fb9aa6f1SThomas Gleixner .ident = "Dell PowerEdge 2950", 276fb9aa6f1SThomas Gleixner .matches = { 277fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Dell"), 278fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"), 279fb9aa6f1SThomas Gleixner }, 280fb9aa6f1SThomas Gleixner }, 281fb9aa6f1SThomas Gleixner { 282fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 283fb9aa6f1SThomas Gleixner .ident = "Dell PowerEdge R900", 284fb9aa6f1SThomas Gleixner .matches = { 285fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Dell"), 286fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R900"), 287fb9aa6f1SThomas Gleixner }, 288fb9aa6f1SThomas Gleixner }, 289fb9aa6f1SThomas Gleixner { 2909b373ed1SNarendra_K@Dell.com .callback = find_sort_method, 2919b373ed1SNarendra_K@Dell.com .ident = "Dell System", 2929b373ed1SNarendra_K@Dell.com .matches = { 2939b373ed1SNarendra_K@Dell.com DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 2949b373ed1SNarendra_K@Dell.com }, 2959b373ed1SNarendra_K@Dell.com }, 2969b373ed1SNarendra_K@Dell.com { 297fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 298fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL20p G3", 299fb9aa6f1SThomas Gleixner .matches = { 300fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"), 301fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G3"), 302fb9aa6f1SThomas Gleixner }, 303fb9aa6f1SThomas Gleixner }, 304fb9aa6f1SThomas Gleixner { 305fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 306fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL20p G4", 307fb9aa6f1SThomas Gleixner .matches = { 308fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"), 309fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G4"), 310fb9aa6f1SThomas Gleixner }, 311fb9aa6f1SThomas Gleixner }, 312fb9aa6f1SThomas Gleixner { 313fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 314fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL30p G1", 315fb9aa6f1SThomas Gleixner .matches = { 316fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"), 317fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL30p G1"), 318fb9aa6f1SThomas Gleixner }, 319fb9aa6f1SThomas Gleixner }, 320fb9aa6f1SThomas Gleixner { 321fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 322fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL25p G1", 323fb9aa6f1SThomas Gleixner .matches = { 324fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"), 325fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL25p G1"), 326fb9aa6f1SThomas Gleixner }, 327fb9aa6f1SThomas Gleixner }, 328fb9aa6f1SThomas Gleixner { 329fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 330fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL35p G1", 331fb9aa6f1SThomas Gleixner .matches = { 332fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"), 333fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL35p G1"), 334fb9aa6f1SThomas Gleixner }, 335fb9aa6f1SThomas Gleixner }, 336fb9aa6f1SThomas Gleixner { 337fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 338fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL45p G1", 339fb9aa6f1SThomas Gleixner .matches = { 340fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"), 341fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G1"), 342fb9aa6f1SThomas Gleixner }, 343fb9aa6f1SThomas Gleixner }, 344fb9aa6f1SThomas Gleixner { 345fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 346fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL45p G2", 347fb9aa6f1SThomas Gleixner .matches = { 348fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"), 349fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G2"), 350fb9aa6f1SThomas Gleixner }, 351fb9aa6f1SThomas Gleixner }, 352fb9aa6f1SThomas Gleixner { 353fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 354fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL460c G1", 355fb9aa6f1SThomas Gleixner .matches = { 356fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"), 357fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL460c G1"), 358fb9aa6f1SThomas Gleixner }, 359fb9aa6f1SThomas Gleixner }, 360fb9aa6f1SThomas Gleixner { 361fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 362fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL465c G1", 363fb9aa6f1SThomas Gleixner .matches = { 364fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"), 365fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL465c G1"), 366fb9aa6f1SThomas Gleixner }, 367fb9aa6f1SThomas Gleixner }, 368fb9aa6f1SThomas Gleixner { 369fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 370fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL480c G1", 371fb9aa6f1SThomas Gleixner .matches = { 372fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"), 373fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL480c G1"), 374fb9aa6f1SThomas Gleixner }, 375fb9aa6f1SThomas Gleixner }, 376fb9aa6f1SThomas Gleixner { 377fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 378fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL685c G1", 379fb9aa6f1SThomas Gleixner .matches = { 380fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"), 381fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"), 382fb9aa6f1SThomas Gleixner }, 383fb9aa6f1SThomas Gleixner }, 3848f8ae1a7SMichal Schmidt { 3858f8ae1a7SMichal Schmidt .callback = set_bf_sort, 3868d64c781STony Camuso .ident = "HP ProLiant DL360", 3878f8ae1a7SMichal Schmidt .matches = { 3888f8ae1a7SMichal Schmidt DMI_MATCH(DMI_SYS_VENDOR, "HP"), 3898d64c781STony Camuso DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL360"), 3908f8ae1a7SMichal Schmidt }, 3918f8ae1a7SMichal Schmidt }, 3928f8ae1a7SMichal Schmidt { 3938f8ae1a7SMichal Schmidt .callback = set_bf_sort, 3948d64c781STony Camuso .ident = "HP ProLiant DL380", 3958f8ae1a7SMichal Schmidt .matches = { 3968f8ae1a7SMichal Schmidt DMI_MATCH(DMI_SYS_VENDOR, "HP"), 3978d64c781STony Camuso DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL380"), 3988f8ae1a7SMichal Schmidt }, 3998f8ae1a7SMichal Schmidt }, 4005b1ea82fSJuha Laiho #ifdef __i386__ 4015b1ea82fSJuha Laiho { 4025b1ea82fSJuha Laiho .callback = assign_all_busses, 4035b1ea82fSJuha Laiho .ident = "Compaq EVO N800c", 4045b1ea82fSJuha Laiho .matches = { 4055b1ea82fSJuha Laiho DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), 4065b1ea82fSJuha Laiho DMI_MATCH(DMI_PRODUCT_NAME, "EVO N800c"), 4075b1ea82fSJuha Laiho }, 4085b1ea82fSJuha Laiho }, 4095b1ea82fSJuha Laiho #endif 410c82bc5adSMichal Schmidt { 411c82bc5adSMichal Schmidt .callback = set_bf_sort, 412739db07fSJesse Barnes .ident = "HP ProLiant DL385 G2", 413c82bc5adSMichal Schmidt .matches = { 414c82bc5adSMichal Schmidt DMI_MATCH(DMI_SYS_VENDOR, "HP"), 415739db07fSJesse Barnes DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL385 G2"), 416c82bc5adSMichal Schmidt }, 417c82bc5adSMichal Schmidt }, 418c82bc5adSMichal Schmidt { 419c82bc5adSMichal Schmidt .callback = set_bf_sort, 420739db07fSJesse Barnes .ident = "HP ProLiant DL585 G2", 421c82bc5adSMichal Schmidt .matches = { 422c82bc5adSMichal Schmidt DMI_MATCH(DMI_SYS_VENDOR, "HP"), 423739db07fSJesse Barnes DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"), 424c82bc5adSMichal Schmidt }, 425c82bc5adSMichal Schmidt }, 426284f5f9dSBjorn Helgaas { 427284f5f9dSBjorn Helgaas .callback = set_scan_all, 428284f5f9dSBjorn Helgaas .ident = "Stratus/NEC ftServer", 429284f5f9dSBjorn Helgaas .matches = { 4301278998fSMyron Stowe DMI_MATCH(DMI_SYS_VENDOR, "Stratus"), 4311278998fSMyron Stowe DMI_MATCH(DMI_PRODUCT_NAME, "ftServer"), 432284f5f9dSBjorn Helgaas }, 433284f5f9dSBjorn Helgaas }, 43451ac3d2fSCharlotte Richardson { 43551ac3d2fSCharlotte Richardson .callback = set_scan_all, 43651ac3d2fSCharlotte Richardson .ident = "Stratus/NEC ftServer", 43751ac3d2fSCharlotte Richardson .matches = { 43851ac3d2fSCharlotte Richardson DMI_MATCH(DMI_SYS_VENDOR, "NEC"), 43951ac3d2fSCharlotte Richardson DMI_MATCH(DMI_PRODUCT_NAME, "Express5800/R32"), 44051ac3d2fSCharlotte Richardson }, 44151ac3d2fSCharlotte Richardson }, 44251ac3d2fSCharlotte Richardson { 44351ac3d2fSCharlotte Richardson .callback = set_scan_all, 44451ac3d2fSCharlotte Richardson .ident = "Stratus/NEC ftServer", 44551ac3d2fSCharlotte Richardson .matches = { 44651ac3d2fSCharlotte Richardson DMI_MATCH(DMI_SYS_VENDOR, "NEC"), 44751ac3d2fSCharlotte Richardson DMI_MATCH(DMI_PRODUCT_NAME, "Express5800/R31"), 44851ac3d2fSCharlotte Richardson }, 44951ac3d2fSCharlotte Richardson }, 450fb9aa6f1SThomas Gleixner {} 451fb9aa6f1SThomas Gleixner }; 452fb9aa6f1SThomas Gleixner 4530df18ff3SYinghai Lu void __init dmi_check_pciprobe(void) 4540df18ff3SYinghai Lu { 4550df18ff3SYinghai Lu dmi_check_system(pciprobe_dmi_table); 4560df18ff3SYinghai Lu } 4570df18ff3SYinghai Lu 45849886cf4SBjorn Helgaas void pcibios_scan_root(int busnum) 459fb9aa6f1SThomas Gleixner { 460289a24a6SBjorn Helgaas struct pci_bus *bus; 461289a24a6SBjorn Helgaas struct pci_sysdata *sd; 462289a24a6SBjorn Helgaas LIST_HEAD(resources); 463289a24a6SBjorn Helgaas 464289a24a6SBjorn Helgaas sd = kzalloc(sizeof(*sd), GFP_KERNEL); 465289a24a6SBjorn Helgaas if (!sd) { 466289a24a6SBjorn Helgaas printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busnum); 46749886cf4SBjorn Helgaas return; 468289a24a6SBjorn Helgaas } 4696616dbdfSBjorn Helgaas sd->node = x86_pci_root_bus_node(busnum); 470289a24a6SBjorn Helgaas x86_pci_root_bus_resources(busnum, &resources); 471289a24a6SBjorn Helgaas printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum); 472289a24a6SBjorn Helgaas bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources); 473289a24a6SBjorn Helgaas if (!bus) { 474289a24a6SBjorn Helgaas pci_free_resource_list(&resources); 475289a24a6SBjorn Helgaas kfree(sd); 476b97ea289SYijing Wang return; 477289a24a6SBjorn Helgaas } 478b97ea289SYijing Wang pci_bus_add_devices(bus); 479fb9aa6f1SThomas Gleixner } 480fb9aa6f1SThomas Gleixner 48144de3395SAlex Nixon void __init pcibios_set_cache_line_size(void) 482fb9aa6f1SThomas Gleixner { 483fb9aa6f1SThomas Gleixner struct cpuinfo_x86 *c = &boot_cpu_data; 484fb9aa6f1SThomas Gleixner 485fb9aa6f1SThomas Gleixner /* 48676b1a87bSDave Jones * Set PCI cacheline size to that of the CPU if the CPU has reported it. 48776b1a87bSDave Jones * (For older CPUs that don't support cpuid, we se it to 32 bytes 48876b1a87bSDave Jones * It's also good for 386/486s (which actually have 16) 489fb9aa6f1SThomas Gleixner * as quite a few PCI devices do not support smaller values. 490fb9aa6f1SThomas Gleixner */ 49176b1a87bSDave Jones if (c->x86_clflush_size > 0) { 49276b1a87bSDave Jones pci_dfl_cache_line_size = c->x86_clflush_size >> 2; 49376b1a87bSDave Jones printk(KERN_DEBUG "PCI: pci_cache_line_size set to %d bytes\n", 49476b1a87bSDave Jones pci_dfl_cache_line_size << 2); 49576b1a87bSDave Jones } else { 496ac1aa47bSJesse Barnes pci_dfl_cache_line_size = 32 >> 2; 49776b1a87bSDave Jones printk(KERN_DEBUG "PCI: Unknown cacheline size. Setting to 32 bytes\n"); 49876b1a87bSDave Jones } 49944de3395SAlex Nixon } 500fb9aa6f1SThomas Gleixner 50144de3395SAlex Nixon int __init pcibios_init(void) 50244de3395SAlex Nixon { 50335a6ae07SAdrian-Ken Rueegsegger if (!raw_pci_ops && !raw_pci_ext_ops) { 50444de3395SAlex Nixon printk(KERN_WARNING "PCI: System does not support PCI\n"); 50544de3395SAlex Nixon return 0; 50644de3395SAlex Nixon } 50744de3395SAlex Nixon 50844de3395SAlex Nixon pcibios_set_cache_line_size(); 509fb9aa6f1SThomas Gleixner pcibios_resource_survey(); 510fb9aa6f1SThomas Gleixner 511fb9aa6f1SThomas Gleixner if (pci_bf_sort >= pci_force_bf) 512fb9aa6f1SThomas Gleixner pci_sort_breadthfirst(); 513fb9aa6f1SThomas Gleixner return 0; 514fb9aa6f1SThomas Gleixner } 515fb9aa6f1SThomas Gleixner 51615fa325bSMyron Stowe char *__init pcibios_setup(char *str) 517fb9aa6f1SThomas Gleixner { 518fb9aa6f1SThomas Gleixner if (!strcmp(str, "off")) { 519fb9aa6f1SThomas Gleixner pci_probe = 0; 520fb9aa6f1SThomas Gleixner return NULL; 521fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "bfsort")) { 522fb9aa6f1SThomas Gleixner pci_bf_sort = pci_force_bf; 523fb9aa6f1SThomas Gleixner return NULL; 524fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "nobfsort")) { 525fb9aa6f1SThomas Gleixner pci_bf_sort = pci_force_nobf; 526fb9aa6f1SThomas Gleixner return NULL; 527fb9aa6f1SThomas Gleixner } 528fb9aa6f1SThomas Gleixner #ifdef CONFIG_PCI_BIOS 529fb9aa6f1SThomas Gleixner else if (!strcmp(str, "bios")) { 530fb9aa6f1SThomas Gleixner pci_probe = PCI_PROBE_BIOS; 531fb9aa6f1SThomas Gleixner return NULL; 532fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "nobios")) { 533fb9aa6f1SThomas Gleixner pci_probe &= ~PCI_PROBE_BIOS; 534fb9aa6f1SThomas Gleixner return NULL; 535fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "biosirq")) { 536fb9aa6f1SThomas Gleixner pci_probe |= PCI_BIOS_IRQ_SCAN; 537fb9aa6f1SThomas Gleixner return NULL; 538fb9aa6f1SThomas Gleixner } else if (!strncmp(str, "pirqaddr=", 9)) { 539fb9aa6f1SThomas Gleixner pirq_table_addr = simple_strtoul(str+9, NULL, 0); 540fb9aa6f1SThomas Gleixner return NULL; 541fb9aa6f1SThomas Gleixner } 542fb9aa6f1SThomas Gleixner #endif 543fb9aa6f1SThomas Gleixner #ifdef CONFIG_PCI_DIRECT 544fb9aa6f1SThomas Gleixner else if (!strcmp(str, "conf1")) { 545fb9aa6f1SThomas Gleixner pci_probe = PCI_PROBE_CONF1 | PCI_NO_CHECKS; 546fb9aa6f1SThomas Gleixner return NULL; 547fb9aa6f1SThomas Gleixner } 548fb9aa6f1SThomas Gleixner else if (!strcmp(str, "conf2")) { 549fb9aa6f1SThomas Gleixner pci_probe = PCI_PROBE_CONF2 | PCI_NO_CHECKS; 550fb9aa6f1SThomas Gleixner return NULL; 551fb9aa6f1SThomas Gleixner } 552fb9aa6f1SThomas Gleixner #endif 553fb9aa6f1SThomas Gleixner #ifdef CONFIG_PCI_MMCONFIG 554fb9aa6f1SThomas Gleixner else if (!strcmp(str, "nommconf")) { 555fb9aa6f1SThomas Gleixner pci_probe &= ~PCI_PROBE_MMCONF; 556fb9aa6f1SThomas Gleixner return NULL; 557fb9aa6f1SThomas Gleixner } 5585f0b2976SYinghai Lu else if (!strcmp(str, "check_enable_amd_mmconf")) { 5595f0b2976SYinghai Lu pci_probe |= PCI_CHECK_ENABLE_AMD_MMCONF; 5605f0b2976SYinghai Lu return NULL; 5615f0b2976SYinghai Lu } 562fb9aa6f1SThomas Gleixner #endif 563fb9aa6f1SThomas Gleixner else if (!strcmp(str, "noacpi")) { 564fb9aa6f1SThomas Gleixner acpi_noirq_set(); 565fb9aa6f1SThomas Gleixner return NULL; 566fb9aa6f1SThomas Gleixner } 567fb9aa6f1SThomas Gleixner else if (!strcmp(str, "noearly")) { 568fb9aa6f1SThomas Gleixner pci_probe |= PCI_PROBE_NOEARLY; 569fb9aa6f1SThomas Gleixner return NULL; 570fb9aa6f1SThomas Gleixner } 571fb9aa6f1SThomas Gleixner else if (!strcmp(str, "usepirqmask")) { 572fb9aa6f1SThomas Gleixner pci_probe |= PCI_USE_PIRQ_MASK; 573fb9aa6f1SThomas Gleixner return NULL; 574fb9aa6f1SThomas Gleixner } else if (!strncmp(str, "irqmask=", 8)) { 575fb9aa6f1SThomas Gleixner pcibios_irq_mask = simple_strtol(str+8, NULL, 0); 576fb9aa6f1SThomas Gleixner return NULL; 577fb9aa6f1SThomas Gleixner } else if (!strncmp(str, "lastbus=", 8)) { 578fb9aa6f1SThomas Gleixner pcibios_last_bus = simple_strtol(str+8, NULL, 0); 579fb9aa6f1SThomas Gleixner return NULL; 580c5f9ee3dSH. Peter Anvin } else if (!strcmp(str, "rom")) { 581fb9aa6f1SThomas Gleixner pci_probe |= PCI_ASSIGN_ROMS; 582fb9aa6f1SThomas Gleixner return NULL; 583bb71ad88SGary Hade } else if (!strcmp(str, "norom")) { 584bb71ad88SGary Hade pci_probe |= PCI_NOASSIGN_ROMS; 585bb71ad88SGary Hade return NULL; 5867bd1c365SMike Habeck } else if (!strcmp(str, "nobar")) { 5877bd1c365SMike Habeck pci_probe |= PCI_NOASSIGN_BARS; 5887bd1c365SMike Habeck return NULL; 589fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "assign-busses")) { 590fb9aa6f1SThomas Gleixner pci_probe |= PCI_ASSIGN_ALL_BUSSES; 591fb9aa6f1SThomas Gleixner return NULL; 592236e946bSLinus Torvalds } else if (!strcmp(str, "use_crs")) { 593236e946bSLinus Torvalds pci_probe |= PCI_USE__CRS; 59462f420f8SGary Hade return NULL; 5957bc5e3f2SBjorn Helgaas } else if (!strcmp(str, "nocrs")) { 5967bc5e3f2SBjorn Helgaas pci_probe |= PCI_ROOT_NO_CRS; 5977bc5e3f2SBjorn Helgaas return NULL; 598f32ab754S=?UTF-8?q?Christian=20K=C3=B6nig?= #ifdef CONFIG_PHYS_ADDR_T_64BIT 599f32ab754S=?UTF-8?q?Christian=20K=C3=B6nig?= } else if (!strcmp(str, "big_root_window")) { 600f32ab754S=?UTF-8?q?Christian=20K=C3=B6nig?= pci_probe |= PCI_BIG_ROOT_WINDOW; 601f32ab754S=?UTF-8?q?Christian=20K=C3=B6nig?= return NULL; 602f32ab754S=?UTF-8?q?Christian=20K=C3=B6nig?= #endif 603fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "routeirq")) { 604fb9aa6f1SThomas Gleixner pci_routeirq = 1; 605fb9aa6f1SThomas Gleixner return NULL; 60613a6ddb0SYinghai Lu } else if (!strcmp(str, "skip_isa_align")) { 60713a6ddb0SYinghai Lu pci_probe |= PCI_CAN_SKIP_ISA_ALIGN; 60813a6ddb0SYinghai Lu return NULL; 609a9322f64SStefan Assmann } else if (!strcmp(str, "noioapicquirk")) { 610a9322f64SStefan Assmann noioapicquirk = 1; 611a9322f64SStefan Assmann return NULL; 6129197979bSStefan Assmann } else if (!strcmp(str, "ioapicreroute")) { 6139197979bSStefan Assmann if (noioapicreroute != -1) 6149197979bSStefan Assmann noioapicreroute = 0; 6159197979bSStefan Assmann return NULL; 61641b9eb26SStefan Assmann } else if (!strcmp(str, "noioapicreroute")) { 61741b9eb26SStefan Assmann if (noioapicreroute != -1) 61841b9eb26SStefan Assmann noioapicreroute = 1; 61941b9eb26SStefan Assmann return NULL; 620fb9aa6f1SThomas Gleixner } 621fb9aa6f1SThomas Gleixner return str; 622fb9aa6f1SThomas Gleixner } 623fb9aa6f1SThomas Gleixner 624fb9aa6f1SThomas Gleixner unsigned int pcibios_assign_all_busses(void) 625fb9aa6f1SThomas Gleixner { 626fb9aa6f1SThomas Gleixner return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0; 627fb9aa6f1SThomas Gleixner } 628fb9aa6f1SThomas Gleixner 6293161832dSKeith Busch static void set_dev_domain_options(struct pci_dev *pdev) 6303161832dSKeith Busch { 6313161832dSKeith Busch if (is_vmd(pdev->bus)) 6323161832dSKeith Busch pdev->hotplug_user_indicators = 1; 6333161832dSKeith Busch } 6343161832dSKeith Busch 635f9a37be0SMatthew Garrett int pcibios_add_device(struct pci_dev *dev) 636f9a37be0SMatthew Garrett { 637f9a37be0SMatthew Garrett struct pci_setup_rom *rom; 6382c681e6bSThomas Gleixner struct irq_domain *msidom; 6392c681e6bSThomas Gleixner struct setup_data *data; 640f9a37be0SMatthew Garrett u64 pa_data; 641f9a37be0SMatthew Garrett 642f9a37be0SMatthew Garrett pa_data = boot_params.hdr.setup_data; 643f9a37be0SMatthew Garrett while (pa_data) { 644f7750a79STom Lendacky data = memremap(pa_data, sizeof(*rom), MEMREMAP_WB); 64565694c5aSMatt Fleming if (!data) 64665694c5aSMatt Fleming return -ENOMEM; 647f9a37be0SMatthew Garrett 648f9a37be0SMatthew Garrett if (data->type == SETUP_PCI) { 649f9a37be0SMatthew Garrett rom = (struct pci_setup_rom *)data; 650f9a37be0SMatthew Garrett 651f9a37be0SMatthew Garrett if ((pci_domain_nr(dev->bus) == rom->segment) && 652f9a37be0SMatthew Garrett (dev->bus->number == rom->bus) && 653f9a37be0SMatthew Garrett (PCI_SLOT(dev->devfn) == rom->device) && 654f9a37be0SMatthew Garrett (PCI_FUNC(dev->devfn) == rom->function) && 655f9a37be0SMatthew Garrett (dev->vendor == rom->vendor) && 656f9a37be0SMatthew Garrett (dev->device == rom->devid)) { 657dbd3fc33SBjorn Helgaas dev->rom = pa_data + 658dbd3fc33SBjorn Helgaas offsetof(struct pci_setup_rom, romdata); 659f9a37be0SMatthew Garrett dev->romlen = rom->pcilen; 660f9a37be0SMatthew Garrett } 661f9a37be0SMatthew Garrett } 662f9a37be0SMatthew Garrett pa_data = data->next; 663f7750a79STom Lendacky memunmap(data); 664f9a37be0SMatthew Garrett } 6653161832dSKeith Busch set_dev_domain_options(dev); 6662c681e6bSThomas Gleixner 6672c681e6bSThomas Gleixner /* 6682c681e6bSThomas Gleixner * Setup the initial MSI domain of the device. If the underlying 6692c681e6bSThomas Gleixner * bus has a PCI/MSI irqdomain associated use the bus domain, 6702c681e6bSThomas Gleixner * otherwise set the default domain. This ensures that special irq 6712c681e6bSThomas Gleixner * domains e.g. VMD are preserved. The default ensures initial 6722c681e6bSThomas Gleixner * operation if irq remapping is not active. If irq remapping is 6732c681e6bSThomas Gleixner * active it will overwrite the domain pointer when the device is 6742c681e6bSThomas Gleixner * associated to a remapping domain. 6752c681e6bSThomas Gleixner */ 6762c681e6bSThomas Gleixner msidom = dev_get_msi_domain(&dev->bus->dev); 6772c681e6bSThomas Gleixner if (!msidom) 6782c681e6bSThomas Gleixner msidom = x86_pci_msi_default_domain; 6792c681e6bSThomas Gleixner dev_set_msi_domain(&dev->dev, msidom); 680f9a37be0SMatthew Garrett return 0; 681f9a37be0SMatthew Garrett } 682f9a37be0SMatthew Garrett 683991de2e5SJiang Liu int pcibios_enable_device(struct pci_dev *dev, int mask) 684991de2e5SJiang Liu { 6856c777e87SBjorn Helgaas int err; 6866c777e87SBjorn Helgaas 6876c777e87SBjorn Helgaas if ((err = pci_enable_resources(dev, mask)) < 0) 6886c777e87SBjorn Helgaas return err; 6896c777e87SBjorn Helgaas 6906c777e87SBjorn Helgaas if (!pci_dev_msi_enabled(dev)) 6916c777e87SBjorn Helgaas return pcibios_enable_irq(dev); 6926c777e87SBjorn Helgaas return 0; 6936c777e87SBjorn Helgaas } 6946c777e87SBjorn Helgaas 6956c777e87SBjorn Helgaas void pcibios_disable_device (struct pci_dev *dev) 6966c777e87SBjorn Helgaas { 6976c777e87SBjorn Helgaas if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq) 6986c777e87SBjorn Helgaas pcibios_disable_irq(dev); 699991de2e5SJiang Liu } 700991de2e5SJiang Liu 701153654dbSRui Wang #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC 702153654dbSRui Wang void pcibios_release_device(struct pci_dev *dev) 703153654dbSRui Wang { 704153654dbSRui Wang if (atomic_dec_return(&dev->enable_cnt) >= 0) 705153654dbSRui Wang pcibios_disable_device(dev); 706153654dbSRui Wang 707153654dbSRui Wang } 708153654dbSRui Wang #endif 709153654dbSRui Wang 710642c92daSTaku Izumi int pci_ext_cfg_avail(void) 7110ef5f8f6SAndrew Patterson { 7120ef5f8f6SAndrew Patterson if (raw_pci_ext_ops) 7130ef5f8f6SAndrew Patterson return 1; 7140ef5f8f6SAndrew Patterson else 7150ef5f8f6SAndrew Patterson return 0; 7160ef5f8f6SAndrew Patterson } 7172856ba60SJon Derrick 7182856ba60SJon Derrick #if IS_ENABLED(CONFIG_VMD) 7192856ba60SJon Derrick struct pci_dev *pci_real_dma_dev(struct pci_dev *dev) 7202856ba60SJon Derrick { 7212856ba60SJon Derrick if (is_vmd(dev->bus)) 7222856ba60SJon Derrick return to_pci_sysdata(dev->bus)->vmd_dev; 7232856ba60SJon Derrick 7242856ba60SJon Derrick return dev; 7252856ba60SJon Derrick } 7262856ba60SJon Derrick #endif 727