]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.arch/x86-acpi-reroute-PCI-interrupt-to-legacy-boot-interrupt.patch
Move xen patchset to new version's subdir.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.arch / x86-acpi-reroute-PCI-interrupt-to-legacy-boot-interrupt.patch
diff --git a/src/patches/suse-2.6.27.31/patches.arch/x86-acpi-reroute-PCI-interrupt-to-legacy-boot-interrupt.patch b/src/patches/suse-2.6.27.31/patches.arch/x86-acpi-reroute-PCI-interrupt-to-legacy-boot-interrupt.patch
new file mode 100644 (file)
index 0000000..8c6b3ef
--- /dev/null
@@ -0,0 +1,153 @@
+From: Stefan Assmann <sassmann@suse.de>
+Subject: pci, acpi: reroute PCI interrupt to legacy boot interrupt equivalent
+
+Some chipsets (e.g. intel 6700PXH) generate a legacy INTx when the
+IRQ entry in the chipset's IO-APIC is masked (as, e.g. the RT kernel
+does during interrupt handling). On chipsets where this INTx generation
+cannot be disabled, we reroute the valid interrupts to their legacy
+equivalent to get rid of spurious interrupts that might otherwise bring
+down (vital) interrupt lines through spurious interrupt detection in
+note_interrupt().
+
+This patch benefited from discussions with Alexander Graf, Torsten Duwe,
+Ihno Krumreich, Daniel Gollub, Hannes Reinecke. The conclusions we drew
+and the patch itself are the authors' responsibility alone.
+
+Signed-off-by: Stefan Assmann <sassmann@suse.de>
+Signed-off-by: Olaf Dabrunz <od@suse.de>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+---
+ drivers/acpi/pci_irq.c |   56 +++++++++++++++++++++++++++++++++++++++++++++++++
+ drivers/pci/quirks.c   |   26 ++++++++++++++++++++++
+ include/linux/pci.h    |    6 +++++
+ 3 files changed, 88 insertions(+)
+
+--- a/drivers/acpi/pci_irq.c
++++ b/drivers/acpi/pci_irq.c
+@@ -384,6 +384,27 @@ acpi_pci_free_irq(struct acpi_prt_entry 
+       return irq;
+ }
++#ifdef CONFIG_X86_IO_APIC
++extern int noioapicquirk;
++
++static int bridge_has_boot_interrupt_variant(struct pci_bus *bus)
++{
++      struct pci_bus *bus_it;
++
++      for (bus_it = bus ; bus_it ; bus_it = bus_it->parent) {
++              if (!bus_it->self)
++                      return 0;
++
++              printk(KERN_INFO "vendor=%04x device=%04x\n", bus_it->self->vendor,
++                              bus_it->self->device);
++
++              if (bus_it->self->irq_reroute_variant)
++                      return bus_it->self->irq_reroute_variant;
++      }
++      return 0;
++}
++#endif /* CONFIG_X86_IO_APIC */
++
+ /*
+  * acpi_pci_irq_lookup
+  * success: return IRQ >= 0
+@@ -413,6 +434,41 @@ acpi_pci_irq_lookup(struct pci_bus *bus,
+       }
+       ret = func(entry, triggering, polarity, link);
++
++#ifdef CONFIG_X86_IO_APIC
++      /*
++       * Some chipsets (e.g. intel 6700PXH) generate a legacy INTx when the
++       * IRQ entry in the chipset's IO-APIC is masked (as, e.g. the RT kernel
++       * does during interrupt handling). When this INTx generation cannot be
++       * disabled, we reroute these interrupts to their legacy equivalent to
++       * get rid of spurious interrupts.
++       */
++        if (!noioapicquirk) {
++              switch (bridge_has_boot_interrupt_variant(bus)) {
++              case 0:
++                      /* no rerouting necessary */
++                      break;
++
++              case INTEL_IRQ_REROUTE_VARIANT:
++                      /*
++                       * Remap according to INTx routing table in 6700PXH
++                       * specs, intel order number 302628-002, section
++                       * 2.15.2. Other chipsets (80332, ...) have the same
++                       * mapping and are handled here as well.
++                       */
++                      printk(KERN_INFO "pci irq %d -> rerouted to legacy "
++                                       "irq %d\n", ret, (ret % 4) + 16);
++                      ret = (ret % 4) + 16;
++                      break;
++
++              default:
++                      printk(KERN_INFO "not rerouting irq %d to legacy irq: "
++                                       "unknown mapping\n", ret);
++                      break;
++              }
++      }
++#endif /* CONFIG_X86_IO_APIC */
++
+       return ret;
+ }
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -1425,6 +1425,32 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN
+ #ifdef CONFIG_X86_IO_APIC
+ /*
++ * Boot interrupts on some chipsets cannot be turned off. For these chipsets,
++ * remap the original interrupt in the linux kernel to the boot interrupt, so
++ * that a PCI device's interrupt handler is installed on the boot interrupt
++ * line instead.
++ */
++static void quirk_reroute_to_boot_interrupts_intel(struct pci_dev *dev)
++{
++      if (noioapicquirk)
++              return;
++
++      dev->irq_reroute_variant = INTEL_IRQ_REROUTE_VARIANT;
++
++      printk(KERN_INFO "PCI quirk: reroute interrupts for 0x%04x:0x%04x\n",
++                      dev->vendor, dev->device);
++      return;
++}
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_80333_0,    quirk_reroute_to_boot_interrupts_intel);
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_80333_1,    quirk_reroute_to_boot_interrupts_intel);
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_ESB2_0,     quirk_reroute_to_boot_interrupts_intel);
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_PXH_0,      quirk_reroute_to_boot_interrupts_intel);
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_PXH_1,      quirk_reroute_to_boot_interrupts_intel);
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_PXHV,       quirk_reroute_to_boot_interrupts_intel);
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_80332_0,    quirk_reroute_to_boot_interrupts_intel);
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_80332_1,    quirk_reroute_to_boot_interrupts_intel);
++
++/*
+  * On some chipsets we can disable the generation of legacy INTx boot
+  * interrupts.
+  */
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -133,6 +133,11 @@ enum pci_dev_flags {
+       PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2,
+ };
++enum pci_irq_reroute_variant {
++      INTEL_IRQ_REROUTE_VARIANT = 1,
++      MAX_IRQ_REROUTE_VARIANTS = 3
++};
++
+ typedef unsigned short __bitwise pci_bus_flags_t;
+ enum pci_bus_flags {
+       PCI_BUS_FLAGS_NO_MSI   = (__force pci_bus_flags_t) 1,
+@@ -217,6 +222,7 @@ struct pci_dev {
+       unsigned int    no_msi:1;       /* device may not use msi */
+       unsigned int    block_ucfg_access:1;    /* userspace config space access is blocked */
+       unsigned int    broken_parity_status:1; /* Device generates false positive parity */
++      unsigned int    irq_reroute_variant:2;  /* device needs IRQ rerouting variant */
+       unsigned int    msi_enabled:1;
+       unsigned int    msix_enabled:1;
+       unsigned int    is_managed:1;