1fb9aa6f1SThomas Gleixner /* 2fb9aa6f1SThomas Gleixner * Low-Level PCI Support for PC 3fb9aa6f1SThomas Gleixner * 4fb9aa6f1SThomas Gleixner * (c) 1999--2000 Martin Mares <mj@ucw.cz> 5fb9aa6f1SThomas Gleixner */ 6fb9aa6f1SThomas Gleixner 7fb9aa6f1SThomas Gleixner #include <linux/sched.h> 8fb9aa6f1SThomas Gleixner #include <linux/pci.h> 9fb9aa6f1SThomas Gleixner #include <linux/ioport.h> 10fb9aa6f1SThomas Gleixner #include <linux/init.h> 11fb9aa6f1SThomas Gleixner #include <linux/dmi.h> 125a0e3ad6STejun Heo #include <linux/slab.h> 13fb9aa6f1SThomas Gleixner 14fb9aa6f1SThomas Gleixner #include <asm/acpi.h> 15fb9aa6f1SThomas Gleixner #include <asm/segment.h> 16fb9aa6f1SThomas Gleixner #include <asm/io.h> 17fb9aa6f1SThomas Gleixner #include <asm/smp.h> 1882487711SJaswinder Singh Rajput #include <asm/pci_x86.h> 19fb9aa6f1SThomas Gleixner 20fb9aa6f1SThomas Gleixner unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | 21fb9aa6f1SThomas Gleixner PCI_PROBE_MMCONF; 22fb9aa6f1SThomas Gleixner 23e3f2baebSYinghai Lu unsigned int pci_early_dump_regs; 24fb9aa6f1SThomas Gleixner static int pci_bf_sort; 256e8af08dSNarendra_K@Dell.com static int smbios_type_b1_flag; 26fb9aa6f1SThomas Gleixner int pci_routeirq; 27a9322f64SStefan Assmann int noioapicquirk; 2841b9eb26SStefan Assmann #ifdef CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS 2941b9eb26SStefan Assmann int noioapicreroute = 0; 3041b9eb26SStefan Assmann #else 319197979bSStefan Assmann int noioapicreroute = 1; 3241b9eb26SStefan Assmann #endif 33fb9aa6f1SThomas Gleixner int pcibios_last_bus = -1; 34fb9aa6f1SThomas Gleixner unsigned long pirq_table_addr; 35fb9aa6f1SThomas Gleixner struct pci_bus *pci_root_bus; 36fb9aa6f1SThomas Gleixner struct pci_raw_ops *raw_pci_ops; 37b6ce068aSMatthew Wilcox struct pci_raw_ops *raw_pci_ext_ops; 38b6ce068aSMatthew Wilcox 39b6ce068aSMatthew Wilcox int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn, 40b6ce068aSMatthew Wilcox int reg, int len, u32 *val) 41b6ce068aSMatthew Wilcox { 42beef3129SMatthew Wilcox if (domain == 0 && reg < 256 && raw_pci_ops) 43b6ce068aSMatthew Wilcox return raw_pci_ops->read(domain, bus, devfn, reg, len, val); 44b6ce068aSMatthew Wilcox if (raw_pci_ext_ops) 45b6ce068aSMatthew Wilcox return raw_pci_ext_ops->read(domain, bus, devfn, reg, len, val); 46b6ce068aSMatthew Wilcox return -EINVAL; 47b6ce068aSMatthew Wilcox } 48b6ce068aSMatthew Wilcox 49b6ce068aSMatthew Wilcox int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn, 50b6ce068aSMatthew Wilcox int reg, int len, u32 val) 51b6ce068aSMatthew Wilcox { 52beef3129SMatthew Wilcox if (domain == 0 && reg < 256 && raw_pci_ops) 53b6ce068aSMatthew Wilcox return raw_pci_ops->write(domain, bus, devfn, reg, len, val); 54b6ce068aSMatthew Wilcox if (raw_pci_ext_ops) 55b6ce068aSMatthew Wilcox return raw_pci_ext_ops->write(domain, bus, devfn, reg, len, val); 56b6ce068aSMatthew Wilcox return -EINVAL; 57b6ce068aSMatthew Wilcox } 58fb9aa6f1SThomas Gleixner 59fb9aa6f1SThomas Gleixner static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) 60fb9aa6f1SThomas Gleixner { 61b6ce068aSMatthew Wilcox return raw_pci_read(pci_domain_nr(bus), bus->number, 62a79e4198SJeff Garzik devfn, where, size, value); 63fb9aa6f1SThomas Gleixner } 64fb9aa6f1SThomas Gleixner 65fb9aa6f1SThomas Gleixner static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) 66fb9aa6f1SThomas Gleixner { 67b6ce068aSMatthew Wilcox return raw_pci_write(pci_domain_nr(bus), bus->number, 68a79e4198SJeff Garzik devfn, where, size, value); 69fb9aa6f1SThomas Gleixner } 70fb9aa6f1SThomas Gleixner 71fb9aa6f1SThomas Gleixner struct pci_ops pci_root_ops = { 72fb9aa6f1SThomas Gleixner .read = pci_read, 73fb9aa6f1SThomas Gleixner .write = pci_write, 74fb9aa6f1SThomas Gleixner }; 75fb9aa6f1SThomas Gleixner 76fb9aa6f1SThomas Gleixner /* 77fb9aa6f1SThomas Gleixner * This interrupt-safe spinlock protects all accesses to PCI 78fb9aa6f1SThomas Gleixner * configuration space. 79fb9aa6f1SThomas Gleixner */ 80d19f61f0SThomas Gleixner DEFINE_RAW_SPINLOCK(pci_config_lock); 81fb9aa6f1SThomas Gleixner 8213a6ddb0SYinghai Lu static int __devinit can_skip_ioresource_align(const struct dmi_system_id *d) 8313a6ddb0SYinghai Lu { 8413a6ddb0SYinghai Lu pci_probe |= PCI_CAN_SKIP_ISA_ALIGN; 8513a6ddb0SYinghai Lu printk(KERN_INFO "PCI: %s detected, can skip ISA alignment\n", d->ident); 8613a6ddb0SYinghai Lu return 0; 8713a6ddb0SYinghai Lu } 8813a6ddb0SYinghai Lu 89821508d4SJan Beulich static const struct dmi_system_id can_skip_pciprobe_dmi_table[] __devinitconst = { 9013a6ddb0SYinghai Lu /* 9113a6ddb0SYinghai Lu * Systems where PCI IO resource ISA alignment can be skipped 9213a6ddb0SYinghai Lu * when the ISA enable bit in the bridge control is not set 9313a6ddb0SYinghai Lu */ 9413a6ddb0SYinghai Lu { 9513a6ddb0SYinghai Lu .callback = can_skip_ioresource_align, 9613a6ddb0SYinghai Lu .ident = "IBM System x3800", 9713a6ddb0SYinghai Lu .matches = { 9813a6ddb0SYinghai Lu DMI_MATCH(DMI_SYS_VENDOR, "IBM"), 9913a6ddb0SYinghai Lu DMI_MATCH(DMI_PRODUCT_NAME, "x3800"), 10013a6ddb0SYinghai Lu }, 10113a6ddb0SYinghai Lu }, 10213a6ddb0SYinghai Lu { 10313a6ddb0SYinghai Lu .callback = can_skip_ioresource_align, 10413a6ddb0SYinghai Lu .ident = "IBM System x3850", 10513a6ddb0SYinghai Lu .matches = { 10613a6ddb0SYinghai Lu DMI_MATCH(DMI_SYS_VENDOR, "IBM"), 10713a6ddb0SYinghai Lu DMI_MATCH(DMI_PRODUCT_NAME, "x3850"), 10813a6ddb0SYinghai Lu }, 10913a6ddb0SYinghai Lu }, 11013a6ddb0SYinghai Lu { 11113a6ddb0SYinghai Lu .callback = can_skip_ioresource_align, 11213a6ddb0SYinghai Lu .ident = "IBM System x3950", 11313a6ddb0SYinghai Lu .matches = { 11413a6ddb0SYinghai Lu DMI_MATCH(DMI_SYS_VENDOR, "IBM"), 11513a6ddb0SYinghai Lu DMI_MATCH(DMI_PRODUCT_NAME, "x3950"), 11613a6ddb0SYinghai Lu }, 11713a6ddb0SYinghai Lu }, 11813a6ddb0SYinghai Lu {} 11913a6ddb0SYinghai Lu }; 12013a6ddb0SYinghai Lu 12113a6ddb0SYinghai Lu void __init dmi_check_skip_isa_align(void) 12213a6ddb0SYinghai Lu { 12313a6ddb0SYinghai Lu dmi_check_system(can_skip_pciprobe_dmi_table); 12413a6ddb0SYinghai Lu } 12513a6ddb0SYinghai Lu 126bb71ad88SGary Hade static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) 127bb71ad88SGary Hade { 128bb71ad88SGary Hade struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE]; 1297bd1c365SMike Habeck struct resource *bar_r; 1307bd1c365SMike Habeck int bar; 1317bd1c365SMike Habeck 1327bd1c365SMike Habeck if (pci_probe & PCI_NOASSIGN_BARS) { 1337bd1c365SMike Habeck /* 1347bd1c365SMike Habeck * If the BIOS did not assign the BAR, zero out the 1357bd1c365SMike Habeck * resource so the kernel doesn't attmept to assign 1367bd1c365SMike Habeck * it later on in pci_assign_unassigned_resources 1377bd1c365SMike Habeck */ 1387bd1c365SMike Habeck for (bar = 0; bar <= PCI_STD_RESOURCE_END; bar++) { 1397bd1c365SMike Habeck bar_r = &dev->resource[bar]; 1407bd1c365SMike Habeck if (bar_r->start == 0 && bar_r->end != 0) { 1417bd1c365SMike Habeck bar_r->flags = 0; 1427bd1c365SMike Habeck bar_r->end = 0; 1437bd1c365SMike Habeck } 1447bd1c365SMike Habeck } 1457bd1c365SMike Habeck } 146bb71ad88SGary Hade 147bb71ad88SGary Hade if (pci_probe & PCI_NOASSIGN_ROMS) { 148bb71ad88SGary Hade if (rom_r->parent) 149bb71ad88SGary Hade return; 150bb71ad88SGary Hade if (rom_r->start) { 151bb71ad88SGary Hade /* we deal with BIOS assigned ROM later */ 152bb71ad88SGary Hade return; 153bb71ad88SGary Hade } 154bb71ad88SGary Hade rom_r->start = rom_r->end = rom_r->flags = 0; 155bb71ad88SGary Hade } 156bb71ad88SGary Hade } 157bb71ad88SGary Hade 158fb9aa6f1SThomas Gleixner /* 159fb9aa6f1SThomas Gleixner * Called after each bus is probed, but before its children 160fb9aa6f1SThomas Gleixner * are examined. 161fb9aa6f1SThomas Gleixner */ 162fb9aa6f1SThomas Gleixner 163fb9aa6f1SThomas Gleixner void __devinit pcibios_fixup_bus(struct pci_bus *b) 164fb9aa6f1SThomas Gleixner { 165bb71ad88SGary Hade struct pci_dev *dev; 166bb71ad88SGary Hade 1670e94ecd0SYinghai Lu /* root bus? */ 1680e94ecd0SYinghai Lu if (!b->parent) 1690e94ecd0SYinghai Lu x86_pci_root_bus_res_quirks(b); 170fb9aa6f1SThomas Gleixner pci_read_bridge_bases(b); 171bb71ad88SGary Hade list_for_each_entry(dev, &b->devices, bus_list) 172bb71ad88SGary Hade pcibios_fixup_device_resources(dev); 173fb9aa6f1SThomas Gleixner } 174fb9aa6f1SThomas Gleixner 175fb9aa6f1SThomas Gleixner /* 176fb9aa6f1SThomas Gleixner * Only use DMI information to set this if nothing was passed 177fb9aa6f1SThomas Gleixner * on the kernel command line (which was parsed earlier). 178fb9aa6f1SThomas Gleixner */ 179fb9aa6f1SThomas Gleixner 18019ad7ae4SLinus Torvalds static int __devinit set_bf_sort(const struct dmi_system_id *d) 181fb9aa6f1SThomas Gleixner { 182fb9aa6f1SThomas Gleixner if (pci_bf_sort == pci_bf_sort_default) { 183fb9aa6f1SThomas Gleixner pci_bf_sort = pci_dmi_bf; 184fb9aa6f1SThomas Gleixner printk(KERN_INFO "PCI: %s detected, enabling pci=bfsort.\n", d->ident); 185fb9aa6f1SThomas Gleixner } 186fb9aa6f1SThomas Gleixner return 0; 187fb9aa6f1SThomas Gleixner } 188fb9aa6f1SThomas Gleixner 1896e8af08dSNarendra_K@Dell.com static void __devinit read_dmi_type_b1(const struct dmi_header *dm, 1906e8af08dSNarendra_K@Dell.com void *private_data) 1916e8af08dSNarendra_K@Dell.com { 1926e8af08dSNarendra_K@Dell.com u8 *d = (u8 *)dm + 4; 1936e8af08dSNarendra_K@Dell.com 1946e8af08dSNarendra_K@Dell.com if (dm->type != 0xB1) 1956e8af08dSNarendra_K@Dell.com return; 1966e8af08dSNarendra_K@Dell.com switch (((*(u32 *)d) >> 9) & 0x03) { 1976e8af08dSNarendra_K@Dell.com case 0x00: 1986e8af08dSNarendra_K@Dell.com printk(KERN_INFO "dmi type 0xB1 record - unknown flag\n"); 1996e8af08dSNarendra_K@Dell.com break; 2006e8af08dSNarendra_K@Dell.com case 0x01: /* set pci=bfsort */ 2016e8af08dSNarendra_K@Dell.com smbios_type_b1_flag = 1; 2026e8af08dSNarendra_K@Dell.com break; 2036e8af08dSNarendra_K@Dell.com case 0x02: /* do not set pci=bfsort */ 2046e8af08dSNarendra_K@Dell.com smbios_type_b1_flag = 2; 2056e8af08dSNarendra_K@Dell.com break; 2066e8af08dSNarendra_K@Dell.com default: 2076e8af08dSNarendra_K@Dell.com break; 2086e8af08dSNarendra_K@Dell.com } 2096e8af08dSNarendra_K@Dell.com } 2106e8af08dSNarendra_K@Dell.com 2116e8af08dSNarendra_K@Dell.com static int __devinit find_sort_method(const struct dmi_system_id *d) 2126e8af08dSNarendra_K@Dell.com { 2136e8af08dSNarendra_K@Dell.com dmi_walk(read_dmi_type_b1, NULL); 2146e8af08dSNarendra_K@Dell.com 2156e8af08dSNarendra_K@Dell.com if (smbios_type_b1_flag == 1) { 2166e8af08dSNarendra_K@Dell.com set_bf_sort(d); 2176e8af08dSNarendra_K@Dell.com return 0; 2186e8af08dSNarendra_K@Dell.com } 2196e8af08dSNarendra_K@Dell.com return -1; 2206e8af08dSNarendra_K@Dell.com } 2216e8af08dSNarendra_K@Dell.com 222fb9aa6f1SThomas Gleixner /* 223fb9aa6f1SThomas Gleixner * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus) 224fb9aa6f1SThomas Gleixner */ 225fb9aa6f1SThomas Gleixner #ifdef __i386__ 22619ad7ae4SLinus Torvalds static int __devinit assign_all_busses(const struct dmi_system_id *d) 227fb9aa6f1SThomas Gleixner { 228fb9aa6f1SThomas Gleixner pci_probe |= PCI_ASSIGN_ALL_BUSSES; 229fb9aa6f1SThomas Gleixner printk(KERN_INFO "%s detected: enabling PCI bus# renumbering" 230fb9aa6f1SThomas Gleixner " (pci=assign-busses)\n", d->ident); 231fb9aa6f1SThomas Gleixner return 0; 232fb9aa6f1SThomas Gleixner } 233fb9aa6f1SThomas Gleixner #endif 234fb9aa6f1SThomas Gleixner 235821508d4SJan Beulich static const struct dmi_system_id __devinitconst pciprobe_dmi_table[] = { 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 { 2506e8af08dSNarendra_K@Dell.com .callback = find_sort_method, 2516e8af08dSNarendra_K@Dell.com .ident = "Dell System", 2526e8af08dSNarendra_K@Dell.com .matches = { 2536e8af08dSNarendra_K@Dell.com DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 2546e8af08dSNarendra_K@Dell.com }, 2556e8af08dSNarendra_K@Dell.com }, 2566e8af08dSNarendra_K@Dell.com { 257fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 258fb9aa6f1SThomas Gleixner .ident = "Dell PowerEdge 1950", 259fb9aa6f1SThomas Gleixner .matches = { 260fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Dell"), 261fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"), 262fb9aa6f1SThomas Gleixner }, 263fb9aa6f1SThomas Gleixner }, 264fb9aa6f1SThomas Gleixner { 265fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 266fb9aa6f1SThomas Gleixner .ident = "Dell PowerEdge 1955", 267fb9aa6f1SThomas Gleixner .matches = { 268fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Dell"), 269fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1955"), 270fb9aa6f1SThomas Gleixner }, 271fb9aa6f1SThomas Gleixner }, 272fb9aa6f1SThomas Gleixner { 273fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 274fb9aa6f1SThomas Gleixner .ident = "Dell PowerEdge 2900", 275fb9aa6f1SThomas Gleixner .matches = { 276fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Dell"), 277fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2900"), 278fb9aa6f1SThomas Gleixner }, 279fb9aa6f1SThomas Gleixner }, 280fb9aa6f1SThomas Gleixner { 281fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 282fb9aa6f1SThomas Gleixner .ident = "Dell PowerEdge 2950", 283fb9aa6f1SThomas Gleixner .matches = { 284fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Dell"), 285fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"), 286fb9aa6f1SThomas Gleixner }, 287fb9aa6f1SThomas Gleixner }, 288fb9aa6f1SThomas Gleixner { 289fb9aa6f1SThomas Gleixner .callback = set_bf_sort, 290fb9aa6f1SThomas Gleixner .ident = "Dell PowerEdge R900", 291fb9aa6f1SThomas Gleixner .matches = { 292fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Dell"), 293fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R900"), 294fb9aa6f1SThomas Gleixner }, 295fb9aa6f1SThomas Gleixner }, 296fb9aa6f1SThomas Gleixner { 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 }, 426fb9aa6f1SThomas Gleixner {} 427fb9aa6f1SThomas Gleixner }; 428fb9aa6f1SThomas Gleixner 4290df18ff3SYinghai Lu void __init dmi_check_pciprobe(void) 4300df18ff3SYinghai Lu { 4310df18ff3SYinghai Lu dmi_check_system(pciprobe_dmi_table); 4320df18ff3SYinghai Lu } 4330df18ff3SYinghai Lu 434fb9aa6f1SThomas Gleixner struct pci_bus * __devinit pcibios_scan_root(int busnum) 435fb9aa6f1SThomas Gleixner { 436fb9aa6f1SThomas Gleixner struct pci_bus *bus = NULL; 437fb9aa6f1SThomas Gleixner struct pci_sysdata *sd; 438fb9aa6f1SThomas Gleixner 439fb9aa6f1SThomas Gleixner while ((bus = pci_find_next_bus(bus)) != NULL) { 440fb9aa6f1SThomas Gleixner if (bus->number == busnum) { 441fb9aa6f1SThomas Gleixner /* Already scanned */ 442fb9aa6f1SThomas Gleixner return bus; 443fb9aa6f1SThomas Gleixner } 444fb9aa6f1SThomas Gleixner } 445fb9aa6f1SThomas Gleixner 446fb9aa6f1SThomas Gleixner /* Allocate per-root-bus (not per bus) arch-specific data. 447fb9aa6f1SThomas Gleixner * TODO: leak; this memory is never freed. 448fb9aa6f1SThomas Gleixner * It's arguable whether it's worth the trouble to care. 449fb9aa6f1SThomas Gleixner */ 450fb9aa6f1SThomas Gleixner sd = kzalloc(sizeof(*sd), GFP_KERNEL); 451fb9aa6f1SThomas Gleixner if (!sd) { 452fb9aa6f1SThomas Gleixner printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum); 453fb9aa6f1SThomas Gleixner return NULL; 454fb9aa6f1SThomas Gleixner } 455fb9aa6f1SThomas Gleixner 456871d5f8dSYinghai Lu sd->node = get_mp_bus_to_node(busnum); 457fb9aa6f1SThomas Gleixner 458871d5f8dSYinghai Lu printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum); 459871d5f8dSYinghai Lu bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd); 460871d5f8dSYinghai Lu if (!bus) 461871d5f8dSYinghai Lu kfree(sd); 462871d5f8dSYinghai Lu 463871d5f8dSYinghai Lu return bus; 464fb9aa6f1SThomas Gleixner } 46544de3395SAlex Nixon void __init pcibios_set_cache_line_size(void) 466fb9aa6f1SThomas Gleixner { 467fb9aa6f1SThomas Gleixner struct cpuinfo_x86 *c = &boot_cpu_data; 468fb9aa6f1SThomas Gleixner 469fb9aa6f1SThomas Gleixner /* 47076b1a87bSDave Jones * Set PCI cacheline size to that of the CPU if the CPU has reported it. 47176b1a87bSDave Jones * (For older CPUs that don't support cpuid, we se it to 32 bytes 47276b1a87bSDave Jones * It's also good for 386/486s (which actually have 16) 473fb9aa6f1SThomas Gleixner * as quite a few PCI devices do not support smaller values. 474fb9aa6f1SThomas Gleixner */ 47576b1a87bSDave Jones if (c->x86_clflush_size > 0) { 47676b1a87bSDave Jones pci_dfl_cache_line_size = c->x86_clflush_size >> 2; 47776b1a87bSDave Jones printk(KERN_DEBUG "PCI: pci_cache_line_size set to %d bytes\n", 47876b1a87bSDave Jones pci_dfl_cache_line_size << 2); 47976b1a87bSDave Jones } else { 480ac1aa47bSJesse Barnes pci_dfl_cache_line_size = 32 >> 2; 48176b1a87bSDave Jones printk(KERN_DEBUG "PCI: Unknown cacheline size. Setting to 32 bytes\n"); 48276b1a87bSDave Jones } 48344de3395SAlex Nixon } 484fb9aa6f1SThomas Gleixner 48544de3395SAlex Nixon int __init pcibios_init(void) 48644de3395SAlex Nixon { 48744de3395SAlex Nixon if (!raw_pci_ops) { 48844de3395SAlex Nixon printk(KERN_WARNING "PCI: System does not support PCI\n"); 48944de3395SAlex Nixon return 0; 49044de3395SAlex Nixon } 49144de3395SAlex Nixon 49244de3395SAlex Nixon pcibios_set_cache_line_size(); 493fb9aa6f1SThomas Gleixner pcibios_resource_survey(); 494fb9aa6f1SThomas Gleixner 495fb9aa6f1SThomas Gleixner if (pci_bf_sort >= pci_force_bf) 496fb9aa6f1SThomas Gleixner pci_sort_breadthfirst(); 497fb9aa6f1SThomas Gleixner return 0; 498fb9aa6f1SThomas Gleixner } 499fb9aa6f1SThomas Gleixner 500fb9aa6f1SThomas Gleixner char * __devinit pcibios_setup(char *str) 501fb9aa6f1SThomas Gleixner { 502fb9aa6f1SThomas Gleixner if (!strcmp(str, "off")) { 503fb9aa6f1SThomas Gleixner pci_probe = 0; 504fb9aa6f1SThomas Gleixner return NULL; 505fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "bfsort")) { 506fb9aa6f1SThomas Gleixner pci_bf_sort = pci_force_bf; 507fb9aa6f1SThomas Gleixner return NULL; 508fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "nobfsort")) { 509fb9aa6f1SThomas Gleixner pci_bf_sort = pci_force_nobf; 510fb9aa6f1SThomas Gleixner return NULL; 511fb9aa6f1SThomas Gleixner } 512fb9aa6f1SThomas Gleixner #ifdef CONFIG_PCI_BIOS 513fb9aa6f1SThomas Gleixner else if (!strcmp(str, "bios")) { 514fb9aa6f1SThomas Gleixner pci_probe = PCI_PROBE_BIOS; 515fb9aa6f1SThomas Gleixner return NULL; 516fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "nobios")) { 517fb9aa6f1SThomas Gleixner pci_probe &= ~PCI_PROBE_BIOS; 518fb9aa6f1SThomas Gleixner return NULL; 519fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "biosirq")) { 520fb9aa6f1SThomas Gleixner pci_probe |= PCI_BIOS_IRQ_SCAN; 521fb9aa6f1SThomas Gleixner return NULL; 522fb9aa6f1SThomas Gleixner } else if (!strncmp(str, "pirqaddr=", 9)) { 523fb9aa6f1SThomas Gleixner pirq_table_addr = simple_strtoul(str+9, NULL, 0); 524fb9aa6f1SThomas Gleixner return NULL; 525fb9aa6f1SThomas Gleixner } 526fb9aa6f1SThomas Gleixner #endif 527fb9aa6f1SThomas Gleixner #ifdef CONFIG_PCI_DIRECT 528fb9aa6f1SThomas Gleixner else if (!strcmp(str, "conf1")) { 529fb9aa6f1SThomas Gleixner pci_probe = PCI_PROBE_CONF1 | PCI_NO_CHECKS; 530fb9aa6f1SThomas Gleixner return NULL; 531fb9aa6f1SThomas Gleixner } 532fb9aa6f1SThomas Gleixner else if (!strcmp(str, "conf2")) { 533fb9aa6f1SThomas Gleixner pci_probe = PCI_PROBE_CONF2 | PCI_NO_CHECKS; 534fb9aa6f1SThomas Gleixner return NULL; 535fb9aa6f1SThomas Gleixner } 536fb9aa6f1SThomas Gleixner #endif 537fb9aa6f1SThomas Gleixner #ifdef CONFIG_PCI_MMCONFIG 538fb9aa6f1SThomas Gleixner else if (!strcmp(str, "nommconf")) { 539fb9aa6f1SThomas Gleixner pci_probe &= ~PCI_PROBE_MMCONF; 540fb9aa6f1SThomas Gleixner return NULL; 541fb9aa6f1SThomas Gleixner } 5425f0b2976SYinghai Lu else if (!strcmp(str, "check_enable_amd_mmconf")) { 5435f0b2976SYinghai Lu pci_probe |= PCI_CHECK_ENABLE_AMD_MMCONF; 5445f0b2976SYinghai Lu return NULL; 5455f0b2976SYinghai Lu } 546fb9aa6f1SThomas Gleixner #endif 547fb9aa6f1SThomas Gleixner else if (!strcmp(str, "noacpi")) { 548fb9aa6f1SThomas Gleixner acpi_noirq_set(); 549fb9aa6f1SThomas Gleixner return NULL; 550fb9aa6f1SThomas Gleixner } 551fb9aa6f1SThomas Gleixner else if (!strcmp(str, "noearly")) { 552fb9aa6f1SThomas Gleixner pci_probe |= PCI_PROBE_NOEARLY; 553fb9aa6f1SThomas Gleixner return NULL; 554fb9aa6f1SThomas Gleixner } 555fb9aa6f1SThomas Gleixner #ifndef CONFIG_X86_VISWS 556fb9aa6f1SThomas Gleixner else if (!strcmp(str, "usepirqmask")) { 557fb9aa6f1SThomas Gleixner pci_probe |= PCI_USE_PIRQ_MASK; 558fb9aa6f1SThomas Gleixner return NULL; 559fb9aa6f1SThomas Gleixner } else if (!strncmp(str, "irqmask=", 8)) { 560fb9aa6f1SThomas Gleixner pcibios_irq_mask = simple_strtol(str+8, NULL, 0); 561fb9aa6f1SThomas Gleixner return NULL; 562fb9aa6f1SThomas Gleixner } else if (!strncmp(str, "lastbus=", 8)) { 563fb9aa6f1SThomas Gleixner pcibios_last_bus = simple_strtol(str+8, NULL, 0); 564fb9aa6f1SThomas Gleixner return NULL; 565fb9aa6f1SThomas Gleixner } 566fb9aa6f1SThomas Gleixner #endif 567fb9aa6f1SThomas Gleixner else if (!strcmp(str, "rom")) { 568fb9aa6f1SThomas Gleixner pci_probe |= PCI_ASSIGN_ROMS; 569fb9aa6f1SThomas Gleixner return NULL; 570bb71ad88SGary Hade } else if (!strcmp(str, "norom")) { 571bb71ad88SGary Hade pci_probe |= PCI_NOASSIGN_ROMS; 572bb71ad88SGary Hade return NULL; 5737bd1c365SMike Habeck } else if (!strcmp(str, "nobar")) { 5747bd1c365SMike Habeck pci_probe |= PCI_NOASSIGN_BARS; 5757bd1c365SMike Habeck return NULL; 576fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "assign-busses")) { 577fb9aa6f1SThomas Gleixner pci_probe |= PCI_ASSIGN_ALL_BUSSES; 578fb9aa6f1SThomas Gleixner return NULL; 579236e946bSLinus Torvalds } else if (!strcmp(str, "use_crs")) { 580236e946bSLinus Torvalds pci_probe |= PCI_USE__CRS; 58162f420f8SGary Hade return NULL; 5827bc5e3f2SBjorn Helgaas } else if (!strcmp(str, "nocrs")) { 5837bc5e3f2SBjorn Helgaas pci_probe |= PCI_ROOT_NO_CRS; 5847bc5e3f2SBjorn Helgaas return NULL; 585e3f2baebSYinghai Lu } else if (!strcmp(str, "earlydump")) { 586e3f2baebSYinghai Lu pci_early_dump_regs = 1; 587e3f2baebSYinghai Lu return NULL; 588fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "routeirq")) { 589fb9aa6f1SThomas Gleixner pci_routeirq = 1; 590fb9aa6f1SThomas Gleixner return NULL; 59113a6ddb0SYinghai Lu } else if (!strcmp(str, "skip_isa_align")) { 59213a6ddb0SYinghai Lu pci_probe |= PCI_CAN_SKIP_ISA_ALIGN; 59313a6ddb0SYinghai Lu return NULL; 594a9322f64SStefan Assmann } else if (!strcmp(str, "noioapicquirk")) { 595a9322f64SStefan Assmann noioapicquirk = 1; 596a9322f64SStefan Assmann return NULL; 5979197979bSStefan Assmann } else if (!strcmp(str, "ioapicreroute")) { 5989197979bSStefan Assmann if (noioapicreroute != -1) 5999197979bSStefan Assmann noioapicreroute = 0; 6009197979bSStefan Assmann return NULL; 60141b9eb26SStefan Assmann } else if (!strcmp(str, "noioapicreroute")) { 60241b9eb26SStefan Assmann if (noioapicreroute != -1) 60341b9eb26SStefan Assmann noioapicreroute = 1; 60441b9eb26SStefan Assmann return NULL; 605fb9aa6f1SThomas Gleixner } 606fb9aa6f1SThomas Gleixner return str; 607fb9aa6f1SThomas Gleixner } 608fb9aa6f1SThomas Gleixner 609fb9aa6f1SThomas Gleixner unsigned int pcibios_assign_all_busses(void) 610fb9aa6f1SThomas Gleixner { 611fb9aa6f1SThomas Gleixner return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0; 612fb9aa6f1SThomas Gleixner } 613fb9aa6f1SThomas Gleixner 614fb9aa6f1SThomas Gleixner int pcibios_enable_device(struct pci_dev *dev, int mask) 615fb9aa6f1SThomas Gleixner { 616fb9aa6f1SThomas Gleixner int err; 617fb9aa6f1SThomas Gleixner 618b81d988cSBjorn Helgaas if ((err = pci_enable_resources(dev, mask)) < 0) 619fb9aa6f1SThomas Gleixner return err; 620fb9aa6f1SThomas Gleixner 62116cf0ebcSRafael J. Wysocki if (!pci_dev_msi_enabled(dev)) 622fb9aa6f1SThomas Gleixner return pcibios_enable_irq(dev); 623fb9aa6f1SThomas Gleixner return 0; 624fb9aa6f1SThomas Gleixner } 625fb9aa6f1SThomas Gleixner 626fb9aa6f1SThomas Gleixner void pcibios_disable_device (struct pci_dev *dev) 627fb9aa6f1SThomas Gleixner { 62816cf0ebcSRafael J. Wysocki if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq) 629fb9aa6f1SThomas Gleixner pcibios_disable_irq(dev); 630fb9aa6f1SThomas Gleixner } 631fb9aa6f1SThomas Gleixner 6320ef5f8f6SAndrew Patterson int pci_ext_cfg_avail(struct pci_dev *dev) 6330ef5f8f6SAndrew Patterson { 6340ef5f8f6SAndrew Patterson if (raw_pci_ext_ops) 6350ef5f8f6SAndrew Patterson return 1; 6360ef5f8f6SAndrew Patterson else 6370ef5f8f6SAndrew Patterson return 0; 6380ef5f8f6SAndrew Patterson } 6390ef5f8f6SAndrew Patterson 64098db6f19SSam Ravnborg struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node) 641fb9aa6f1SThomas Gleixner { 642fb9aa6f1SThomas Gleixner struct pci_bus *bus = NULL; 643fb9aa6f1SThomas Gleixner struct pci_sysdata *sd; 644fb9aa6f1SThomas Gleixner 645fb9aa6f1SThomas Gleixner /* 646fb9aa6f1SThomas Gleixner * Allocate per-root-bus (not per bus) arch-specific data. 647fb9aa6f1SThomas Gleixner * TODO: leak; this memory is never freed. 648fb9aa6f1SThomas Gleixner * It's arguable whether it's worth the trouble to care. 649fb9aa6f1SThomas Gleixner */ 650fb9aa6f1SThomas Gleixner sd = kzalloc(sizeof(*sd), GFP_KERNEL); 651fb9aa6f1SThomas Gleixner if (!sd) { 652fb9aa6f1SThomas Gleixner printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busno); 653fb9aa6f1SThomas Gleixner return NULL; 654fb9aa6f1SThomas Gleixner } 655871d5f8dSYinghai Lu sd->node = node; 656871d5f8dSYinghai Lu bus = pci_scan_bus(busno, ops, sd); 657fb9aa6f1SThomas Gleixner if (!bus) 658fb9aa6f1SThomas Gleixner kfree(sd); 659fb9aa6f1SThomas Gleixner 660fb9aa6f1SThomas Gleixner return bus; 661fb9aa6f1SThomas Gleixner } 662871d5f8dSYinghai Lu 66398db6f19SSam Ravnborg struct pci_bus * __devinit pci_scan_bus_with_sysdata(int busno) 664871d5f8dSYinghai Lu { 665871d5f8dSYinghai Lu return pci_scan_bus_on_node(busno, &pci_root_ops, -1); 666871d5f8dSYinghai Lu } 6672547089cSJesse Barnes 6682547089cSJesse Barnes /* 6692547089cSJesse Barnes * NUMA info for PCI busses 6702547089cSJesse Barnes * 6712547089cSJesse Barnes * Early arch code is responsible for filling in reasonable values here. 6722547089cSJesse Barnes * A node id of "-1" means "use current node". In other words, if a bus 6732547089cSJesse Barnes * has a -1 node id, it's not tightly coupled to any particular chunk 6742547089cSJesse Barnes * of memory (as is the case on some Nehalem systems). 6752547089cSJesse Barnes */ 6762547089cSJesse Barnes #ifdef CONFIG_NUMA 6772547089cSJesse Barnes 6782547089cSJesse Barnes #define BUS_NR 256 6792547089cSJesse Barnes 6802547089cSJesse Barnes #ifdef CONFIG_X86_64 6812547089cSJesse Barnes 6822547089cSJesse Barnes static int mp_bus_to_node[BUS_NR] = { 6832547089cSJesse Barnes [0 ... BUS_NR - 1] = -1 6842547089cSJesse Barnes }; 6852547089cSJesse Barnes 6862547089cSJesse Barnes void set_mp_bus_to_node(int busnum, int node) 6872547089cSJesse Barnes { 6882547089cSJesse Barnes if (busnum >= 0 && busnum < BUS_NR) 6892547089cSJesse Barnes mp_bus_to_node[busnum] = node; 6902547089cSJesse Barnes } 6912547089cSJesse Barnes 6922547089cSJesse Barnes int get_mp_bus_to_node(int busnum) 6932547089cSJesse Barnes { 6942547089cSJesse Barnes int node = -1; 6952547089cSJesse Barnes 6962547089cSJesse Barnes if (busnum < 0 || busnum > (BUS_NR - 1)) 6972547089cSJesse Barnes return node; 6982547089cSJesse Barnes 6992547089cSJesse Barnes node = mp_bus_to_node[busnum]; 7002547089cSJesse Barnes 7012547089cSJesse Barnes /* 7022547089cSJesse Barnes * let numa_node_id to decide it later in dma_alloc_pages 7032547089cSJesse Barnes * if there is no ram on that node 7042547089cSJesse Barnes */ 7052547089cSJesse Barnes if (node != -1 && !node_online(node)) 7062547089cSJesse Barnes node = -1; 7072547089cSJesse Barnes 7082547089cSJesse Barnes return node; 7092547089cSJesse Barnes } 7102547089cSJesse Barnes 7112547089cSJesse Barnes #else /* CONFIG_X86_32 */ 7122547089cSJesse Barnes 71376baeebfSJesse Barnes static int mp_bus_to_node[BUS_NR] = { 7142547089cSJesse Barnes [0 ... BUS_NR - 1] = -1 7152547089cSJesse Barnes }; 7162547089cSJesse Barnes 7172547089cSJesse Barnes void set_mp_bus_to_node(int busnum, int node) 7182547089cSJesse Barnes { 7192547089cSJesse Barnes if (busnum >= 0 && busnum < BUS_NR) 7202547089cSJesse Barnes mp_bus_to_node[busnum] = (unsigned char) node; 7212547089cSJesse Barnes } 7222547089cSJesse Barnes 7232547089cSJesse Barnes int get_mp_bus_to_node(int busnum) 7242547089cSJesse Barnes { 7252547089cSJesse Barnes int node; 7262547089cSJesse Barnes 7272547089cSJesse Barnes if (busnum < 0 || busnum > (BUS_NR - 1)) 7282547089cSJesse Barnes return 0; 7292547089cSJesse Barnes node = mp_bus_to_node[busnum]; 7302547089cSJesse Barnes return node; 7312547089cSJesse Barnes } 7322547089cSJesse Barnes 7332547089cSJesse Barnes #endif /* CONFIG_X86_32 */ 7342547089cSJesse Barnes 7352547089cSJesse Barnes #endif /* CONFIG_NUMA */ 736