x86: boot interrupt reroute fix
Subsystems (4)
v2 cover x86: boot interrupt reroute fix
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
PATCH v2 1/5 ACPI: move struct acpi_prt_entry to actbl1.h
From: Stefan Assmann <[email protected]>
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.
--- drivers/acpi/pci_irq.c | 8 -------- include/acpi/actbl1.h | 10 ++++++++++ 2 files changed, 10 insertions(+), 8 deletions(-)
drivers/acpi/pci_irq.c +0 -8
@@ -45,14 +45,6 @@#define _COMPONENT ACPI_PCI_COMPONENTACPI_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);
include/acpi/actbl1.h +10 -0
@@ -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 */
Signature · 1 line
1.7.3.2
PATCH v2 2/5 ACPI: make acpi_pci_irq_find_prt_entry return a copy of a prt_entry
In reply to Stefan AssmannFrom: Stefan Assmann <[email protected]>
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.
--- drivers/acpi/pci_irq.c | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-)
drivers/acpi/pci_irq.c +9 -2
@@ -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).
Signature · 1 line
1.7.3.2
PATCH v2 3/5 PCI: Add locking to pci_find_upstream_pcie_bridge()
In reply to Stefan AssmannFrom: Stefan Assmann <[email protected]>
pci_find_upstream_pcie_bridge() should take the pci_bus_sem semaphore while reading global PCI structures.
--- drivers/pci/search.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
drivers/pci/search.c +4 -0
@@ -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; }
Signature · 1 line
1.7.3.2
PATCH v2 4/5 PCI: Add header declaration for pci_find_upstream_pcie_bridge()
In reply to Stefan AssmannFrom: Stefan Assmann <[email protected]>
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.
--- include/linux/pci.h | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
include/linux/pci.h +3 -0
@@ -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)
Signature · 1 line
1.7.3.2
PATCH v2 5/5 PCI, ACPI: re-add boot interrupt reroute code in separate files
In reply to Stefan AssmannFrom: Stefan Assmann <[email protected]>
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.
--- 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
arch/x86/include/asm/boot_irq.h new file +28 -0
@@ -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 */
arch/x86/kernel/apic/Makefile +3 -0
@@ -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)
arch/x86/kernel/apic/boot_irq.c new file +63 -0
63 lines not on this page · raw message
drivers/acpi/pci_irq.c +4 -0
@@ -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; }
Signature · 1 line
1.7.3.2
Quoted 16 lines · Stefan Assmann
During the 2.6.29 merge parts of
e1d3a90846b40ad3160bf4b648d36c6badad39acgot 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:
- structacpi_prt_entry
-pci_find_upstream_pcie_bridge()Additionally to not change any information in the global
acpi_prt_listit is desirable to haveacpi_pci_irq_find_prt_entry()return a pointer to a copy of a structacpi_prt_entryinstead of pointer into the globalacpi_prt_list. The callers ofacpi_pci_irq_find_prt_entry()have been updated to free the allocated structure as well.
Quoted 8 lines
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:
- splitpci_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 CacheraQuoted 16 lines · Stefan Assmann
During the 2.6.29 merge parts of
e1d3a90846b40ad3160bf4b648d36c6badad39acgot 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:
- structacpi_prt_entry
-pci_find_upstream_pcie_bridge()Additionally to not change any information in the global
acpi_prt_listit is desirable to haveacpi_pci_irq_find_prt_entry()return a pointer to a copy of a structacpi_prt_entryinstead of pointer into the globalacpi_prt_list. The callers ofacpi_pci_irq_find_prt_entry()have been updated to free the allocated structure as well.
Quoted 8 lines
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:
- splitpci_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