1 /* 2 * Low-Level PCI Support for PC 3 * 4 * (c) 1999--2000 Martin Mares <mj@ucw.cz> 5 */ 6 7 #include <linux/sched.h> 8 #include <linux/pci.h> 9 #include <linux/ioport.h> 10 #include <linux/init.h> 11 #include <linux/dmi.h> 12 #include <linux/slab.h> 13 14 #include <asm-generic/pci-bridge.h> 15 #include <asm/acpi.h> 16 #include <asm/segment.h> 17 #include <asm/io.h> 18 #include <asm/smp.h> 19 #include <asm/pci_x86.h> 20 21 unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | 22 PCI_PROBE_MMCONF; 23 24 unsigned int pci_early_dump_regs; 25 static int pci_bf_sort; 26 static int smbios_type_b1_flag; 27 int pci_routeirq; 28 int noioapicquirk; 29 #ifdef CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS 30 int noioapicreroute = 0; 31 #else 32 int noioapicreroute = 1; 33 #endif 34 int pcibios_last_bus = -1; 35 unsigned long pirq_table_addr; 36 struct pci_bus *pci_root_bus; 37 const struct pci_raw_ops *__read_mostly raw_pci_ops; 38 const struct pci_raw_ops *__read_mostly raw_pci_ext_ops; 39 40 int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn, 41 int reg, int len, u32 *val) 42 { 43 if (domain == 0 && reg < 256 && raw_pci_ops) 44 return raw_pci_ops->read(domain, bus, devfn, reg, len, val); 45 if (raw_pci_ext_ops) 46 return raw_pci_ext_ops->read(domain, bus, devfn, reg, len, val); 47 return -EINVAL; 48 } 49 50 int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn, 51 int reg, int len, u32 val) 52 { 53 if (domain == 0 && reg < 256 && raw_pci_ops) 54 return raw_pci_ops->write(domain, bus, devfn, reg, len, val); 55 if (raw_pci_ext_ops) 56 return raw_pci_ext_ops->write(domain, bus, devfn, reg, len, val); 57 return -EINVAL; 58 } 59 60 static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) 61 { 62 return raw_pci_read(pci_domain_nr(bus), bus->number, 63 devfn, where, size, value); 64 } 65 66 static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) 67 { 68 return raw_pci_write(pci_domain_nr(bus), bus->number, 69 devfn, where, size, value); 70 } 71 72 struct pci_ops pci_root_ops = { 73 .read = pci_read, 74 .write = pci_write, 75 }; 76 77 /* 78 * This interrupt-safe spinlock protects all accesses to PCI 79 * configuration space. 80 */ 81 DEFINE_RAW_SPINLOCK(pci_config_lock); 82 83 static int __devinit can_skip_ioresource_align(const struct dmi_system_id *d) 84 { 85 pci_probe |= PCI_CAN_SKIP_ISA_ALIGN; 86 printk(KERN_INFO "PCI: %s detected, can skip ISA alignment\n", d->ident); 87 return 0; 88 } 89 90 static const struct dmi_system_id can_skip_pciprobe_dmi_table[] __devinitconst = { 91 /* 92 * Systems where PCI IO resource ISA alignment can be skipped 93 * when the ISA enable bit in the bridge control is not set 94 */ 95 { 96 .callback = can_skip_ioresource_align, 97 .ident = "IBM System x3800", 98 .matches = { 99 DMI_MATCH(DMI_SYS_VENDOR, "IBM"), 100 DMI_MATCH(DMI_PRODUCT_NAME, "x3800"), 101 }, 102 }, 103 { 104 .callback = can_skip_ioresource_align, 105 .ident = "IBM System x3850", 106 .matches = { 107 DMI_MATCH(DMI_SYS_VENDOR, "IBM"), 108 DMI_MATCH(DMI_PRODUCT_NAME, "x3850"), 109 }, 110 }, 111 { 112 .callback = can_skip_ioresource_align, 113 .ident = "IBM System x3950", 114 .matches = { 115 DMI_MATCH(DMI_SYS_VENDOR, "IBM"), 116 DMI_MATCH(DMI_PRODUCT_NAME, "x3950"), 117 }, 118 }, 119 {} 120 }; 121 122 void __init dmi_check_skip_isa_align(void) 123 { 124 dmi_check_system(can_skip_pciprobe_dmi_table); 125 } 126 127 static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) 128 { 129 struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE]; 130 struct resource *bar_r; 131 int bar; 132 133 if (pci_probe & PCI_NOASSIGN_BARS) { 134 /* 135 * If the BIOS did not assign the BAR, zero out the 136 * resource so the kernel doesn't attmept to assign 137 * it later on in pci_assign_unassigned_resources 138 */ 139 for (bar = 0; bar <= PCI_STD_RESOURCE_END; bar++) { 140 bar_r = &dev->resource[bar]; 141 if (bar_r->start == 0 && bar_r->end != 0) { 142 bar_r->flags = 0; 143 bar_r->end = 0; 144 } 145 } 146 } 147 148 if (pci_probe & PCI_NOASSIGN_ROMS) { 149 if (rom_r->parent) 150 return; 151 if (rom_r->start) { 152 /* we deal with BIOS assigned ROM later */ 153 return; 154 } 155 rom_r->start = rom_r->end = rom_r->flags = 0; 156 } 157 } 158 159 /* 160 * Called after each bus is probed, but before its children 161 * are examined. 162 */ 163 164 void __devinit pcibios_fixup_bus(struct pci_bus *b) 165 { 166 struct pci_dev *dev; 167 168 pci_read_bridge_bases(b); 169 list_for_each_entry(dev, &b->devices, bus_list) 170 pcibios_fixup_device_resources(dev); 171 } 172 173 /* 174 * Only use DMI information to set this if nothing was passed 175 * on the kernel command line (which was parsed earlier). 176 */ 177 178 static int __devinit set_bf_sort(const struct dmi_system_id *d) 179 { 180 if (pci_bf_sort == pci_bf_sort_default) { 181 pci_bf_sort = pci_dmi_bf; 182 printk(KERN_INFO "PCI: %s detected, enabling pci=bfsort.\n", d->ident); 183 } 184 return 0; 185 } 186 187 static void __devinit read_dmi_type_b1(const struct dmi_header *dm, 188 void *private_data) 189 { 190 u8 *d = (u8 *)dm + 4; 191 192 if (dm->type != 0xB1) 193 return; 194 switch (((*(u32 *)d) >> 9) & 0x03) { 195 case 0x00: 196 printk(KERN_INFO "dmi type 0xB1 record - unknown flag\n"); 197 break; 198 case 0x01: /* set pci=bfsort */ 199 smbios_type_b1_flag = 1; 200 break; 201 case 0x02: /* do not set pci=bfsort */ 202 smbios_type_b1_flag = 2; 203 break; 204 default: 205 break; 206 } 207 } 208 209 static int __devinit find_sort_method(const struct dmi_system_id *d) 210 { 211 dmi_walk(read_dmi_type_b1, NULL); 212 213 if (smbios_type_b1_flag == 1) { 214 set_bf_sort(d); 215 return 0; 216 } 217 return -1; 218 } 219 220 /* 221 * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus) 222 */ 223 #ifdef __i386__ 224 static int __devinit assign_all_busses(const struct dmi_system_id *d) 225 { 226 pci_probe |= PCI_ASSIGN_ALL_BUSSES; 227 printk(KERN_INFO "%s detected: enabling PCI bus# renumbering" 228 " (pci=assign-busses)\n", d->ident); 229 return 0; 230 } 231 #endif 232 233 static int __devinit set_scan_all(const struct dmi_system_id *d) 234 { 235 printk(KERN_INFO "PCI: %s detected, enabling pci=pcie_scan_all\n", 236 d->ident); 237 pci_add_flags(PCI_SCAN_ALL_PCIE_DEVS); 238 return 0; 239 } 240 241 static const struct dmi_system_id __devinitconst pciprobe_dmi_table[] = { 242 #ifdef __i386__ 243 /* 244 * Laptops which need pci=assign-busses to see Cardbus cards 245 */ 246 { 247 .callback = assign_all_busses, 248 .ident = "Samsung X20 Laptop", 249 .matches = { 250 DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"), 251 DMI_MATCH(DMI_PRODUCT_NAME, "SX20S"), 252 }, 253 }, 254 #endif /* __i386__ */ 255 { 256 .callback = set_bf_sort, 257 .ident = "Dell PowerEdge 1950", 258 .matches = { 259 DMI_MATCH(DMI_SYS_VENDOR, "Dell"), 260 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"), 261 }, 262 }, 263 { 264 .callback = set_bf_sort, 265 .ident = "Dell PowerEdge 1955", 266 .matches = { 267 DMI_MATCH(DMI_SYS_VENDOR, "Dell"), 268 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1955"), 269 }, 270 }, 271 { 272 .callback = set_bf_sort, 273 .ident = "Dell PowerEdge 2900", 274 .matches = { 275 DMI_MATCH(DMI_SYS_VENDOR, "Dell"), 276 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2900"), 277 }, 278 }, 279 { 280 .callback = set_bf_sort, 281 .ident = "Dell PowerEdge 2950", 282 .matches = { 283 DMI_MATCH(DMI_SYS_VENDOR, "Dell"), 284 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"), 285 }, 286 }, 287 { 288 .callback = set_bf_sort, 289 .ident = "Dell PowerEdge R900", 290 .matches = { 291 DMI_MATCH(DMI_SYS_VENDOR, "Dell"), 292 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R900"), 293 }, 294 }, 295 { 296 .callback = find_sort_method, 297 .ident = "Dell System", 298 .matches = { 299 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 300 }, 301 }, 302 { 303 .callback = set_bf_sort, 304 .ident = "HP ProLiant BL20p G3", 305 .matches = { 306 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 307 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G3"), 308 }, 309 }, 310 { 311 .callback = set_bf_sort, 312 .ident = "HP ProLiant BL20p G4", 313 .matches = { 314 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 315 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G4"), 316 }, 317 }, 318 { 319 .callback = set_bf_sort, 320 .ident = "HP ProLiant BL30p G1", 321 .matches = { 322 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 323 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL30p G1"), 324 }, 325 }, 326 { 327 .callback = set_bf_sort, 328 .ident = "HP ProLiant BL25p G1", 329 .matches = { 330 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 331 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL25p G1"), 332 }, 333 }, 334 { 335 .callback = set_bf_sort, 336 .ident = "HP ProLiant BL35p G1", 337 .matches = { 338 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 339 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL35p G1"), 340 }, 341 }, 342 { 343 .callback = set_bf_sort, 344 .ident = "HP ProLiant BL45p G1", 345 .matches = { 346 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 347 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G1"), 348 }, 349 }, 350 { 351 .callback = set_bf_sort, 352 .ident = "HP ProLiant BL45p G2", 353 .matches = { 354 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 355 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G2"), 356 }, 357 }, 358 { 359 .callback = set_bf_sort, 360 .ident = "HP ProLiant BL460c G1", 361 .matches = { 362 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 363 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL460c G1"), 364 }, 365 }, 366 { 367 .callback = set_bf_sort, 368 .ident = "HP ProLiant BL465c G1", 369 .matches = { 370 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 371 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL465c G1"), 372 }, 373 }, 374 { 375 .callback = set_bf_sort, 376 .ident = "HP ProLiant BL480c G1", 377 .matches = { 378 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 379 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL480c G1"), 380 }, 381 }, 382 { 383 .callback = set_bf_sort, 384 .ident = "HP ProLiant BL685c G1", 385 .matches = { 386 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 387 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"), 388 }, 389 }, 390 { 391 .callback = set_bf_sort, 392 .ident = "HP ProLiant DL360", 393 .matches = { 394 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 395 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL360"), 396 }, 397 }, 398 { 399 .callback = set_bf_sort, 400 .ident = "HP ProLiant DL380", 401 .matches = { 402 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 403 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL380"), 404 }, 405 }, 406 #ifdef __i386__ 407 { 408 .callback = assign_all_busses, 409 .ident = "Compaq EVO N800c", 410 .matches = { 411 DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), 412 DMI_MATCH(DMI_PRODUCT_NAME, "EVO N800c"), 413 }, 414 }, 415 #endif 416 { 417 .callback = set_bf_sort, 418 .ident = "HP ProLiant DL385 G2", 419 .matches = { 420 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 421 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL385 G2"), 422 }, 423 }, 424 { 425 .callback = set_bf_sort, 426 .ident = "HP ProLiant DL585 G2", 427 .matches = { 428 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 429 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"), 430 }, 431 }, 432 { 433 .callback = set_scan_all, 434 .ident = "Stratus/NEC ftServer", 435 .matches = { 436 DMI_MATCH(DMI_SYS_VENDOR, "ftServer"), 437 }, 438 }, 439 {} 440 }; 441 442 void __init dmi_check_pciprobe(void) 443 { 444 dmi_check_system(pciprobe_dmi_table); 445 } 446 447 struct pci_bus * __devinit pcibios_scan_root(int busnum) 448 { 449 struct pci_bus *bus = NULL; 450 451 while ((bus = pci_find_next_bus(bus)) != NULL) { 452 if (bus->number == busnum) { 453 /* Already scanned */ 454 return bus; 455 } 456 } 457 458 return pci_scan_bus_on_node(busnum, &pci_root_ops, 459 get_mp_bus_to_node(busnum)); 460 } 461 462 void __init pcibios_set_cache_line_size(void) 463 { 464 struct cpuinfo_x86 *c = &boot_cpu_data; 465 466 /* 467 * Set PCI cacheline size to that of the CPU if the CPU has reported it. 468 * (For older CPUs that don't support cpuid, we se it to 32 bytes 469 * It's also good for 386/486s (which actually have 16) 470 * as quite a few PCI devices do not support smaller values. 471 */ 472 if (c->x86_clflush_size > 0) { 473 pci_dfl_cache_line_size = c->x86_clflush_size >> 2; 474 printk(KERN_DEBUG "PCI: pci_cache_line_size set to %d bytes\n", 475 pci_dfl_cache_line_size << 2); 476 } else { 477 pci_dfl_cache_line_size = 32 >> 2; 478 printk(KERN_DEBUG "PCI: Unknown cacheline size. Setting to 32 bytes\n"); 479 } 480 } 481 482 int __init pcibios_init(void) 483 { 484 if (!raw_pci_ops) { 485 printk(KERN_WARNING "PCI: System does not support PCI\n"); 486 return 0; 487 } 488 489 pcibios_set_cache_line_size(); 490 pcibios_resource_survey(); 491 492 if (pci_bf_sort >= pci_force_bf) 493 pci_sort_breadthfirst(); 494 return 0; 495 } 496 497 char * __init pcibios_setup(char *str) 498 { 499 if (!strcmp(str, "off")) { 500 pci_probe = 0; 501 return NULL; 502 } else if (!strcmp(str, "bfsort")) { 503 pci_bf_sort = pci_force_bf; 504 return NULL; 505 } else if (!strcmp(str, "nobfsort")) { 506 pci_bf_sort = pci_force_nobf; 507 return NULL; 508 } 509 #ifdef CONFIG_PCI_BIOS 510 else if (!strcmp(str, "bios")) { 511 pci_probe = PCI_PROBE_BIOS; 512 return NULL; 513 } else if (!strcmp(str, "nobios")) { 514 pci_probe &= ~PCI_PROBE_BIOS; 515 return NULL; 516 } else if (!strcmp(str, "biosirq")) { 517 pci_probe |= PCI_BIOS_IRQ_SCAN; 518 return NULL; 519 } else if (!strncmp(str, "pirqaddr=", 9)) { 520 pirq_table_addr = simple_strtoul(str+9, NULL, 0); 521 return NULL; 522 } 523 #endif 524 #ifdef CONFIG_PCI_DIRECT 525 else if (!strcmp(str, "conf1")) { 526 pci_probe = PCI_PROBE_CONF1 | PCI_NO_CHECKS; 527 return NULL; 528 } 529 else if (!strcmp(str, "conf2")) { 530 pci_probe = PCI_PROBE_CONF2 | PCI_NO_CHECKS; 531 return NULL; 532 } 533 #endif 534 #ifdef CONFIG_PCI_MMCONFIG 535 else if (!strcmp(str, "nommconf")) { 536 pci_probe &= ~PCI_PROBE_MMCONF; 537 return NULL; 538 } 539 else if (!strcmp(str, "check_enable_amd_mmconf")) { 540 pci_probe |= PCI_CHECK_ENABLE_AMD_MMCONF; 541 return NULL; 542 } 543 #endif 544 else if (!strcmp(str, "noacpi")) { 545 acpi_noirq_set(); 546 return NULL; 547 } 548 else if (!strcmp(str, "noearly")) { 549 pci_probe |= PCI_PROBE_NOEARLY; 550 return NULL; 551 } 552 #ifndef CONFIG_X86_VISWS 553 else if (!strcmp(str, "usepirqmask")) { 554 pci_probe |= PCI_USE_PIRQ_MASK; 555 return NULL; 556 } else if (!strncmp(str, "irqmask=", 8)) { 557 pcibios_irq_mask = simple_strtol(str+8, NULL, 0); 558 return NULL; 559 } else if (!strncmp(str, "lastbus=", 8)) { 560 pcibios_last_bus = simple_strtol(str+8, NULL, 0); 561 return NULL; 562 } 563 #endif 564 else if (!strcmp(str, "rom")) { 565 pci_probe |= PCI_ASSIGN_ROMS; 566 return NULL; 567 } else if (!strcmp(str, "norom")) { 568 pci_probe |= PCI_NOASSIGN_ROMS; 569 return NULL; 570 } else if (!strcmp(str, "nobar")) { 571 pci_probe |= PCI_NOASSIGN_BARS; 572 return NULL; 573 } else if (!strcmp(str, "assign-busses")) { 574 pci_probe |= PCI_ASSIGN_ALL_BUSSES; 575 return NULL; 576 } else if (!strcmp(str, "use_crs")) { 577 pci_probe |= PCI_USE__CRS; 578 return NULL; 579 } else if (!strcmp(str, "nocrs")) { 580 pci_probe |= PCI_ROOT_NO_CRS; 581 return NULL; 582 } else if (!strcmp(str, "earlydump")) { 583 pci_early_dump_regs = 1; 584 return NULL; 585 } else if (!strcmp(str, "routeirq")) { 586 pci_routeirq = 1; 587 return NULL; 588 } else if (!strcmp(str, "skip_isa_align")) { 589 pci_probe |= PCI_CAN_SKIP_ISA_ALIGN; 590 return NULL; 591 } else if (!strcmp(str, "noioapicquirk")) { 592 noioapicquirk = 1; 593 return NULL; 594 } else if (!strcmp(str, "ioapicreroute")) { 595 if (noioapicreroute != -1) 596 noioapicreroute = 0; 597 return NULL; 598 } else if (!strcmp(str, "noioapicreroute")) { 599 if (noioapicreroute != -1) 600 noioapicreroute = 1; 601 return NULL; 602 } 603 return str; 604 } 605 606 unsigned int pcibios_assign_all_busses(void) 607 { 608 return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0; 609 } 610 611 int pcibios_enable_device(struct pci_dev *dev, int mask) 612 { 613 int err; 614 615 if ((err = pci_enable_resources(dev, mask)) < 0) 616 return err; 617 618 if (!pci_dev_msi_enabled(dev)) 619 return pcibios_enable_irq(dev); 620 return 0; 621 } 622 623 void pcibios_disable_device (struct pci_dev *dev) 624 { 625 if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq) 626 pcibios_disable_irq(dev); 627 } 628 629 int pci_ext_cfg_avail(struct pci_dev *dev) 630 { 631 if (raw_pci_ext_ops) 632 return 1; 633 else 634 return 0; 635 } 636 637 struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node) 638 { 639 LIST_HEAD(resources); 640 struct pci_bus *bus = NULL; 641 struct pci_sysdata *sd; 642 643 /* 644 * Allocate per-root-bus (not per bus) arch-specific data. 645 * TODO: leak; this memory is never freed. 646 * It's arguable whether it's worth the trouble to care. 647 */ 648 sd = kzalloc(sizeof(*sd), GFP_KERNEL); 649 if (!sd) { 650 printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busno); 651 return NULL; 652 } 653 sd->node = node; 654 x86_pci_root_bus_resources(busno, &resources); 655 printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busno); 656 bus = pci_scan_root_bus(NULL, busno, ops, sd, &resources); 657 if (!bus) { 658 pci_free_resource_list(&resources); 659 kfree(sd); 660 } 661 662 return bus; 663 } 664 665 struct pci_bus * __devinit pci_scan_bus_with_sysdata(int busno) 666 { 667 return pci_scan_bus_on_node(busno, &pci_root_ops, -1); 668 } 669 670 /* 671 * NUMA info for PCI busses 672 * 673 * Early arch code is responsible for filling in reasonable values here. 674 * A node id of "-1" means "use current node". In other words, if a bus 675 * has a -1 node id, it's not tightly coupled to any particular chunk 676 * of memory (as is the case on some Nehalem systems). 677 */ 678 #ifdef CONFIG_NUMA 679 680 #define BUS_NR 256 681 682 #ifdef CONFIG_X86_64 683 684 static int mp_bus_to_node[BUS_NR] = { 685 [0 ... BUS_NR - 1] = -1 686 }; 687 688 void set_mp_bus_to_node(int busnum, int node) 689 { 690 if (busnum >= 0 && busnum < BUS_NR) 691 mp_bus_to_node[busnum] = node; 692 } 693 694 int get_mp_bus_to_node(int busnum) 695 { 696 int node = -1; 697 698 if (busnum < 0 || busnum > (BUS_NR - 1)) 699 return node; 700 701 node = mp_bus_to_node[busnum]; 702 703 /* 704 * let numa_node_id to decide it later in dma_alloc_pages 705 * if there is no ram on that node 706 */ 707 if (node != -1 && !node_online(node)) 708 node = -1; 709 710 return node; 711 } 712 713 #else /* CONFIG_X86_32 */ 714 715 static int mp_bus_to_node[BUS_NR] = { 716 [0 ... BUS_NR - 1] = -1 717 }; 718 719 void set_mp_bus_to_node(int busnum, int node) 720 { 721 if (busnum >= 0 && busnum < BUS_NR) 722 mp_bus_to_node[busnum] = (unsigned char) node; 723 } 724 725 int get_mp_bus_to_node(int busnum) 726 { 727 int node; 728 729 if (busnum < 0 || busnum > (BUS_NR - 1)) 730 return 0; 731 node = mp_bus_to_node[busnum]; 732 return node; 733 } 734 735 #endif /* CONFIG_X86_32 */ 736 737 #endif /* CONFIG_NUMA */ 738