diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 11 | ||||
-rw-r--r-- | arch/x86/Kconfig | 24 | ||||
-rw-r--r-- | arch/x86/include/asm/io_apic.h | 10 | ||||
-rw-r--r-- | arch/x86/include/asm/pci.h | 2 | ||||
-rw-r--r-- | arch/x86/pci/common.c | 17 | ||||
-rw-r--r-- | drivers/acpi/pci_irq.c | 56 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 170 | ||||
-rw-r--r-- | include/linux/pci.h | 6 | ||||
-rw-r--r-- | include/linux/pci_ids.h | 5 |
9 files changed, 280 insertions, 21 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 343e0f0f84b..63bac584f9c 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1638,6 +1638,17 @@ and is between 256 and 4096 characters. It is defined in the file | |||
1638 | nomsi [MSI] If the PCI_MSI kernel config parameter is | 1638 | nomsi [MSI] If the PCI_MSI kernel config parameter is |
1639 | enabled, this kernel boot option can be used to | 1639 | enabled, this kernel boot option can be used to |
1640 | disable the use of MSI interrupts system-wide. | 1640 | disable the use of MSI interrupts system-wide. |
1641 | noioapicquirk [APIC] Disable all boot interrupt quirks. | ||
1642 | Safety option to keep boot IRQs enabled. This | ||
1643 | should never be necessary. | ||
1644 | ioapicreroute [APIC] Enable rerouting of boot IRQs to the | ||
1645 | primary IO-APIC for bridges that cannot disable | ||
1646 | boot IRQs. This fixes a source of spurious IRQs | ||
1647 | when the system masks IRQs. | ||
1648 | noioapicreroute [APIC] Disable workaround that uses the | ||
1649 | boot IRQ equivalent of an IRQ that connects to | ||
1650 | a chipset where boot IRQs cannot be disabled. | ||
1651 | The opposite of ioapicreroute. | ||
1641 | biosirq [X86-32] Use PCI BIOS calls to get the interrupt | 1652 | biosirq [X86-32] Use PCI BIOS calls to get the interrupt |
1642 | routing table. These calls are known to be buggy | 1653 | routing table. These calls are known to be buggy |
1643 | on several machines and they hang the machine | 1654 | on several machines and they hang the machine |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 350bee1d54d..f4ed47db79e 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -653,6 +653,30 @@ config X86_VISWS_APIC | |||
653 | def_bool y | 653 | def_bool y |
654 | depends on X86_32 && X86_VISWS | 654 | depends on X86_32 && X86_VISWS |
655 | 655 | ||
656 | config X86_REROUTE_FOR_BROKEN_BOOT_IRQS | ||
657 | bool "Reroute for broken boot IRQs" | ||
658 | default n | ||
659 | depends on X86_IO_APIC | ||
660 | help | ||
661 | This option enables a workaround that fixes a source of | ||
662 | spurious interrupts. This is recommended when threaded | ||
663 | interrupt handling is used on systems where the generation of | ||
664 | superfluous "boot interrupts" cannot be disabled. | ||
665 | |||
666 | Some chipsets generate a legacy INTx "boot IRQ" when the IRQ | ||
667 | entry in the chipset's IO-APIC is masked (as, e.g. the RT | ||
668 | kernel does during interrupt handling). On chipsets where this | ||
669 | boot IRQ generation cannot be disabled, this workaround keeps | ||
670 | the original IRQ line masked so that only the equivalent "boot | ||
671 | IRQ" is delivered to the CPUs. The workaround also tells the | ||
672 | kernel to set up the IRQ handler on the boot IRQ line. In this | ||
673 | way only one interrupt is delivered to the kernel. Otherwise | ||
674 | the spurious second interrupt may cause the kernel to bring | ||
675 | down (vital) interrupt lines. | ||
676 | |||
677 | Only affects "broken" chipsets. Interrupt sharing may be | ||
678 | increased on these systems. | ||
679 | |||
656 | config X86_MCE | 680 | config X86_MCE |
657 | bool "Machine Check Exception" | 681 | bool "Machine Check Exception" |
658 | depends on !X86_VOYAGER | 682 | depends on !X86_VOYAGER |
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 6afd9933a7d..e475e009ae5 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h | |||
@@ -156,11 +156,21 @@ extern int sis_apic_bug; | |||
156 | /* 1 if "noapic" boot option passed */ | 156 | /* 1 if "noapic" boot option passed */ |
157 | extern int skip_ioapic_setup; | 157 | extern int skip_ioapic_setup; |
158 | 158 | ||
159 | /* 1 if "noapic" boot option passed */ | ||
160 | extern int noioapicquirk; | ||
161 | |||
162 | /* -1 if "noapic" boot option passed */ | ||
163 | extern int noioapicreroute; | ||
164 | |||
159 | /* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */ | 165 | /* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */ |
160 | extern int timer_through_8259; | 166 | extern int timer_through_8259; |
161 | 167 | ||
162 | static inline void disable_ioapic_setup(void) | 168 | static inline void disable_ioapic_setup(void) |
163 | { | 169 | { |
170 | #ifdef CONFIG_PCI | ||
171 | noioapicquirk = 1; | ||
172 | noioapicreroute = -1; | ||
173 | #endif | ||
164 | skip_ioapic_setup = 1; | 174 | skip_ioapic_setup = 1; |
165 | } | 175 | } |
166 | 176 | ||
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 875b38edf19..647781298e7 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h | |||
@@ -19,6 +19,8 @@ struct pci_sysdata { | |||
19 | }; | 19 | }; |
20 | 20 | ||
21 | extern int pci_routeirq; | 21 | extern int pci_routeirq; |
22 | extern int noioapicquirk; | ||
23 | extern int noioapicreroute; | ||
22 | 24 | ||
23 | /* scan a bus after allocating a pci_sysdata for it */ | 25 | /* scan a bus after allocating a pci_sysdata for it */ |
24 | extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops, | 26 | extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops, |
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index b67732bbb85..bb1a01f089e 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c | |||
@@ -23,6 +23,12 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | | |||
23 | unsigned int pci_early_dump_regs; | 23 | unsigned int pci_early_dump_regs; |
24 | static int pci_bf_sort; | 24 | static int pci_bf_sort; |
25 | int pci_routeirq; | 25 | int pci_routeirq; |
26 | int noioapicquirk; | ||
27 | #ifdef CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS | ||
28 | int noioapicreroute = 0; | ||
29 | #else | ||
30 | int noioapicreroute = 1; | ||
31 | #endif | ||
26 | int pcibios_last_bus = -1; | 32 | int pcibios_last_bus = -1; |
27 | unsigned long pirq_table_addr; | 33 | unsigned long pirq_table_addr; |
28 | struct pci_bus *pci_root_bus; | 34 | struct pci_bus *pci_root_bus; |
@@ -519,6 +525,17 @@ char * __devinit pcibios_setup(char *str) | |||
519 | } else if (!strcmp(str, "skip_isa_align")) { | 525 | } else if (!strcmp(str, "skip_isa_align")) { |
520 | pci_probe |= PCI_CAN_SKIP_ISA_ALIGN; | 526 | pci_probe |= PCI_CAN_SKIP_ISA_ALIGN; |
521 | return NULL; | 527 | return NULL; |
528 | } else if (!strcmp(str, "noioapicquirk")) { | ||
529 | noioapicquirk = 1; | ||
530 | return NULL; | ||
531 | } else if (!strcmp(str, "ioapicreroute")) { | ||
532 | if (noioapicreroute != -1) | ||
533 | noioapicreroute = 0; | ||
534 | return NULL; | ||
535 | } else if (!strcmp(str, "noioapicreroute")) { | ||
536 | if (noioapicreroute != -1) | ||
537 | noioapicreroute = 1; | ||
538 | return NULL; | ||
522 | } | 539 | } |
523 | return str; | 540 | return str; |
524 | } | 541 | } |
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 11acaee14d6..bf79d83bdfb 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
@@ -384,6 +384,27 @@ acpi_pci_free_irq(struct acpi_prt_entry *entry, | |||
384 | return irq; | 384 | return irq; |
385 | } | 385 | } |
386 | 386 | ||
387 | #ifdef CONFIG_X86_IO_APIC | ||
388 | extern int noioapicquirk; | ||
389 | |||
390 | static int bridge_has_boot_interrupt_variant(struct pci_bus *bus) | ||
391 | { | ||
392 | struct pci_bus *bus_it; | ||
393 | |||
394 | for (bus_it = bus ; bus_it ; bus_it = bus_it->parent) { | ||
395 | if (!bus_it->self) | ||
396 | return 0; | ||
397 | |||
398 | printk(KERN_INFO "vendor=%04x device=%04x\n", bus_it->self->vendor, | ||
399 | bus_it->self->device); | ||
400 | |||
401 | if (bus_it->self->irq_reroute_variant) | ||
402 | return bus_it->self->irq_reroute_variant; | ||
403 | } | ||
404 | return 0; | ||
405 | } | ||
406 | #endif /* CONFIG_X86_IO_APIC */ | ||
407 | |||
387 | /* | 408 | /* |
388 | * acpi_pci_irq_lookup | 409 | * acpi_pci_irq_lookup |
389 | * success: return IRQ >= 0 | 410 | * success: return IRQ >= 0 |
@@ -413,6 +434,41 @@ acpi_pci_irq_lookup(struct pci_bus *bus, | |||
413 | } | 434 | } |
414 | 435 | ||
415 | ret = func(entry, triggering, polarity, link); | 436 | ret = func(entry, triggering, polarity, link); |
437 | |||
438 | #ifdef CONFIG_X86_IO_APIC | ||
439 | /* | ||
440 | * Some chipsets (e.g. intel 6700PXH) generate a legacy INTx when the | ||
441 | * IRQ entry in the chipset's IO-APIC is masked (as, e.g. the RT kernel | ||
442 | * does during interrupt handling). When this INTx generation cannot be | ||
443 | * disabled, we reroute these interrupts to their legacy equivalent to | ||
444 | * get rid of spurious interrupts. | ||
445 | */ | ||
446 | if (!noioapicquirk) { | ||
447 | switch (bridge_has_boot_interrupt_variant(bus)) { | ||
448 | case 0: | ||
449 | /* no rerouting necessary */ | ||
450 | break; | ||
451 | |||
452 | case INTEL_IRQ_REROUTE_VARIANT: | ||
453 | /* | ||
454 | * Remap according to INTx routing table in 6700PXH | ||
455 | * specs, intel order number 302628-002, section | ||
456 | * 2.15.2. Other chipsets (80332, ...) have the same | ||
457 | * mapping and are handled here as well. | ||
458 | */ | ||
459 | printk(KERN_INFO "pci irq %d -> rerouted to legacy " | ||
460 | "irq %d\n", ret, (ret % 4) + 16); | ||
461 | ret = (ret % 4) + 16; | ||
462 | break; | ||
463 | |||
464 | default: | ||
465 | printk(KERN_INFO "not rerouting irq %d to legacy irq: " | ||
466 | "unknown mapping\n", ret); | ||
467 | break; | ||
468 | } | ||
469 | } | ||
470 | #endif /* CONFIG_X86_IO_APIC */ | ||
471 | |||
416 | return ret; | 472 | return ret; |
417 | } | 473 | } |
418 | 474 | ||
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 96cf8ecd04c..0b60ed884d9 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -619,27 +619,6 @@ static void __init quirk_ioapic_rmw(struct pci_dev *dev) | |||
619 | sis_apic_bug = 1; | 619 | sis_apic_bug = 1; |
620 | } | 620 | } |
621 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw); | 621 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw); |
622 | |||
623 | #define AMD8131_revA0 0x01 | ||
624 | #define AMD8131_revB0 0x11 | ||
625 | #define AMD8131_MISC 0x40 | ||
626 | #define AMD8131_NIOAMODE_BIT 0 | ||
627 | static void quirk_amd_8131_ioapic(struct pci_dev *dev) | ||
628 | { | ||
629 | unsigned char tmp; | ||
630 | |||
631 | if (nr_ioapics == 0) | ||
632 | return; | ||
633 | |||
634 | if (dev->revision == AMD8131_revA0 || dev->revision == AMD8131_revB0) { | ||
635 | dev_info(&dev->dev, "Fixing up AMD8131 IOAPIC mode\n"); | ||
636 | pci_read_config_byte( dev, AMD8131_MISC, &tmp); | ||
637 | tmp &= ~(1 << AMD8131_NIOAMODE_BIT); | ||
638 | pci_write_config_byte( dev, AMD8131_MISC, tmp); | ||
639 | } | ||
640 | } | ||
641 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic); | ||
642 | DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic); | ||
643 | #endif /* CONFIG_X86_IO_APIC */ | 622 | #endif /* CONFIG_X86_IO_APIC */ |
644 | 623 | ||
645 | /* | 624 | /* |
@@ -1436,6 +1415,155 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2609, quirk_intel_pcie_pm); | |||
1436 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm); | 1415 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm); |
1437 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm); | 1416 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm); |
1438 | 1417 | ||
1418 | #ifdef CONFIG_X86_IO_APIC | ||
1419 | /* | ||
1420 | * Boot interrupts on some chipsets cannot be turned off. For these chipsets, | ||
1421 | * remap the original interrupt in the linux kernel to the boot interrupt, so | ||
1422 | * that a PCI device's interrupt handler is installed on the boot interrupt | ||
1423 | * line instead. | ||
1424 | */ | ||
1425 | static void quirk_reroute_to_boot_interrupts_intel(struct pci_dev *dev) | ||
1426 | { | ||
1427 | if (noioapicquirk || noioapicreroute) | ||
1428 | return; | ||
1429 | |||
1430 | dev->irq_reroute_variant = INTEL_IRQ_REROUTE_VARIANT; | ||
1431 | |||
1432 | printk(KERN_INFO "PCI quirk: reroute interrupts for 0x%04x:0x%04x\n", | ||
1433 | dev->vendor, dev->device); | ||
1434 | return; | ||
1435 | } | ||
1436 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80333_0, quirk_reroute_to_boot_interrupts_intel); | ||
1437 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80333_1, quirk_reroute_to_boot_interrupts_intel); | ||
1438 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, quirk_reroute_to_boot_interrupts_intel); | ||
1439 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_0, quirk_reroute_to_boot_interrupts_intel); | ||
1440 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1, quirk_reroute_to_boot_interrupts_intel); | ||
1441 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHV, quirk_reroute_to_boot_interrupts_intel); | ||
1442 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80332_0, quirk_reroute_to_boot_interrupts_intel); | ||
1443 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80332_1, quirk_reroute_to_boot_interrupts_intel); | ||
1444 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80333_0, quirk_reroute_to_boot_interrupts_intel); | ||
1445 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80333_1, quirk_reroute_to_boot_interrupts_intel); | ||
1446 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, quirk_reroute_to_boot_interrupts_intel); | ||
1447 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_0, quirk_reroute_to_boot_interrupts_intel); | ||
1448 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1, quirk_reroute_to_boot_interrupts_intel); | ||
1449 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHV, quirk_reroute_to_boot_interrupts_intel); | ||
1450 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80332_0, quirk_reroute_to_boot_interrupts_intel); | ||
1451 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80332_1, quirk_reroute_to_boot_interrupts_intel); | ||
1452 | |||
1453 | /* | ||
1454 | * On some chipsets we can disable the generation of legacy INTx boot | ||
1455 | * interrupts. | ||
1456 | */ | ||
1457 | |||
1458 | /* | ||
1459 | * IO-APIC1 on 6300ESB generates boot interrupts, see intel order no | ||
1460 | * 300641-004US, section 5.7.3. | ||
1461 | */ | ||
1462 | #define INTEL_6300_IOAPIC_ABAR 0x40 | ||
1463 | #define INTEL_6300_DISABLE_BOOT_IRQ (1<<14) | ||
1464 | |||
1465 | static void quirk_disable_intel_boot_interrupt(struct pci_dev *dev) | ||
1466 | { | ||
1467 | u16 pci_config_word; | ||
1468 | |||
1469 | if (noioapicquirk) | ||
1470 | return; | ||
1471 | |||
1472 | pci_read_config_word(dev, INTEL_6300_IOAPIC_ABAR, &pci_config_word); | ||
1473 | pci_config_word |= INTEL_6300_DISABLE_BOOT_IRQ; | ||
1474 | pci_write_config_word(dev, INTEL_6300_IOAPIC_ABAR, pci_config_word); | ||
1475 | |||
1476 | printk(KERN_INFO "disabled boot interrupt on device 0x%04x:0x%04x\n", | ||
1477 | dev->vendor, dev->device); | ||
1478 | } | ||
1479 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_10, quirk_disable_intel_boot_interrupt); | ||
1480 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_10, quirk_disable_intel_boot_interrupt); | ||
1481 | |||
1482 | /* | ||
1483 | * disable boot interrupts on HT-1000 | ||
1484 | */ | ||
1485 | #define BC_HT1000_FEATURE_REG 0x64 | ||
1486 | #define BC_HT1000_PIC_REGS_ENABLE (1<<0) | ||
1487 | #define BC_HT1000_MAP_IDX 0xC00 | ||
1488 | #define BC_HT1000_MAP_DATA 0xC01 | ||
1489 | |||
1490 | static void quirk_disable_broadcom_boot_interrupt(struct pci_dev *dev) | ||
1491 | { | ||
1492 | u32 pci_config_dword; | ||
1493 | u8 irq; | ||
1494 | |||
1495 | if (noioapicquirk) | ||
1496 | return; | ||
1497 | |||
1498 | pci_read_config_dword(dev, BC_HT1000_FEATURE_REG, &pci_config_dword); | ||
1499 | pci_write_config_dword(dev, BC_HT1000_FEATURE_REG, pci_config_dword | | ||
1500 | BC_HT1000_PIC_REGS_ENABLE); | ||
1501 | |||
1502 | for (irq = 0x10; irq < 0x10 + 32; irq++) { | ||
1503 | outb(irq, BC_HT1000_MAP_IDX); | ||
1504 | outb(0x00, BC_HT1000_MAP_DATA); | ||
1505 | } | ||
1506 | |||
1507 | pci_write_config_dword(dev, BC_HT1000_FEATURE_REG, pci_config_dword); | ||
1508 | |||
1509 | printk(KERN_INFO "disabled boot interrupts on PCI device" | ||
1510 | "0x%04x:0x%04x\n", dev->vendor, dev->device); | ||
1511 | } | ||
1512 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB, quirk_disable_broadcom_boot_interrupt); | ||
1513 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB, quirk_disable_broadcom_boot_interrupt); | ||
1514 | |||
1515 | /* | ||
1516 | * disable boot interrupts on AMD and ATI chipsets | ||
1517 | */ | ||
1518 | /* | ||
1519 | * NOIOAMODE needs to be disabled to disable "boot interrupts". For AMD 8131 | ||
1520 | * rev. A0 and B0, NOIOAMODE needs to be disabled anyway to fix IO-APIC mode | ||
1521 | * (due to an erratum). | ||
1522 | */ | ||
1523 | #define AMD_813X_MISC 0x40 | ||
1524 | #define AMD_813X_NOIOAMODE (1<<0) | ||
1525 | |||
1526 | static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev) | ||
1527 | { | ||
1528 | u32 pci_config_dword; | ||
1529 | |||
1530 | if (noioapicquirk) | ||
1531 | return; | ||
1532 | |||
1533 | pci_read_config_dword(dev, AMD_813X_MISC, &pci_config_dword); | ||
1534 | pci_config_dword &= ~AMD_813X_NOIOAMODE; | ||
1535 | pci_write_config_dword(dev, AMD_813X_MISC, pci_config_dword); | ||
1536 | |||
1537 | printk(KERN_INFO "disabled boot interrupts on PCI device " | ||
1538 | "0x%04x:0x%04x\n", dev->vendor, dev->device); | ||
1539 | } | ||
1540 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_amd_813x_boot_interrupt); | ||
1541 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, quirk_disable_amd_813x_boot_interrupt); | ||
1542 | |||
1543 | #define AMD_8111_PCI_IRQ_ROUTING 0x56 | ||
1544 | |||
1545 | static void quirk_disable_amd_8111_boot_interrupt(struct pci_dev *dev) | ||
1546 | { | ||
1547 | u16 pci_config_word; | ||
1548 | |||
1549 | if (noioapicquirk) | ||
1550 | return; | ||
1551 | |||
1552 | pci_read_config_word(dev, AMD_8111_PCI_IRQ_ROUTING, &pci_config_word); | ||
1553 | if (!pci_config_word) { | ||
1554 | printk(KERN_INFO "boot interrupts on PCI device 0x%04x:0x%04x " | ||
1555 | "already disabled\n", | ||
1556 | dev->vendor, dev->device); | ||
1557 | return; | ||
1558 | } | ||
1559 | pci_write_config_word(dev, AMD_8111_PCI_IRQ_ROUTING, 0); | ||
1560 | printk(KERN_INFO "disabled boot interrupts on PCI device " | ||
1561 | "0x%04x:0x%04x\n", dev->vendor, dev->device); | ||
1562 | } | ||
1563 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS, quirk_disable_amd_8111_boot_interrupt); | ||
1564 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS, quirk_disable_amd_8111_boot_interrupt); | ||
1565 | #endif /* CONFIG_X86_IO_APIC */ | ||
1566 | |||
1439 | /* | 1567 | /* |
1440 | * Toshiba TC86C001 IDE controller reports the standard 8-byte BAR0 size | 1568 | * Toshiba TC86C001 IDE controller reports the standard 8-byte BAR0 size |
1441 | * but the PIO transfers won't work if BAR0 falls at the odd 8 bytes. | 1569 | * but the PIO transfers won't work if BAR0 falls at the odd 8 bytes. |
diff --git a/include/linux/pci.h b/include/linux/pci.h index c75b82bda32..9194adf82e2 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -134,6 +134,11 @@ enum pci_dev_flags { | |||
134 | PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2, | 134 | PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2, |
135 | }; | 135 | }; |
136 | 136 | ||
137 | enum pci_irq_reroute_variant { | ||
138 | INTEL_IRQ_REROUTE_VARIANT = 1, | ||
139 | MAX_IRQ_REROUTE_VARIANTS = 3 | ||
140 | }; | ||
141 | |||
137 | typedef unsigned short __bitwise pci_bus_flags_t; | 142 | typedef unsigned short __bitwise pci_bus_flags_t; |
138 | enum pci_bus_flags { | 143 | enum pci_bus_flags { |
139 | PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1, | 144 | PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1, |
@@ -218,6 +223,7 @@ struct pci_dev { | |||
218 | unsigned int no_msi:1; /* device may not use msi */ | 223 | unsigned int no_msi:1; /* device may not use msi */ |
219 | unsigned int block_ucfg_access:1; /* userspace config space access is blocked */ | 224 | unsigned int block_ucfg_access:1; /* userspace config space access is blocked */ |
220 | unsigned int broken_parity_status:1; /* Device generates false positive parity */ | 225 | unsigned int broken_parity_status:1; /* Device generates false positive parity */ |
226 | unsigned int irq_reroute_variant:2; /* device needs IRQ rerouting variant */ | ||
221 | unsigned int msi_enabled:1; | 227 | unsigned int msi_enabled:1; |
222 | unsigned int msix_enabled:1; | 228 | unsigned int msix_enabled:1; |
223 | unsigned int ari_enabled:1; /* ARI forwarding */ | 229 | unsigned int ari_enabled:1; /* ARI forwarding */ |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 1800f1d6e40..b6e69445428 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -2304,6 +2304,10 @@ | |||
2304 | #define PCI_DEVICE_ID_INTEL_PXH_0 0x0329 | 2304 | #define PCI_DEVICE_ID_INTEL_PXH_0 0x0329 |
2305 | #define PCI_DEVICE_ID_INTEL_PXH_1 0x032A | 2305 | #define PCI_DEVICE_ID_INTEL_PXH_1 0x032A |
2306 | #define PCI_DEVICE_ID_INTEL_PXHV 0x032C | 2306 | #define PCI_DEVICE_ID_INTEL_PXHV 0x032C |
2307 | #define PCI_DEVICE_ID_INTEL_80332_0 0x0330 | ||
2308 | #define PCI_DEVICE_ID_INTEL_80332_1 0x0332 | ||
2309 | #define PCI_DEVICE_ID_INTEL_80333_0 0x0370 | ||
2310 | #define PCI_DEVICE_ID_INTEL_80333_1 0x0372 | ||
2307 | #define PCI_DEVICE_ID_INTEL_82375 0x0482 | 2311 | #define PCI_DEVICE_ID_INTEL_82375 0x0482 |
2308 | #define PCI_DEVICE_ID_INTEL_82424 0x0483 | 2312 | #define PCI_DEVICE_ID_INTEL_82424 0x0483 |
2309 | #define PCI_DEVICE_ID_INTEL_82378 0x0484 | 2313 | #define PCI_DEVICE_ID_INTEL_82378 0x0484 |
@@ -2376,6 +2380,7 @@ | |||
2376 | #define PCI_DEVICE_ID_INTEL_ESB_4 0x25a4 | 2380 | #define PCI_DEVICE_ID_INTEL_ESB_4 0x25a4 |
2377 | #define PCI_DEVICE_ID_INTEL_ESB_5 0x25a6 | 2381 | #define PCI_DEVICE_ID_INTEL_ESB_5 0x25a6 |
2378 | #define PCI_DEVICE_ID_INTEL_ESB_9 0x25ab | 2382 | #define PCI_DEVICE_ID_INTEL_ESB_9 0x25ab |
2383 | #define PCI_DEVICE_ID_INTEL_ESB_10 0x25ac | ||
2379 | #define PCI_DEVICE_ID_INTEL_82820_HB 0x2500 | 2384 | #define PCI_DEVICE_ID_INTEL_82820_HB 0x2500 |
2380 | #define PCI_DEVICE_ID_INTEL_82820_UP_HB 0x2501 | 2385 | #define PCI_DEVICE_ID_INTEL_82820_UP_HB 0x2501 |
2381 | #define PCI_DEVICE_ID_INTEL_82850_HB 0x2530 | 2386 | #define PCI_DEVICE_ID_INTEL_82850_HB 0x2530 |