diff options
Diffstat (limited to 'arch/x86/pci')
-rw-r--r-- | arch/x86/pci/Makefile | 3 | ||||
-rw-r--r-- | arch/x86/pci/acpi.c | 59 | ||||
-rw-r--r-- | arch/x86/pci/amd_bus.c | 10 | ||||
-rw-r--r-- | arch/x86/pci/bus_numa.c | 13 | ||||
-rw-r--r-- | arch/x86/pci/common.c | 133 | ||||
-rw-r--r-- | arch/x86/pci/fixup.c | 24 | ||||
-rw-r--r-- | arch/x86/pci/irq.c | 6 | ||||
-rw-r--r-- | arch/x86/pci/legacy.c | 4 | ||||
-rw-r--r-- | arch/x86/pci/numaq_32.c | 165 | ||||
-rw-r--r-- | arch/x86/pci/visws.c | 87 | ||||
-rw-r--r-- | arch/x86/pci/xen.c | 29 |
11 files changed, 80 insertions, 453 deletions
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile index e063eed0f912..5c6fc3577a49 100644 --- a/arch/x86/pci/Makefile +++ b/arch/x86/pci/Makefile | |||
@@ -13,9 +13,6 @@ obj-y += legacy.o irq.o | |||
13 | 13 | ||
14 | obj-$(CONFIG_STA2X11) += sta2x11-fixup.o | 14 | obj-$(CONFIG_STA2X11) += sta2x11-fixup.o |
15 | 15 | ||
16 | obj-$(CONFIG_X86_VISWS) += visws.o | ||
17 | |||
18 | obj-$(CONFIG_X86_NUMAQ) += numaq_32.o | ||
19 | obj-$(CONFIG_X86_NUMACHIP) += numachip.o | 16 | obj-$(CONFIG_X86_NUMACHIP) += numachip.o |
20 | 17 | ||
21 | obj-$(CONFIG_X86_INTEL_MID) += intel_mid_pci.o | 18 | obj-$(CONFIG_X86_INTEL_MID) += intel_mid_pci.o |
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 4f25ec077552..01edac6c5e18 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c | |||
@@ -218,9 +218,8 @@ static void teardown_mcfg_map(struct pci_root_info *info) | |||
218 | } | 218 | } |
219 | #endif | 219 | #endif |
220 | 220 | ||
221 | static acpi_status | 221 | static acpi_status resource_to_addr(struct acpi_resource *resource, |
222 | resource_to_addr(struct acpi_resource *resource, | 222 | struct acpi_resource_address64 *addr) |
223 | struct acpi_resource_address64 *addr) | ||
224 | { | 223 | { |
225 | acpi_status status; | 224 | acpi_status status; |
226 | struct acpi_resource_memory24 *memory24; | 225 | struct acpi_resource_memory24 *memory24; |
@@ -265,8 +264,7 @@ resource_to_addr(struct acpi_resource *resource, | |||
265 | return AE_ERROR; | 264 | return AE_ERROR; |
266 | } | 265 | } |
267 | 266 | ||
268 | static acpi_status | 267 | static acpi_status count_resource(struct acpi_resource *acpi_res, void *data) |
269 | count_resource(struct acpi_resource *acpi_res, void *data) | ||
270 | { | 268 | { |
271 | struct pci_root_info *info = data; | 269 | struct pci_root_info *info = data; |
272 | struct acpi_resource_address64 addr; | 270 | struct acpi_resource_address64 addr; |
@@ -278,8 +276,7 @@ count_resource(struct acpi_resource *acpi_res, void *data) | |||
278 | return AE_OK; | 276 | return AE_OK; |
279 | } | 277 | } |
280 | 278 | ||
281 | static acpi_status | 279 | static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data) |
282 | setup_resource(struct acpi_resource *acpi_res, void *data) | ||
283 | { | 280 | { |
284 | struct pci_root_info *info = data; | 281 | struct pci_root_info *info = data; |
285 | struct resource *res; | 282 | struct resource *res; |
@@ -435,9 +432,9 @@ static void release_pci_root_info(struct pci_host_bridge *bridge) | |||
435 | __release_pci_root_info(info); | 432 | __release_pci_root_info(info); |
436 | } | 433 | } |
437 | 434 | ||
438 | static void | 435 | static void probe_pci_root_info(struct pci_root_info *info, |
439 | probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device, | 436 | struct acpi_device *device, |
440 | int busnum, int domain) | 437 | int busnum, int domain) |
441 | { | 438 | { |
442 | size_t size; | 439 | size_t size; |
443 | 440 | ||
@@ -473,16 +470,13 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device, | |||
473 | struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) | 470 | struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) |
474 | { | 471 | { |
475 | struct acpi_device *device = root->device; | 472 | struct acpi_device *device = root->device; |
476 | struct pci_root_info *info = NULL; | 473 | struct pci_root_info *info; |
477 | int domain = root->segment; | 474 | int domain = root->segment; |
478 | int busnum = root->secondary.start; | 475 | int busnum = root->secondary.start; |
479 | LIST_HEAD(resources); | 476 | LIST_HEAD(resources); |
480 | struct pci_bus *bus = NULL; | 477 | struct pci_bus *bus; |
481 | struct pci_sysdata *sd; | 478 | struct pci_sysdata *sd; |
482 | int node; | 479 | int node; |
483 | #ifdef CONFIG_ACPI_NUMA | ||
484 | int pxm; | ||
485 | #endif | ||
486 | 480 | ||
487 | if (pci_ignore_seg) | 481 | if (pci_ignore_seg) |
488 | domain = 0; | 482 | domain = 0; |
@@ -494,19 +488,12 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) | |||
494 | return NULL; | 488 | return NULL; |
495 | } | 489 | } |
496 | 490 | ||
497 | node = -1; | 491 | node = acpi_get_node(device->handle); |
498 | #ifdef CONFIG_ACPI_NUMA | 492 | if (node == NUMA_NO_NODE) |
499 | pxm = acpi_get_pxm(device->handle); | 493 | node = x86_pci_root_bus_node(busnum); |
500 | if (pxm >= 0) | ||
501 | node = pxm_to_node(pxm); | ||
502 | if (node != -1) | ||
503 | set_mp_bus_to_node(busnum, node); | ||
504 | else | ||
505 | #endif | ||
506 | node = get_mp_bus_to_node(busnum); | ||
507 | 494 | ||
508 | if (node != -1 && !node_online(node)) | 495 | if (node != NUMA_NO_NODE && !node_online(node)) |
509 | node = -1; | 496 | node = NUMA_NO_NODE; |
510 | 497 | ||
511 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 498 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
512 | if (!info) { | 499 | if (!info) { |
@@ -519,15 +506,12 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) | |||
519 | sd->domain = domain; | 506 | sd->domain = domain; |
520 | sd->node = node; | 507 | sd->node = node; |
521 | sd->companion = device; | 508 | sd->companion = device; |
522 | /* | 509 | |
523 | * Maybe the desired pci bus has been already scanned. In such case | ||
524 | * it is unnecessary to scan the pci bus with the given domain,busnum. | ||
525 | */ | ||
526 | bus = pci_find_bus(domain, busnum); | 510 | bus = pci_find_bus(domain, busnum); |
527 | if (bus) { | 511 | if (bus) { |
528 | /* | 512 | /* |
529 | * If the desired bus exits, the content of bus->sysdata will | 513 | * If the desired bus has been scanned already, replace |
530 | * be replaced by sd. | 514 | * its bus->sysdata. |
531 | */ | 515 | */ |
532 | memcpy(bus->sysdata, sd, sizeof(*sd)); | 516 | memcpy(bus->sysdata, sd, sizeof(*sd)); |
533 | kfree(info); | 517 | kfree(info); |
@@ -572,15 +556,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) | |||
572 | pcie_bus_configure_settings(child); | 556 | pcie_bus_configure_settings(child); |
573 | } | 557 | } |
574 | 558 | ||
575 | if (bus && node != -1) { | 559 | if (bus && node != NUMA_NO_NODE) |
576 | #ifdef CONFIG_ACPI_NUMA | ||
577 | if (pxm >= 0) | ||
578 | dev_printk(KERN_DEBUG, &bus->dev, | ||
579 | "on NUMA node %d (pxm %d)\n", node, pxm); | ||
580 | #else | ||
581 | dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node); | 560 | dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node); |
582 | #endif | ||
583 | } | ||
584 | 561 | ||
585 | return bus; | 562 | return bus; |
586 | } | 563 | } |
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index a48be98e9ded..a313a7fb6b86 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c | |||
@@ -44,15 +44,6 @@ static struct pci_root_info __init *find_pci_root_info(int node, int link) | |||
44 | return NULL; | 44 | return NULL; |
45 | } | 45 | } |
46 | 46 | ||
47 | static void __init set_mp_bus_range_to_node(int min_bus, int max_bus, int node) | ||
48 | { | ||
49 | #ifdef CONFIG_NUMA | ||
50 | int j; | ||
51 | |||
52 | for (j = min_bus; j <= max_bus; j++) | ||
53 | set_mp_bus_to_node(j, node); | ||
54 | #endif | ||
55 | } | ||
56 | /** | 47 | /** |
57 | * early_fill_mp_bus_to_node() | 48 | * early_fill_mp_bus_to_node() |
58 | * called before pcibios_scan_root and pci_scan_bus | 49 | * called before pcibios_scan_root and pci_scan_bus |
@@ -117,7 +108,6 @@ static int __init early_fill_mp_bus_info(void) | |||
117 | min_bus = (reg >> 16) & 0xff; | 108 | min_bus = (reg >> 16) & 0xff; |
118 | max_bus = (reg >> 24) & 0xff; | 109 | max_bus = (reg >> 24) & 0xff; |
119 | node = (reg >> 4) & 0x07; | 110 | node = (reg >> 4) & 0x07; |
120 | set_mp_bus_range_to_node(min_bus, max_bus, node); | ||
121 | link = (reg >> 8) & 0x03; | 111 | link = (reg >> 8) & 0x03; |
122 | 112 | ||
123 | info = alloc_pci_root_info(min_bus, max_bus, node, link); | 113 | info = alloc_pci_root_info(min_bus, max_bus, node, link); |
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c index c2735feb2508..f3a2cfc14125 100644 --- a/arch/x86/pci/bus_numa.c +++ b/arch/x86/pci/bus_numa.c | |||
@@ -10,9 +10,6 @@ static struct pci_root_info *x86_find_pci_root_info(int bus) | |||
10 | { | 10 | { |
11 | struct pci_root_info *info; | 11 | struct pci_root_info *info; |
12 | 12 | ||
13 | if (list_empty(&pci_root_infos)) | ||
14 | return NULL; | ||
15 | |||
16 | list_for_each_entry(info, &pci_root_infos, list) | 13 | list_for_each_entry(info, &pci_root_infos, list) |
17 | if (info->busn.start == bus) | 14 | if (info->busn.start == bus) |
18 | return info; | 15 | return info; |
@@ -20,6 +17,16 @@ static struct pci_root_info *x86_find_pci_root_info(int bus) | |||
20 | return NULL; | 17 | return NULL; |
21 | } | 18 | } |
22 | 19 | ||
20 | int x86_pci_root_bus_node(int bus) | ||
21 | { | ||
22 | struct pci_root_info *info = x86_find_pci_root_info(bus); | ||
23 | |||
24 | if (!info) | ||
25 | return NUMA_NO_NODE; | ||
26 | |||
27 | return info->node; | ||
28 | } | ||
29 | |||
23 | void x86_pci_root_bus_resources(int bus, struct list_head *resources) | 30 | void x86_pci_root_bus_resources(int bus, struct list_head *resources) |
24 | { | 31 | { |
25 | struct pci_root_info *info = x86_find_pci_root_info(bus); | 32 | struct pci_root_info *info = x86_find_pci_root_info(bus); |
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 981c2dbd72cc..059a76c29739 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c | |||
@@ -456,19 +456,25 @@ void __init dmi_check_pciprobe(void) | |||
456 | dmi_check_system(pciprobe_dmi_table); | 456 | dmi_check_system(pciprobe_dmi_table); |
457 | } | 457 | } |
458 | 458 | ||
459 | struct pci_bus *pcibios_scan_root(int busnum) | 459 | void pcibios_scan_root(int busnum) |
460 | { | 460 | { |
461 | struct pci_bus *bus = NULL; | 461 | struct pci_bus *bus; |
462 | struct pci_sysdata *sd; | ||
463 | LIST_HEAD(resources); | ||
462 | 464 | ||
463 | while ((bus = pci_find_next_bus(bus)) != NULL) { | 465 | sd = kzalloc(sizeof(*sd), GFP_KERNEL); |
464 | if (bus->number == busnum) { | 466 | if (!sd) { |
465 | /* Already scanned */ | 467 | printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busnum); |
466 | return bus; | 468 | return; |
467 | } | 469 | } |
470 | sd->node = x86_pci_root_bus_node(busnum); | ||
471 | x86_pci_root_bus_resources(busnum, &resources); | ||
472 | printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum); | ||
473 | bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources); | ||
474 | if (!bus) { | ||
475 | pci_free_resource_list(&resources); | ||
476 | kfree(sd); | ||
468 | } | 477 | } |
469 | |||
470 | return pci_scan_bus_on_node(busnum, &pci_root_ops, | ||
471 | get_mp_bus_to_node(busnum)); | ||
472 | } | 478 | } |
473 | 479 | ||
474 | void __init pcibios_set_cache_line_size(void) | 480 | void __init pcibios_set_cache_line_size(void) |
@@ -561,7 +567,6 @@ char * __init pcibios_setup(char *str) | |||
561 | pci_probe |= PCI_PROBE_NOEARLY; | 567 | pci_probe |= PCI_PROBE_NOEARLY; |
562 | return NULL; | 568 | return NULL; |
563 | } | 569 | } |
564 | #ifndef CONFIG_X86_VISWS | ||
565 | else if (!strcmp(str, "usepirqmask")) { | 570 | else if (!strcmp(str, "usepirqmask")) { |
566 | pci_probe |= PCI_USE_PIRQ_MASK; | 571 | pci_probe |= PCI_USE_PIRQ_MASK; |
567 | return NULL; | 572 | return NULL; |
@@ -571,9 +576,7 @@ char * __init pcibios_setup(char *str) | |||
571 | } else if (!strncmp(str, "lastbus=", 8)) { | 576 | } else if (!strncmp(str, "lastbus=", 8)) { |
572 | pcibios_last_bus = simple_strtol(str+8, NULL, 0); | 577 | pcibios_last_bus = simple_strtol(str+8, NULL, 0); |
573 | return NULL; | 578 | return NULL; |
574 | } | 579 | } else if (!strcmp(str, "rom")) { |
575 | #endif | ||
576 | else if (!strcmp(str, "rom")) { | ||
577 | pci_probe |= PCI_ASSIGN_ROMS; | 580 | pci_probe |= PCI_ASSIGN_ROMS; |
578 | return NULL; | 581 | return NULL; |
579 | } else if (!strcmp(str, "norom")) { | 582 | } else if (!strcmp(str, "norom")) { |
@@ -677,105 +680,3 @@ int pci_ext_cfg_avail(void) | |||
677 | else | 680 | else |
678 | return 0; | 681 | return 0; |
679 | } | 682 | } |
680 | |||
681 | struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node) | ||
682 | { | ||
683 | LIST_HEAD(resources); | ||
684 | struct pci_bus *bus = NULL; | ||
685 | struct pci_sysdata *sd; | ||
686 | |||
687 | /* | ||
688 | * Allocate per-root-bus (not per bus) arch-specific data. | ||
689 | * TODO: leak; this memory is never freed. | ||
690 | * It's arguable whether it's worth the trouble to care. | ||
691 | */ | ||
692 | sd = kzalloc(sizeof(*sd), GFP_KERNEL); | ||
693 | if (!sd) { | ||
694 | printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busno); | ||
695 | return NULL; | ||
696 | } | ||
697 | sd->node = node; | ||
698 | x86_pci_root_bus_resources(busno, &resources); | ||
699 | printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busno); | ||
700 | bus = pci_scan_root_bus(NULL, busno, ops, sd, &resources); | ||
701 | if (!bus) { | ||
702 | pci_free_resource_list(&resources); | ||
703 | kfree(sd); | ||
704 | } | ||
705 | |||
706 | return bus; | ||
707 | } | ||
708 | |||
709 | struct pci_bus *pci_scan_bus_with_sysdata(int busno) | ||
710 | { | ||
711 | return pci_scan_bus_on_node(busno, &pci_root_ops, -1); | ||
712 | } | ||
713 | |||
714 | /* | ||
715 | * NUMA info for PCI busses | ||
716 | * | ||
717 | * Early arch code is responsible for filling in reasonable values here. | ||
718 | * A node id of "-1" means "use current node". In other words, if a bus | ||
719 | * has a -1 node id, it's not tightly coupled to any particular chunk | ||
720 | * of memory (as is the case on some Nehalem systems). | ||
721 | */ | ||
722 | #ifdef CONFIG_NUMA | ||
723 | |||
724 | #define BUS_NR 256 | ||
725 | |||
726 | #ifdef CONFIG_X86_64 | ||
727 | |||
728 | static int mp_bus_to_node[BUS_NR] = { | ||
729 | [0 ... BUS_NR - 1] = -1 | ||
730 | }; | ||
731 | |||
732 | void set_mp_bus_to_node(int busnum, int node) | ||
733 | { | ||
734 | if (busnum >= 0 && busnum < BUS_NR) | ||
735 | mp_bus_to_node[busnum] = node; | ||
736 | } | ||
737 | |||
738 | int get_mp_bus_to_node(int busnum) | ||
739 | { | ||
740 | int node = -1; | ||
741 | |||
742 | if (busnum < 0 || busnum > (BUS_NR - 1)) | ||
743 | return node; | ||
744 | |||
745 | node = mp_bus_to_node[busnum]; | ||
746 | |||
747 | /* | ||
748 | * let numa_node_id to decide it later in dma_alloc_pages | ||
749 | * if there is no ram on that node | ||
750 | */ | ||
751 | if (node != -1 && !node_online(node)) | ||
752 | node = -1; | ||
753 | |||
754 | return node; | ||
755 | } | ||
756 | |||
757 | #else /* CONFIG_X86_32 */ | ||
758 | |||
759 | static int mp_bus_to_node[BUS_NR] = { | ||
760 | [0 ... BUS_NR - 1] = -1 | ||
761 | }; | ||
762 | |||
763 | void set_mp_bus_to_node(int busnum, int node) | ||
764 | { | ||
765 | if (busnum >= 0 && busnum < BUS_NR) | ||
766 | mp_bus_to_node[busnum] = (unsigned char) node; | ||
767 | } | ||
768 | |||
769 | int get_mp_bus_to_node(int busnum) | ||
770 | { | ||
771 | int node; | ||
772 | |||
773 | if (busnum < 0 || busnum > (BUS_NR - 1)) | ||
774 | return 0; | ||
775 | node = mp_bus_to_node[busnum]; | ||
776 | return node; | ||
777 | } | ||
778 | |||
779 | #endif /* CONFIG_X86_32 */ | ||
780 | |||
781 | #endif /* CONFIG_NUMA */ | ||
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index bca9e85daaa5..94ae9ae9574f 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c | |||
@@ -25,9 +25,9 @@ static void pci_fixup_i450nx(struct pci_dev *d) | |||
25 | dev_dbg(&d->dev, "i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, | 25 | dev_dbg(&d->dev, "i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, |
26 | suba, subb); | 26 | suba, subb); |
27 | if (busno) | 27 | if (busno) |
28 | pci_scan_bus_with_sysdata(busno); /* Bus A */ | 28 | pcibios_scan_root(busno); /* Bus A */ |
29 | if (suba < subb) | 29 | if (suba < subb) |
30 | pci_scan_bus_with_sysdata(suba+1); /* Bus B */ | 30 | pcibios_scan_root(suba+1); /* Bus B */ |
31 | } | 31 | } |
32 | pcibios_last_bus = -1; | 32 | pcibios_last_bus = -1; |
33 | } | 33 | } |
@@ -42,7 +42,7 @@ static void pci_fixup_i450gx(struct pci_dev *d) | |||
42 | u8 busno; | 42 | u8 busno; |
43 | pci_read_config_byte(d, 0x4a, &busno); | 43 | pci_read_config_byte(d, 0x4a, &busno); |
44 | dev_info(&d->dev, "i440KX/GX host bridge; secondary bus %02x\n", busno); | 44 | dev_info(&d->dev, "i440KX/GX host bridge; secondary bus %02x\n", busno); |
45 | pci_scan_bus_with_sysdata(busno); | 45 | pcibios_scan_root(busno); |
46 | pcibios_last_bus = -1; | 46 | pcibios_last_bus = -1; |
47 | } | 47 | } |
48 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx); | 48 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx); |
@@ -313,9 +313,10 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_r | |||
313 | * IORESOURCE_ROM_SHADOW is used to associate the boot video | 313 | * IORESOURCE_ROM_SHADOW is used to associate the boot video |
314 | * card with this copy. On laptops this copy has to be used since | 314 | * card with this copy. On laptops this copy has to be used since |
315 | * the main ROM may be compressed or combined with another image. | 315 | * the main ROM may be compressed or combined with another image. |
316 | * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW | 316 | * See pci_map_rom() for use of this flag. Before marking the device |
317 | * is marked here since the boot video device will be the only enabled | 317 | * with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set |
318 | * video device at this point. | 318 | * by either arch cde or vga-arbitration, if so only apply the fixup to this |
319 | * already determined primary video card. | ||
319 | */ | 320 | */ |
320 | 321 | ||
321 | static void pci_fixup_video(struct pci_dev *pdev) | 322 | static void pci_fixup_video(struct pci_dev *pdev) |
@@ -346,12 +347,13 @@ static void pci_fixup_video(struct pci_dev *pdev) | |||
346 | } | 347 | } |
347 | bus = bus->parent; | 348 | bus = bus->parent; |
348 | } | 349 | } |
349 | pci_read_config_word(pdev, PCI_COMMAND, &config); | 350 | if (!vga_default_device() || pdev == vga_default_device()) { |
350 | if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { | 351 | pci_read_config_word(pdev, PCI_COMMAND, &config); |
351 | pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; | 352 | if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { |
352 | dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n"); | 353 | pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; |
353 | if (!vga_default_device()) | 354 | dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n"); |
354 | vga_set_default_device(pdev); | 355 | vga_set_default_device(pdev); |
356 | } | ||
355 | } | 357 | } |
356 | } | 358 | } |
357 | DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, | 359 | DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, |
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index 372e9b8989b3..84112f55dd7a 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c | |||
@@ -136,13 +136,9 @@ static void __init pirq_peer_trick(void) | |||
136 | busmap[e->bus] = 1; | 136 | busmap[e->bus] = 1; |
137 | } | 137 | } |
138 | for (i = 1; i < 256; i++) { | 138 | for (i = 1; i < 256; i++) { |
139 | int node; | ||
140 | if (!busmap[i] || pci_find_bus(0, i)) | 139 | if (!busmap[i] || pci_find_bus(0, i)) |
141 | continue; | 140 | continue; |
142 | node = get_mp_bus_to_node(i); | 141 | pcibios_scan_root(i); |
143 | if (pci_scan_bus_on_node(i, &pci_root_ops, node)) | ||
144 | printk(KERN_INFO "PCI: Discovered primary peer " | ||
145 | "bus %02x [IRQ]\n", i); | ||
146 | } | 142 | } |
147 | pcibios_last_bus = -1; | 143 | pcibios_last_bus = -1; |
148 | } | 144 | } |
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c index 4db96fb1c232..5b662c0faf8c 100644 --- a/arch/x86/pci/legacy.c +++ b/arch/x86/pci/legacy.c | |||
@@ -37,19 +37,17 @@ int __init pci_legacy_init(void) | |||
37 | void pcibios_scan_specific_bus(int busn) | 37 | void pcibios_scan_specific_bus(int busn) |
38 | { | 38 | { |
39 | int devfn; | 39 | int devfn; |
40 | long node; | ||
41 | u32 l; | 40 | u32 l; |
42 | 41 | ||
43 | if (pci_find_bus(0, busn)) | 42 | if (pci_find_bus(0, busn)) |
44 | return; | 43 | return; |
45 | 44 | ||
46 | node = get_mp_bus_to_node(busn); | ||
47 | for (devfn = 0; devfn < 256; devfn += 8) { | 45 | for (devfn = 0; devfn < 256; devfn += 8) { |
48 | if (!raw_pci_read(0, busn, devfn, PCI_VENDOR_ID, 2, &l) && | 46 | if (!raw_pci_read(0, busn, devfn, PCI_VENDOR_ID, 2, &l) && |
49 | l != 0x0000 && l != 0xffff) { | 47 | l != 0x0000 && l != 0xffff) { |
50 | DBG("Found device at %02x:%02x [%04x]\n", busn, devfn, l); | 48 | DBG("Found device at %02x:%02x [%04x]\n", busn, devfn, l); |
51 | printk(KERN_INFO "PCI: Discovered peer bus %02x\n", busn); | 49 | printk(KERN_INFO "PCI: Discovered peer bus %02x\n", busn); |
52 | pci_scan_bus_on_node(busn, &pci_root_ops, node); | 50 | pcibios_scan_root(busn); |
53 | return; | 51 | return; |
54 | } | 52 | } |
55 | } | 53 | } |
diff --git a/arch/x86/pci/numaq_32.c b/arch/x86/pci/numaq_32.c deleted file mode 100644 index 72c229f9ebcf..000000000000 --- a/arch/x86/pci/numaq_32.c +++ /dev/null | |||
@@ -1,165 +0,0 @@ | |||
1 | /* | ||
2 | * numaq_32.c - Low-level PCI access for NUMA-Q machines | ||
3 | */ | ||
4 | |||
5 | #include <linux/pci.h> | ||
6 | #include <linux/init.h> | ||
7 | #include <linux/nodemask.h> | ||
8 | #include <asm/apic.h> | ||
9 | #include <asm/mpspec.h> | ||
10 | #include <asm/pci_x86.h> | ||
11 | #include <asm/numaq.h> | ||
12 | |||
13 | #define BUS2QUAD(global) (mp_bus_id_to_node[global]) | ||
14 | |||
15 | #define BUS2LOCAL(global) (mp_bus_id_to_local[global]) | ||
16 | |||
17 | #define QUADLOCAL2BUS(quad,local) (quad_local_to_mp_bus_id[quad][local]) | ||
18 | |||
19 | #define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \ | ||
20 | (0x80000000 | (BUS2LOCAL(bus) << 16) | (devfn << 8) | (reg & ~3)) | ||
21 | |||
22 | static void write_cf8(unsigned bus, unsigned devfn, unsigned reg) | ||
23 | { | ||
24 | unsigned val = PCI_CONF1_MQ_ADDRESS(bus, devfn, reg); | ||
25 | if (xquad_portio) | ||
26 | writel(val, XQUAD_PORT_ADDR(0xcf8, BUS2QUAD(bus))); | ||
27 | else | ||
28 | outl(val, 0xCF8); | ||
29 | } | ||
30 | |||
31 | static int pci_conf1_mq_read(unsigned int seg, unsigned int bus, | ||
32 | unsigned int devfn, int reg, int len, u32 *value) | ||
33 | { | ||
34 | unsigned long flags; | ||
35 | void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus)); | ||
36 | |||
37 | WARN_ON(seg); | ||
38 | if (!value || (bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) | ||
39 | return -EINVAL; | ||
40 | |||
41 | raw_spin_lock_irqsave(&pci_config_lock, flags); | ||
42 | |||
43 | write_cf8(bus, devfn, reg); | ||
44 | |||
45 | switch (len) { | ||
46 | case 1: | ||
47 | if (xquad_portio) | ||
48 | *value = readb(adr + (reg & 3)); | ||
49 | else | ||
50 | *value = inb(0xCFC + (reg & 3)); | ||
51 | break; | ||
52 | case 2: | ||
53 | if (xquad_portio) | ||
54 | *value = readw(adr + (reg & 2)); | ||
55 | else | ||
56 | *value = inw(0xCFC + (reg & 2)); | ||
57 | break; | ||
58 | case 4: | ||
59 | if (xquad_portio) | ||
60 | *value = readl(adr); | ||
61 | else | ||
62 | *value = inl(0xCFC); | ||
63 | break; | ||
64 | } | ||
65 | |||
66 | raw_spin_unlock_irqrestore(&pci_config_lock, flags); | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static int pci_conf1_mq_write(unsigned int seg, unsigned int bus, | ||
72 | unsigned int devfn, int reg, int len, u32 value) | ||
73 | { | ||
74 | unsigned long flags; | ||
75 | void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus)); | ||
76 | |||
77 | WARN_ON(seg); | ||
78 | if ((bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) | ||
79 | return -EINVAL; | ||
80 | |||
81 | raw_spin_lock_irqsave(&pci_config_lock, flags); | ||
82 | |||
83 | write_cf8(bus, devfn, reg); | ||
84 | |||
85 | switch (len) { | ||
86 | case 1: | ||
87 | if (xquad_portio) | ||
88 | writeb(value, adr + (reg & 3)); | ||
89 | else | ||
90 | outb((u8)value, 0xCFC + (reg & 3)); | ||
91 | break; | ||
92 | case 2: | ||
93 | if (xquad_portio) | ||
94 | writew(value, adr + (reg & 2)); | ||
95 | else | ||
96 | outw((u16)value, 0xCFC + (reg & 2)); | ||
97 | break; | ||
98 | case 4: | ||
99 | if (xquad_portio) | ||
100 | writel(value, adr + reg); | ||
101 | else | ||
102 | outl((u32)value, 0xCFC); | ||
103 | break; | ||
104 | } | ||
105 | |||
106 | raw_spin_unlock_irqrestore(&pci_config_lock, flags); | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | #undef PCI_CONF1_MQ_ADDRESS | ||
112 | |||
113 | static const struct pci_raw_ops pci_direct_conf1_mq = { | ||
114 | .read = pci_conf1_mq_read, | ||
115 | .write = pci_conf1_mq_write | ||
116 | }; | ||
117 | |||
118 | |||
119 | static void pci_fixup_i450nx(struct pci_dev *d) | ||
120 | { | ||
121 | /* | ||
122 | * i450NX -- Find and scan all secondary buses on all PXB's. | ||
123 | */ | ||
124 | int pxb, reg; | ||
125 | u8 busno, suba, subb; | ||
126 | int quad = BUS2QUAD(d->bus->number); | ||
127 | |||
128 | dev_info(&d->dev, "searching for i450NX host bridges\n"); | ||
129 | reg = 0xd0; | ||
130 | for(pxb=0; pxb<2; pxb++) { | ||
131 | pci_read_config_byte(d, reg++, &busno); | ||
132 | pci_read_config_byte(d, reg++, &suba); | ||
133 | pci_read_config_byte(d, reg++, &subb); | ||
134 | dev_dbg(&d->dev, "i450NX PXB %d: %02x/%02x/%02x\n", | ||
135 | pxb, busno, suba, subb); | ||
136 | if (busno) { | ||
137 | /* Bus A */ | ||
138 | pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, busno)); | ||
139 | } | ||
140 | if (suba < subb) { | ||
141 | /* Bus B */ | ||
142 | pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, suba+1)); | ||
143 | } | ||
144 | } | ||
145 | pcibios_last_bus = -1; | ||
146 | } | ||
147 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx); | ||
148 | |||
149 | int __init pci_numaq_init(void) | ||
150 | { | ||
151 | int quad; | ||
152 | |||
153 | raw_pci_ops = &pci_direct_conf1_mq; | ||
154 | |||
155 | pcibios_scan_root(0); | ||
156 | if (num_online_nodes() > 1) | ||
157 | for_each_online_node(quad) { | ||
158 | if (quad == 0) | ||
159 | continue; | ||
160 | printk("Scanning PCI bus %d for quad %d\n", | ||
161 | QUADLOCAL2BUS(quad,0), quad); | ||
162 | pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, 0)); | ||
163 | } | ||
164 | return 0; | ||
165 | } | ||
diff --git a/arch/x86/pci/visws.c b/arch/x86/pci/visws.c deleted file mode 100644 index 3e6d2a6db866..000000000000 --- a/arch/x86/pci/visws.c +++ /dev/null | |||
@@ -1,87 +0,0 @@ | |||
1 | /* | ||
2 | * Low-Level PCI Support for SGI Visual Workstation | ||
3 | * | ||
4 | * (c) 1999--2000 Martin Mares <mj@ucw.cz> | ||
5 | */ | ||
6 | |||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/pci.h> | ||
9 | #include <linux/init.h> | ||
10 | |||
11 | #include <asm/setup.h> | ||
12 | #include <asm/pci_x86.h> | ||
13 | #include <asm/visws/cobalt.h> | ||
14 | #include <asm/visws/lithium.h> | ||
15 | |||
16 | static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; } | ||
17 | static void pci_visws_disable_irq(struct pci_dev *dev) { } | ||
18 | |||
19 | /* int (*pcibios_enable_irq)(struct pci_dev *dev) = &pci_visws_enable_irq; */ | ||
20 | /* void (*pcibios_disable_irq)(struct pci_dev *dev) = &pci_visws_disable_irq; */ | ||
21 | |||
22 | /* void __init pcibios_penalize_isa_irq(int irq, int active) {} */ | ||
23 | |||
24 | |||
25 | unsigned int pci_bus0, pci_bus1; | ||
26 | |||
27 | static int __init visws_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | ||
28 | { | ||
29 | int irq, bus = dev->bus->number; | ||
30 | |||
31 | pin--; | ||
32 | |||
33 | /* Nothing useful at PIIX4 pin 1 */ | ||
34 | if (bus == pci_bus0 && slot == 4 && pin == 0) | ||
35 | return -1; | ||
36 | |||
37 | /* PIIX4 USB is on Bus 0, Slot 4, Line 3 */ | ||
38 | if (bus == pci_bus0 && slot == 4 && pin == 3) { | ||
39 | irq = CO_IRQ(CO_APIC_PIIX4_USB); | ||
40 | goto out; | ||
41 | } | ||
42 | |||
43 | /* First pin spread down 1 APIC entry per slot */ | ||
44 | if (pin == 0) { | ||
45 | irq = CO_IRQ((bus == pci_bus0 ? CO_APIC_PCIB_BASE0 : | ||
46 | CO_APIC_PCIA_BASE0) + slot); | ||
47 | goto out; | ||
48 | } | ||
49 | |||
50 | /* lines 1,2,3 from any slot is shared in this twirly pattern */ | ||
51 | if (bus == pci_bus1) { | ||
52 | /* lines 1-3 from devices 0 1 rotate over 2 apic entries */ | ||
53 | irq = CO_IRQ(CO_APIC_PCIA_BASE123 + ((slot + (pin - 1)) % 2)); | ||
54 | } else { /* bus == pci_bus0 */ | ||
55 | /* lines 1-3 from devices 0-3 rotate over 3 apic entries */ | ||
56 | if (slot == 0) | ||
57 | slot = 3; /* same pattern */ | ||
58 | irq = CO_IRQ(CO_APIC_PCIA_BASE123 + ((3 - slot) + (pin - 1) % 3)); | ||
59 | } | ||
60 | out: | ||
61 | printk(KERN_DEBUG "PCI: Bus %d Slot %d Line %d -> IRQ %d\n", bus, slot, pin, irq); | ||
62 | return irq; | ||
63 | } | ||
64 | |||
65 | int __init pci_visws_init(void) | ||
66 | { | ||
67 | pcibios_enable_irq = &pci_visws_enable_irq; | ||
68 | pcibios_disable_irq = &pci_visws_disable_irq; | ||
69 | |||
70 | /* The VISWS supports configuration access type 1 only */ | ||
71 | pci_probe = (pci_probe | PCI_PROBE_CONF1) & | ||
72 | ~(PCI_PROBE_BIOS | PCI_PROBE_CONF2); | ||
73 | |||
74 | pci_bus0 = li_pcib_read16(LI_PCI_BUSNUM) & 0xff; | ||
75 | pci_bus1 = li_pcia_read16(LI_PCI_BUSNUM) & 0xff; | ||
76 | |||
77 | printk(KERN_INFO "PCI: Lithium bridge A bus: %u, " | ||
78 | "bridge B (PIIX4) bus: %u\n", pci_bus1, pci_bus0); | ||
79 | |||
80 | raw_pci_ops = &pci_direct_conf1; | ||
81 | pci_scan_bus_with_sysdata(pci_bus0); | ||
82 | pci_scan_bus_with_sysdata(pci_bus1); | ||
83 | pci_fixup_irqs(pci_common_swizzle, visws_map_irq); | ||
84 | pcibios_resource_survey(); | ||
85 | /* Request bus scan */ | ||
86 | return 1; | ||
87 | } | ||
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 103e702ec5a7..905956f16465 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
@@ -178,6 +178,7 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
178 | i = 0; | 178 | i = 0; |
179 | list_for_each_entry(msidesc, &dev->msi_list, list) { | 179 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
180 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], | 180 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], |
181 | (type == PCI_CAP_ID_MSI) ? nvec : 1, | ||
181 | (type == PCI_CAP_ID_MSIX) ? | 182 | (type == PCI_CAP_ID_MSIX) ? |
182 | "pcifront-msi-x" : | 183 | "pcifront-msi-x" : |
183 | "pcifront-msi", | 184 | "pcifront-msi", |
@@ -245,6 +246,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
245 | "xen: msi already bound to pirq=%d\n", pirq); | 246 | "xen: msi already bound to pirq=%d\n", pirq); |
246 | } | 247 | } |
247 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, | 248 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, |
249 | (type == PCI_CAP_ID_MSI) ? nvec : 1, | ||
248 | (type == PCI_CAP_ID_MSIX) ? | 250 | (type == PCI_CAP_ID_MSIX) ? |
249 | "msi-x" : "msi", | 251 | "msi-x" : "msi", |
250 | DOMID_SELF); | 252 | DOMID_SELF); |
@@ -269,9 +271,6 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
269 | int ret = 0; | 271 | int ret = 0; |
270 | struct msi_desc *msidesc; | 272 | struct msi_desc *msidesc; |
271 | 273 | ||
272 | if (type == PCI_CAP_ID_MSI && nvec > 1) | ||
273 | return 1; | ||
274 | |||
275 | list_for_each_entry(msidesc, &dev->msi_list, list) { | 274 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
276 | struct physdev_map_pirq map_irq; | 275 | struct physdev_map_pirq map_irq; |
277 | domid_t domid; | 276 | domid_t domid; |
@@ -291,7 +290,10 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
291 | (pci_domain_nr(dev->bus) << 16); | 290 | (pci_domain_nr(dev->bus) << 16); |
292 | map_irq.devfn = dev->devfn; | 291 | map_irq.devfn = dev->devfn; |
293 | 292 | ||
294 | if (type == PCI_CAP_ID_MSIX) { | 293 | if (type == PCI_CAP_ID_MSI && nvec > 1) { |
294 | map_irq.type = MAP_PIRQ_TYPE_MULTI_MSI; | ||
295 | map_irq.entry_nr = nvec; | ||
296 | } else if (type == PCI_CAP_ID_MSIX) { | ||
295 | int pos; | 297 | int pos; |
296 | u32 table_offset, bir; | 298 | u32 table_offset, bir; |
297 | 299 | ||
@@ -308,6 +310,16 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
308 | if (pci_seg_supported) | 310 | if (pci_seg_supported) |
309 | ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, | 311 | ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, |
310 | &map_irq); | 312 | &map_irq); |
313 | if (type == PCI_CAP_ID_MSI && nvec > 1 && ret) { | ||
314 | /* | ||
315 | * If MAP_PIRQ_TYPE_MULTI_MSI is not available | ||
316 | * there's nothing else we can do in this case. | ||
317 | * Just set ret > 0 so driver can retry with | ||
318 | * single MSI. | ||
319 | */ | ||
320 | ret = 1; | ||
321 | goto out; | ||
322 | } | ||
311 | if (ret == -EINVAL && !pci_domain_nr(dev->bus)) { | 323 | if (ret == -EINVAL && !pci_domain_nr(dev->bus)) { |
312 | map_irq.type = MAP_PIRQ_TYPE_MSI; | 324 | map_irq.type = MAP_PIRQ_TYPE_MSI; |
313 | map_irq.index = -1; | 325 | map_irq.index = -1; |
@@ -324,11 +336,10 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
324 | goto out; | 336 | goto out; |
325 | } | 337 | } |
326 | 338 | ||
327 | ret = xen_bind_pirq_msi_to_irq(dev, msidesc, | 339 | ret = xen_bind_pirq_msi_to_irq(dev, msidesc, map_irq.pirq, |
328 | map_irq.pirq, | 340 | (type == PCI_CAP_ID_MSI) ? nvec : 1, |
329 | (type == PCI_CAP_ID_MSIX) ? | 341 | (type == PCI_CAP_ID_MSIX) ? "msi-x" : "msi", |
330 | "msi-x" : "msi", | 342 | domid); |
331 | domid); | ||
332 | if (ret < 0) | 343 | if (ret < 0) |
333 | goto out; | 344 | goto out; |
334 | } | 345 | } |