aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/pci_irq.c56
-rw-r--r--drivers/pci/quirks.c28
-rw-r--r--include/linux/pci.h6
3 files changed, 90 insertions, 0 deletions
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 89022a74faee..b37cb0a9826e 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
388extern int noioapicquirk;
389
390static 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 eb97564316d0..ac634ae2eb08 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1365,6 +1365,34 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm);
1365 1365
1366#ifdef CONFIG_X86_IO_APIC 1366#ifdef CONFIG_X86_IO_APIC
1367/* 1367/*
1368 * Boot interrupts on some chipsets cannot be turned off. For these chipsets,
1369 * remap the original interrupt in the linux kernel to the boot interrupt, so
1370 * that a PCI device's interrupt handler is installed on the boot interrupt
1371 * line instead.
1372 */
1373static void quirk_reroute_to_boot_interrupts_intel(struct pci_dev *dev)
1374{
1375 int i;
1376
1377 if (noioapicquirk)
1378 return;
1379
1380 dev->irq_reroute_variant = INTEL_IRQ_REROUTE_VARIANT;
1381
1382 printk(KERN_INFO "PCI quirk: reroute interrupts for 0x%04x:0x%04x\n",
1383 dev->vendor, dev->device);
1384 return;
1385}
1386DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80333_0, quirk_reroute_to_boot_interrupts_intel);
1387DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80333_1, quirk_reroute_to_boot_interrupts_intel);
1388DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, quirk_reroute_to_boot_interrupts_intel);
1389DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_0, quirk_reroute_to_boot_interrupts_intel);
1390DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1, quirk_reroute_to_boot_interrupts_intel);
1391DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHV, quirk_reroute_to_boot_interrupts_intel);
1392DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80332_0, quirk_reroute_to_boot_interrupts_intel);
1393DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80332_1, quirk_reroute_to_boot_interrupts_intel);
1394
1395/*
1368 * On some chipsets we can disable the generation of legacy INTx boot 1396 * On some chipsets we can disable the generation of legacy INTx boot
1369 * interrupts. 1397 * interrupts.
1370 */ 1398 */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index d18b1dd49fab..6755cf5ac109 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -117,6 +117,11 @@ enum pci_dev_flags {
117 PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG = (__force pci_dev_flags_t) 1, 117 PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG = (__force pci_dev_flags_t) 1,
118}; 118};
119 119
120enum pci_irq_reroute_variant {
121 INTEL_IRQ_REROUTE_VARIANT = 1,
122 MAX_IRQ_REROUTE_VARIANTS = 3
123};
124
120typedef unsigned short __bitwise pci_bus_flags_t; 125typedef unsigned short __bitwise pci_bus_flags_t;
121enum pci_bus_flags { 126enum pci_bus_flags {
122 PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1, 127 PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1,
@@ -194,6 +199,7 @@ struct pci_dev {
194 unsigned int no_d1d2:1; /* only allow d0 or d3 */ 199 unsigned int no_d1d2:1; /* only allow d0 or d3 */
195 unsigned int block_ucfg_access:1; /* userspace config space access is blocked */ 200 unsigned int block_ucfg_access:1; /* userspace config space access is blocked */
196 unsigned int broken_parity_status:1; /* Device generates false positive parity */ 201 unsigned int broken_parity_status:1; /* Device generates false positive parity */
202 unsigned int irq_reroute_variant:2; /* device needs IRQ rerouting variant */
197 unsigned int msi_enabled:1; 203 unsigned int msi_enabled:1;
198 unsigned int msix_enabled:1; 204 unsigned int msix_enabled:1;
199 unsigned int is_managed:1; 205 unsigned int is_managed:1;