* [PATCH 1/5 v2] ACPI: move struct acpi_prt_entry to actbl1.h
2010-12-02 15:33 [PATCH 0/5 v2] x86: boot interrupt reroute fix Stefan Assmann
@ 2010-12-02 15:33 ` Stefan Assmann
2010-12-02 15:33 ` [PATCH 2/5 v2] ACPI: make acpi_pci_irq_find_prt_entry return a copy of a prt_entry Stefan Assmann
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Stefan Assmann @ 2010-12-02 15:33 UTC (permalink / raw)
To: linux-acpi
Cc: lenb, linux-pci, JBeulich, jbarnes, Stefan Assmann, mingo,
bjorn.helgaas, tglx, Olaf.Dabrunz
From: Stefan Assmann <sassmann@redhat.com>
Moving struct acpi_prt_entry from drivers/acpi/pci_irq.c to
include/acpi/actbl1.h to make it available outside of pci_irq.c. This will
allow the boot interrupt reroute code, and others, to operate with
acpi_prt_entrys.
Signed-off-by: Stefan Assmann <sassmann@redhat.com>
---
drivers/acpi/pci_irq.c | 8 --------
include/acpi/actbl1.h | 10 ++++++++++
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index f907cfb..3bc2164 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -45,14 +45,6 @@
#define _COMPONENT ACPI_PCI_COMPONENT
ACPI_MODULE_NAME("pci_irq");
-struct acpi_prt_entry {
- struct list_head list;
- struct acpi_pci_id id;
- u8 pin;
- acpi_handle link;
- u32 index; /* GSI, or link _CRS index */
-};
-
static LIST_HEAD(acpi_prt_list);
static DEFINE_SPINLOCK(acpi_prt_lock);
diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
index c637b75..bbc46ed 100644
--- a/include/acpi/actbl1.h
+++ b/include/acpi/actbl1.h
@@ -752,6 +752,16 @@ struct acpi_madt_local_x2apic_nmi {
u8 reserved[3];
};
+/* _PRT entry */
+
+struct acpi_prt_entry {
+ struct list_head list;
+ struct acpi_pci_id id;
+ u8 pin;
+ acpi_handle link;
+ u32 index; /* GSI, or link _CRS index */
+};
+
/*
* Common flags fields for MADT subtables
*/
--
1.7.3.2
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 2/5 v2] ACPI: make acpi_pci_irq_find_prt_entry return a copy of a prt_entry
2010-12-02 15:33 [PATCH 0/5 v2] x86: boot interrupt reroute fix Stefan Assmann
2010-12-02 15:33 ` [PATCH 1/5 v2] ACPI: move struct acpi_prt_entry to actbl1.h Stefan Assmann
@ 2010-12-02 15:33 ` Stefan Assmann
2010-12-02 15:33 ` [PATCH 3/5 v2] PCI: Add locking to pci_find_upstream_pcie_bridge() Stefan Assmann
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Stefan Assmann @ 2010-12-02 15:33 UTC (permalink / raw)
To: linux-acpi
Cc: linux-pci, jbarnes, JBeulich, Olaf.Dabrunz, Stefan Assmann, mingo,
bjorn.helgaas, tglx, lenb
From: Stefan Assmann <sassmann@redhat.com>
By returning a pointer to a copy of struct acpi_prt_entry in
acpi_pci_irq_find_prt_entry() the calling code may modify the returned
structure without altering entries in the global acpi_prt_list. Thus the
changes to acpi_prt_entry by the boot interrupt reroute code won't change the
original PRT entries.
Currently there are only two calls for acpi_pci_irq_find_prt_entry() and both
are in acpi_pci_irq_lookup(). acpi_pci_irq_lookup() itself is used only by
acpi_pci_irq_enable() and acpi_pci_irq_disable() so both are also updated to
free the copy of struct acpi_prt_entry appropriately.
Signed-off-by: Stefan Assmann <sassmann@redhat.com>
---
drivers/acpi/pci_irq.c | 11 +++++++++--
1 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 3bc2164..e1632b2 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -60,7 +60,7 @@ static inline char pin_name(int pin)
static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
int pin)
{
- struct acpi_prt_entry *entry;
+ struct acpi_prt_entry *entry, *entry_copy;
int segment = pci_domain_nr(dev->bus);
int bus = dev->bus->number;
int device = PCI_SLOT(dev->devfn);
@@ -72,7 +72,11 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
&& (device == entry->id.device)
&& (pin == entry->pin)) {
spin_unlock(&acpi_prt_lock);
- return entry;
+ entry_copy = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);
+ if (!entry_copy)
+ return NULL;
+ memcpy(entry_copy, entry, sizeof(struct acpi_prt_entry));
+ return entry_copy;
}
}
spin_unlock(&acpi_prt_lock);
@@ -384,6 +388,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
&link);
else
gsi = entry->index;
+ kfree(entry);
} else
gsi = -1;
@@ -453,6 +458,8 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
else
gsi = entry->index;
+ if (entry)
+ kfree(entry);
/*
* TBD: It might be worth clearing dev->irq by magic constant
* (e.g. PCI_UNDEFINED_IRQ).
--
1.7.3.2
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 3/5 v2] PCI: Add locking to pci_find_upstream_pcie_bridge()
2010-12-02 15:33 [PATCH 0/5 v2] x86: boot interrupt reroute fix Stefan Assmann
2010-12-02 15:33 ` [PATCH 1/5 v2] ACPI: move struct acpi_prt_entry to actbl1.h Stefan Assmann
2010-12-02 15:33 ` [PATCH 2/5 v2] ACPI: make acpi_pci_irq_find_prt_entry return a copy of a prt_entry Stefan Assmann
@ 2010-12-02 15:33 ` Stefan Assmann
2010-12-02 15:33 ` [PATCH 4/5 v2] PCI: Add header declaration for pci_find_upstream_pcie_bridge() Stefan Assmann
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Stefan Assmann @ 2010-12-02 15:33 UTC (permalink / raw)
To: linux-acpi
Cc: lenb, linux-pci, JBeulich, jbarnes, Stefan Assmann, mingo,
bjorn.helgaas, tglx, Olaf.Dabrunz
From: Stefan Assmann <sassmann@redhat.com>
pci_find_upstream_pcie_bridge() should take the pci_bus_sem semaphore while
reading global PCI structures.
Signed-off-by: Stefan Assmann <sassmann@redhat.com>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
drivers/pci/search.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 9d75dc8..c8159b0 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -29,6 +29,8 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
if (pci_is_pcie(pdev))
return NULL;
+
+ down_read(&pci_bus_sem);
while (1) {
if (pci_is_root_bus(pdev->bus))
break;
@@ -38,6 +40,7 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
tmp = pdev;
continue;
}
+ up_read(&pci_bus_sem);
/* PCI device should connect to a PCIe bridge */
if (pdev->pcie_type != PCI_EXP_TYPE_PCI_BRIDGE) {
/* Busted hardware? */
@@ -46,6 +49,7 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
}
return pdev;
}
+ up_read(&pci_bus_sem);
return tmp;
}
--
1.7.3.2
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 4/5 v2] PCI: Add header declaration for pci_find_upstream_pcie_bridge()
2010-12-02 15:33 [PATCH 0/5 v2] x86: boot interrupt reroute fix Stefan Assmann
` (2 preceding siblings ...)
2010-12-02 15:33 ` [PATCH 3/5 v2] PCI: Add locking to pci_find_upstream_pcie_bridge() Stefan Assmann
@ 2010-12-02 15:33 ` Stefan Assmann
2010-12-02 15:34 ` [PATCH 5/5 v2] PCI, ACPI: re-add boot interrupt reroute code in separate files Stefan Assmann
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Stefan Assmann @ 2010-12-02 15:33 UTC (permalink / raw)
To: linux-acpi
Cc: linux-pci, jbarnes, JBeulich, Olaf.Dabrunz, Stefan Assmann, mingo,
bjorn.helgaas, tglx, lenb
From: Stefan Assmann <sassmann@redhat.com>
Add header declaration for pci_find_upstream_pcie_bridge to pci.h. This will
allow the boot interrupt reroute code, and others, to make use of the
implementation.
Signed-off-by: Stefan Assmann <sassmann@redhat.com>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
include/linux/pci.h | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 7454408..7acb6b2 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -698,6 +698,7 @@ int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn,
int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
+struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev);
struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
struct pci_dev *from);
@@ -1208,6 +1209,8 @@ static inline void pci_unblock_user_cfg_access(struct pci_dev *dev)
static inline struct pci_bus *pci_find_next_bus(const struct pci_bus *from)
{ return NULL; }
+static inline struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
+{ return NULL; }
static inline struct pci_dev *pci_get_slot(struct pci_bus *bus,
unsigned int devfn)
--
1.7.3.2
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 5/5 v2] PCI, ACPI: re-add boot interrupt reroute code in separate files
2010-12-02 15:33 [PATCH 0/5 v2] x86: boot interrupt reroute fix Stefan Assmann
` (3 preceding siblings ...)
2010-12-02 15:33 ` [PATCH 4/5 v2] PCI: Add header declaration for pci_find_upstream_pcie_bridge() Stefan Assmann
@ 2010-12-02 15:34 ` Stefan Assmann
2010-12-09 15:19 ` [PATCH 0/5 v2] x86: boot interrupt reroute fix Stefan Assmann
2011-01-11 10:38 ` Stefan Assmann
6 siblings, 0 replies; 8+ messages in thread
From: Stefan Assmann @ 2010-12-02 15:34 UTC (permalink / raw)
To: linux-acpi
Cc: lenb, linux-pci, JBeulich, jbarnes, Stefan Assmann, mingo,
bjorn.helgaas, tglx, Olaf.Dabrunz
From: Stefan Assmann <sassmann@redhat.com>
During the 2.6.29 merge major parts of e1d3a90846b40ad3160bf4b648d36c6badad39ac
got lost because of other ACPI changes. As suggested by Ingo Molnar the missing
boot interrupt reroute parts are re-added in separate files. The code has
been updated to be less ifdeffy and play along with the current ACPI code. The
printks have been converted to dev_info(). Also the implementation of
bridge_has_boot_interrupt_variant() has been dropped in favor to the existing
pci_find_upstream_pcie_bridge().
By request of Bjorn Helgaas I've created a bugzilla entry at
https://bugzilla.kernel.org/show_bug.cgi?id=21882
to gather information about the boot interrupt reroute problem.
Signed-off-by: Stefan Assmann <sassmann@redhat.com>
---
arch/x86/include/asm/boot_irq.h | 28 +++++++++++++++++
arch/x86/kernel/apic/Makefile | 3 ++
arch/x86/kernel/apic/boot_irq.c | 63 +++++++++++++++++++++++++++++++++++++++
drivers/acpi/pci_irq.c | 4 ++
4 files changed, 98 insertions(+), 0 deletions(-)
create mode 100644 arch/x86/include/asm/boot_irq.h
create mode 100644 arch/x86/kernel/apic/boot_irq.c
diff --git a/arch/x86/include/asm/boot_irq.h b/arch/x86/include/asm/boot_irq.h
new file mode 100644
index 0000000..0cc35e1
--- /dev/null
+++ b/arch/x86/include/asm/boot_irq.h
@@ -0,0 +1,28 @@
+#ifndef _ASM_X86_BOOT_IRQ_H
+#define _ASM_X86_BOOT_IRQ_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Workaround for boot interrupts that cannot be disabled in hardware: makes
+ * affected devices always use the boot interrupt, the original interrupt line
+ * for the device remains disabled.
+ */
+
+#include <linux/pci.h>
+#ifdef CONFIG_ACPI
+#include <linux/acpi.h>
+#endif /* CONFIG_ACPI */
+
+#ifdef CONFIG_X86_IO_APIC
+#ifdef CONFIG_ACPI
+extern struct acpi_prt_entry *boot_irq_reroute (struct pci_dev *dev, struct acpi_prt_entry *entry);
+#endif /* CONFIG_ACPI */
+#else
+static inline struct acpi_prt_entry *boot_irq_reroute (struct pci_dev *dev, struct acpi_prt_entry *entry)
+ { return entry; }
+#endif /* CONFIG_X86_IO_APIC */
+
+#endif /* _ASM_X86_BOOT_IRQ_H */
diff --git a/arch/x86/kernel/apic/Makefile b/arch/x86/kernel/apic/Makefile
index 910f20b..4603b66 100644
--- a/arch/x86/kernel/apic/Makefile
+++ b/arch/x86/kernel/apic/Makefile
@@ -9,6 +9,9 @@ endif
obj-$(CONFIG_HARDLOCKUP_DETECTOR) += hw_nmi.o
obj-$(CONFIG_X86_IO_APIC) += io_apic.o
+ifeq ($(CONFIG_ACPI),y)
+obj-$(CONFIG_X86_IO_APIC) += boot_irq.o
+endif
obj-$(CONFIG_SMP) += ipi.o
ifeq ($(CONFIG_X86_64),y)
diff --git a/arch/x86/kernel/apic/boot_irq.c b/arch/x86/kernel/apic/boot_irq.c
new file mode 100644
index 0000000..297d590
--- /dev/null
+++ b/arch/x86/kernel/apic/boot_irq.c
@@ -0,0 +1,63 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Workaround for boot interrupts that cannot be disabled in hardware: makes
+ * affected devices always use the boot interrupt, the original interrupt line
+ * for the device remains disabled.
+ */
+
+#include <linux/types.h>
+#include <asm/boot_irq.h>
+
+/*
+ * On it's way to the CPU a PCI IRQ might pass multiple PCI bridges therefore
+ * we need to inspect all of them.
+ */
+static int boot_irq_check_broken_bridge(struct pci_dev *pdev)
+{
+ struct pci_dev *tmp_pdev;
+
+ tmp_pdev = pci_find_upstream_pcie_bridge(pdev);
+
+ if (tmp_pdev)
+ return tmp_pdev->irq_reroute_variant;
+ else
+ return 0;
+}
+
+/*
+ * 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.
+ */
+struct acpi_prt_entry *boot_irq_reroute(struct pci_dev *dev, struct acpi_prt_entry *entry)
+{
+ u32 orig_index;
+
+ switch (boot_irq_check_broken_bridge(dev)) {
+ case 0:
+ break; /* no rerouting necessary */
+
+ 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.
+ */
+ orig_index = entry->index;
+ entry->index = (entry->index % 4) + 16;
+ dev_info(&dev->dev, "PCI IRQ %d -> rerouted to legacy boot IRQ %d\n", orig_index, entry->index);
+ break;
+
+ default:
+ dev_info(&dev->dev, "Not rerouting PCI IRQ %d: unknown mapping\n", entry->index);
+ break;
+ }
+
+ return entry;
+}
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index e1632b2..83eb5f6 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -39,6 +39,7 @@
#include <linux/slab.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
+#include <asm/boot_irq.h>
#define PREFIX "ACPI: "
@@ -309,6 +310,9 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
if (entry) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n",
pci_name(dev), pin_name(pin)));
+ if (!noioapicquirk)
+ entry = boot_irq_reroute(dev, entry);
+
return entry;
}
--
1.7.3.2
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH 0/5 v2] x86: boot interrupt reroute fix
2010-12-02 15:33 [PATCH 0/5 v2] x86: boot interrupt reroute fix Stefan Assmann
` (4 preceding siblings ...)
2010-12-02 15:34 ` [PATCH 5/5 v2] PCI, ACPI: re-add boot interrupt reroute code in separate files Stefan Assmann
@ 2010-12-09 15:19 ` Stefan Assmann
2011-01-11 10:38 ` Stefan Assmann
6 siblings, 0 replies; 8+ messages in thread
From: Stefan Assmann @ 2010-12-09 15:19 UTC (permalink / raw)
To: lenb
Cc: linux-acpi, linux-pci, jbarnes, JBeulich, Olaf.Dabrunz, mingo,
bjorn.helgaas, tglx
On 02.12.2010 16:33, Stefan Assmann wrote:
> During the 2.6.29 merge parts of e1d3a90846b40ad3160bf4b648d36c6badad39ac got
> lost because of other ACPI changes. This patchset gets the reroute code working
> again with the current ACPI code. As suggested by Ingo Molnar the missing boot
> interrupt reroute parts are re-added in separate files.
> Therefore some smaller changes to the ACPI and PCI code are necessary to allow
> the boot interrupt reroute code to access required structures and functionality.
> In detail, the reroute code requires access to:
> - struct acpi_prt_entry
> - pci_find_upstream_pcie_bridge()
>
> Additionally to not change any information in the global acpi_prt_list it is
> desirable to have acpi_pci_irq_find_prt_entry() return a pointer to a copy of
> a struct acpi_prt_entry instead of pointer into the global acpi_prt_list. The
> callers of acpi_pci_irq_find_prt_entry() have been updated to free the
> allocated structure as well.
>
> By request of Bjorn Helgaas I've created a bugzilla entry at
> https://bugzilla.kernel.org/show_bug.cgi?id=21882
> to gather information about the boot interrupt reroute problem.
>
> Jesse Barnes suggested to integrate the changes through the ACPI tree.
>
> v2:
> - split pci_find_upstream_pcie_bridge() changes into separate patches
ping?
Stefan
--
Stefan Assmann | Red Hat GmbH
Software Engineer | Otto-Hahn-Strasse 20, 85609 Dornach
| HR: Amtsgericht Muenchen HRB 153243
| GF: Brendan Lane, Charlie Peters,
sassmann at redhat.com | Michael Cunningham, Charles Cachera
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH 0/5 v2] x86: boot interrupt reroute fix
2010-12-02 15:33 [PATCH 0/5 v2] x86: boot interrupt reroute fix Stefan Assmann
` (5 preceding siblings ...)
2010-12-09 15:19 ` [PATCH 0/5 v2] x86: boot interrupt reroute fix Stefan Assmann
@ 2011-01-11 10:38 ` Stefan Assmann
6 siblings, 0 replies; 8+ messages in thread
From: Stefan Assmann @ 2011-01-11 10:38 UTC (permalink / raw)
To: jbarnes
Cc: linux-acpi, linux-pci, JBeulich, Olaf.Dabrunz, mingo,
bjorn.helgaas, tglx, lenb
On 02.12.2010 16:33, Stefan Assmann wrote:
> During the 2.6.29 merge parts of e1d3a90846b40ad3160bf4b648d36c6badad39ac got
> lost because of other ACPI changes. This patchset gets the reroute code working
> again with the current ACPI code. As suggested by Ingo Molnar the missing boot
> interrupt reroute parts are re-added in separate files.
> Therefore some smaller changes to the ACPI and PCI code are necessary to allow
> the boot interrupt reroute code to access required structures and functionality.
> In detail, the reroute code requires access to:
> - struct acpi_prt_entry
> - pci_find_upstream_pcie_bridge()
>
> Additionally to not change any information in the global acpi_prt_list it is
> desirable to have acpi_pci_irq_find_prt_entry() return a pointer to a copy of
> a struct acpi_prt_entry instead of pointer into the global acpi_prt_list. The
> callers of acpi_pci_irq_find_prt_entry() have been updated to free the
> allocated structure as well.
>
> By request of Bjorn Helgaas I've created a bugzilla entry at
> https://bugzilla.kernel.org/show_bug.cgi?id=21882
> to gather information about the boot interrupt reroute problem.
>
> Jesse Barnes suggested to integrate the changes through the ACPI tree.
>
> v2:
> - split pci_find_upstream_pcie_bridge() changes into separate patches
No response from the ACPI side.
Jesse,
could you take the PCI changes (patches 3 and 4) through your tree?
Stefan
--
Stefan Assmann | Red Hat GmbH
Software Engineer | Otto-Hahn-Strasse 20, 85609 Dornach
| HR: Amtsgericht Muenchen HRB 153243
| GF: Brendan Lane, Charlie Peters,
sassmann at redhat.com | Michael Cunningham, Charles Cachera
^ permalink raw reply [flat|nested] 8+ messages in thread