diff options
author | Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | 2016-09-05 15:12:38 +0100 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-09-10 02:50:50 +0200 |
commit | 10b68700add43d0c38fedefb7a2b7df931f8e84e (patch) | |
tree | 9a9dab42923bc84a11e1be5003834e0e0015a84a /drivers/acpi/pci_irq.c | |
parent | c6935931c1894ff857616ff8549b61236a19148f (diff) | |
download | linux-10b68700add43d0c38fedefb7a2b7df931f8e84e.tar.gz linux-10b68700add43d0c38fedefb7a2b7df931f8e84e.tar.bz2 linux-10b68700add43d0c38fedefb7a2b7df931f8e84e.zip |
ACPI / PCI: fix GIC irq model default PCI IRQ polarity
On ACPI ARM based systems the GIC interrupt controller
and corresponding interrupt model permit only the high
polarity for level interrupts.
ACPI firmware describes PCI legacy IRQs through entries
in the _PRT objects. Entries in the _PRT can be of two types:
- Static: not configurable, trigger/polarity default to level-low,
_PRT entry defines the global GSI interrupt number
- Configurable: _PRT interrupt entry contains a reference to the
corresponding PCI interrupt link device (that in turn provides the
interrupt descriptor through its _CRS/_PRS methods)
Configurable IRQ entries are not currently allowed by the ACPI
specification on ARM since they can only be used for interrupt pins that
are routable, as per ACPI specifications (version 6.1, 6.2.13):
"[...] There are two ways that _PRT can be used. Typically, the
interrupt input that a given PCI interrupt is on is configurable. For
example, a given PCI interrupt might be configured for either IRQ 10 or
11 on an 8259 interrupt controller. In this model, each interrupt is
represented in the ACPI namespace as a PCI Interrupt Link Device. [...]"
ARM platforms GIC configurations do not allow dynamic IRQ routing,
since routing is statically laid out at synthesis time; therefore PCI
interrupt links cannot be used for PCI legacy IRQ descriptions in the
_PRT on ARM systems.
On the other hand, current core ACPI code handling PCI legacy IRQs
consider IRQ trigger/polarity for static _PRT entries as level-low.
On ARM systems with a GIC interrupt controller and corresponding
ACPI interrupt model this does not work in that GIC interrupt
controller is only capable of handling level interrupts whose
polarity is high (for PCI legacy IRQs - that are level-low by
specification - this means that the legacy IRQs are inverted before
reaching the interrupt controller pin), resulting in IRQ allocation
failures such as:
genirq: Setting trigger mode 8 for irq 18 failed (gic_set_type+0x0/0x48)
Change the default polarity for PCI legacy IRQs to high on systems
booting wth ACPI on platforms with a GIC interrupt controller model,
fixing the discrepancy between specification and HW behaviour.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Tested-by: Duc Dang <dhdang@apm.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/pci_irq.c')
-rw-r--r-- | drivers/acpi/pci_irq.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 2c45dd3acc17..c576a6fe4ebb 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -411,7 +411,15 @@ int acpi_pci_irq_enable(struct pci_dev *dev) int gsi; u8 pin; int triggering = ACPI_LEVEL_SENSITIVE; - int polarity = ACPI_ACTIVE_LOW; + /* + * On ARM systems with the GIC interrupt model, level interrupts + * are always polarity high by specification; PCI legacy + * IRQs lines are inverted before reaching the interrupt + * controller and must therefore be considered active high + * as default. + */ + int polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ? + ACPI_ACTIVE_HIGH : ACPI_ACTIVE_LOW; char *link = NULL; char link_desc[16]; int rc; |