* [PATCH 0/4] x86: boot interrupt reroute fix
@ 2010-11-18 13:51 Stefan Assmann
2010-11-18 13:52 ` [PATCH 1/4] ACPI: move struct acpi_prt_entry to actbl1.h Stefan Assmann
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Stefan Assmann @ 2010-11-18 13:51 UTC (permalink / raw)
To: linux-pci
Cc: JBeulich, linux-acpi, Olaf.Dabrunz, Stefan Assmann, mingo,
bjorn.helgaas, tglx, lenb
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 boot interrupt
reroute code has been split into its own file.
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.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/4] ACPI: move struct acpi_prt_entry to actbl1.h
2010-11-18 13:51 [PATCH 0/4] x86: boot interrupt reroute fix Stefan Assmann
@ 2010-11-18 13:52 ` Stefan Assmann
2010-11-18 13:52 ` [PATCH 2/4] ACPI: make acpi_pci_irq_find_prt_entry return a copy of a prt_entry Stefan Assmann
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Stefan Assmann @ 2010-11-18 13:52 UTC (permalink / raw)
To: linux-pci
Cc: lenb, JBeulich, linux-acpi, Stefan Assmann, mingo, Olaf.Dabrunz,
tglx, bjorn.helgaas
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.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/4] ACPI: make acpi_pci_irq_find_prt_entry return a copy of a prt_entry
2010-11-18 13:51 [PATCH 0/4] x86: boot interrupt reroute fix Stefan Assmann
2010-11-18 13:52 ` [PATCH 1/4] ACPI: move struct acpi_prt_entry to actbl1.h Stefan Assmann
@ 2010-11-18 13:52 ` Stefan Assmann
2010-11-18 13:52 ` [PATCH 3/4] PCI: fix locking for pci_find_upstream_pcie_bridge and add declaration Stefan Assmann
2010-11-18 13:52 ` [PATCH 4/4] PCI, ACPI: re-add boot interrupt reroute code in separate files Stefan Assmann
3 siblings, 0 replies; 6+ messages in thread
From: Stefan Assmann @ 2010-11-18 13:52 UTC (permalink / raw)
To: linux-pci
Cc: JBeulich, bjorn.helgaas, linux-acpi, Stefan Assmann, mingo, lenb,
tglx, Olaf.Dabrunz
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..02202a2 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.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/4] PCI: fix locking for pci_find_upstream_pcie_bridge and add declaration
2010-11-18 13:51 [PATCH 0/4] x86: boot interrupt reroute fix Stefan Assmann
2010-11-18 13:52 ` [PATCH 1/4] ACPI: move struct acpi_prt_entry to actbl1.h Stefan Assmann
2010-11-18 13:52 ` [PATCH 2/4] ACPI: make acpi_pci_irq_find_prt_entry return a copy of a prt_entry Stefan Assmann
@ 2010-11-18 13:52 ` Stefan Assmann
2010-11-18 18:18 ` Jesse Barnes
2010-11-18 13:52 ` [PATCH 4/4] PCI, ACPI: re-add boot interrupt reroute code in separate files Stefan Assmann
3 siblings, 1 reply; 6+ messages in thread
From: Stefan Assmann @ 2010-11-18 13:52 UTC (permalink / raw)
To: linux-pci
Cc: JBeulich, linux-acpi, Olaf.Dabrunz, Stefan Assmann, mingo,
bjorn.helgaas, tglx, lenb
From: Stefan Assmann <sassmann@redhat.com>
Add header declaration of pci_find_upstream_pcie_bridge to pci.h. This will
allow the boot interrupt reroute code, and others, to make use of this
implementation. Also pci_find_upstream_pcie_bridge should take the pci_bus_sem
semaphore while reading global PCI structures, so update the locking as well.
Signed-off-by: Stefan Assmann <sassmann@redhat.com>
---
drivers/pci/search.c | 4 ++++
include/linux/pci.h | 3 +++
2 files changed, 7 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;
}
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.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 4/4] PCI, ACPI: re-add boot interrupt reroute code in separate files
2010-11-18 13:51 [PATCH 0/4] x86: boot interrupt reroute fix Stefan Assmann
` (2 preceding siblings ...)
2010-11-18 13:52 ` [PATCH 3/4] PCI: fix locking for pci_find_upstream_pcie_bridge and add declaration Stefan Assmann
@ 2010-11-18 13:52 ` Stefan Assmann
3 siblings, 0 replies; 6+ messages in thread
From: Stefan Assmann @ 2010-11-18 13:52 UTC (permalink / raw)
To: linux-pci
Cc: lenb, JBeulich, linux-acpi, Stefan Assmann, mingo, Olaf.Dabrunz,
tglx, bjorn.helgaas
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 a separate file. 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] 6+ messages in thread
* Re: [PATCH 3/4] PCI: fix locking for pci_find_upstream_pcie_bridge and add declaration
2010-11-18 13:52 ` [PATCH 3/4] PCI: fix locking for pci_find_upstream_pcie_bridge and add declaration Stefan Assmann
@ 2010-11-18 18:18 ` Jesse Barnes
0 siblings, 0 replies; 6+ messages in thread
From: Jesse Barnes @ 2010-11-18 18:18 UTC (permalink / raw)
To: Stefan Assmann
Cc: linux-pci, JBeulich, linux-acpi, Olaf.Dabrunz, mingo,
bjorn.helgaas, tglx, lenb
On Thu, 18 Nov 2010 08:52:28 -0500
Stefan Assmann <sassmann@redhat.com> wrote:
> From: Stefan Assmann <sassmann@redhat.com>
>
> Add header declaration of pci_find_upstream_pcie_bridge to pci.h. This will
> allow the boot interrupt reroute code, and others, to make use of this
> implementation. Also pci_find_upstream_pcie_bridge should take the pci_bus_sem
> semaphore while reading global PCI structures, so update the locking as well.
>
> Signed-off-by: Stefan Assmann <sassmann@redhat.com>
> ---
You should split this into two patches just to keep things separate,
but other than that it looks fine. I assume this set will go through
the ACPI tree, you can add my:
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
--
Jesse Barnes, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2010-11-18 18:18 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-18 13:51 [PATCH 0/4] x86: boot interrupt reroute fix Stefan Assmann
2010-11-18 13:52 ` [PATCH 1/4] ACPI: move struct acpi_prt_entry to actbl1.h Stefan Assmann
2010-11-18 13:52 ` [PATCH 2/4] ACPI: make acpi_pci_irq_find_prt_entry return a copy of a prt_entry Stefan Assmann
2010-11-18 13:52 ` [PATCH 3/4] PCI: fix locking for pci_find_upstream_pcie_bridge and add declaration Stefan Assmann
2010-11-18 18:18 ` Jesse Barnes
2010-11-18 13:52 ` [PATCH 4/4] PCI, ACPI: re-add boot interrupt reroute code in separate files Stefan Assmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).