forked from luck/tmp_suning_uos_patched
ACPI / resources: call acpi_get_override_irq() only for legacy IRQ resources
acpi_get_override_irq() was added because there was a problem with
buggy BIOSes passing wrong IRQ() resource for the RTC IRQ. The
commit that added the workaround was 61fd47e0c8
(ACPI: fix two
IRQ8 issues in IOAPIC mode).
With ACPI 5 enumerated devices there are typically one or more
extended IRQ resources per device (and these IRQs can be shared).
However, the acpi_get_override_irq() workaround forces all IRQs in
range 0 - 15 (the legacy ISA IRQs) to be edge triggered, active high
as can be seen from the dmesg below:
ACPI: IRQ 6 override to edge, high
ACPI: IRQ 7 override to edge, high
ACPI: IRQ 7 override to edge, high
ACPI: IRQ 13 override to edge, high
Also /proc/interrupts for the I2C controllers (INT33C2 and INT33C3) shows
the same thing:
7: 4 0 0 0 IO-APIC-edge INT33C2:00, INT33C3:00
The _CSR method for INT33C2 (and INT33C3) device returns following
resource:
Interrupt (ResourceConsumer, Level, ActiveLow, Shared,,, )
{
0x00000007,
}
which states that this is supposed to be level triggered, active low,
shared IRQ instead.
Fix this by making sure that acpi_get_override_irq() gets only called
when we are dealing with legacy IRQ() or IRQNoFlags() descriptors.
While we are there, correct pr_warning() to print the right triggering
value.
This change turns out to be necessary to make DMA work correctly on
systems based on the Intel Lynxpoint PCH (Platform Controller Hub).
[rjw: Changelog]
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: 3.9+ <stable@vger.kernel.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
7d13205581
commit
204ebc0aa3
|
@ -304,7 +304,8 @@ static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
|
static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
|
||||||
u8 triggering, u8 polarity, u8 shareable)
|
u8 triggering, u8 polarity, u8 shareable,
|
||||||
|
bool legacy)
|
||||||
{
|
{
|
||||||
int irq, p, t;
|
int irq, p, t;
|
||||||
|
|
||||||
|
@ -317,14 +318,19 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
|
||||||
* In IO-APIC mode, use overrided attribute. Two reasons:
|
* In IO-APIC mode, use overrided attribute. Two reasons:
|
||||||
* 1. BIOS bug in DSDT
|
* 1. BIOS bug in DSDT
|
||||||
* 2. BIOS uses IO-APIC mode Interrupt Source Override
|
* 2. BIOS uses IO-APIC mode Interrupt Source Override
|
||||||
|
*
|
||||||
|
* We do this only if we are dealing with IRQ() or IRQNoFlags()
|
||||||
|
* resource (the legacy ISA resources). With modern ACPI 5 devices
|
||||||
|
* using extended IRQ descriptors we take the IRQ configuration
|
||||||
|
* from _CRS directly.
|
||||||
*/
|
*/
|
||||||
if (!acpi_get_override_irq(gsi, &t, &p)) {
|
if (legacy && !acpi_get_override_irq(gsi, &t, &p)) {
|
||||||
u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
|
u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
|
||||||
u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
|
u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
|
||||||
|
|
||||||
if (triggering != trig || polarity != pol) {
|
if (triggering != trig || polarity != pol) {
|
||||||
pr_warning("ACPI: IRQ %d override to %s, %s\n", gsi,
|
pr_warning("ACPI: IRQ %d override to %s, %s\n", gsi,
|
||||||
t ? "edge" : "level", p ? "low" : "high");
|
t ? "level" : "edge", p ? "low" : "high");
|
||||||
triggering = trig;
|
triggering = trig;
|
||||||
polarity = pol;
|
polarity = pol;
|
||||||
}
|
}
|
||||||
|
@ -373,7 +379,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
|
||||||
}
|
}
|
||||||
acpi_dev_get_irqresource(res, irq->interrupts[index],
|
acpi_dev_get_irqresource(res, irq->interrupts[index],
|
||||||
irq->triggering, irq->polarity,
|
irq->triggering, irq->polarity,
|
||||||
irq->sharable);
|
irq->sharable, true);
|
||||||
break;
|
break;
|
||||||
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
|
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
|
||||||
ext_irq = &ares->data.extended_irq;
|
ext_irq = &ares->data.extended_irq;
|
||||||
|
@ -383,7 +389,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
|
||||||
}
|
}
|
||||||
acpi_dev_get_irqresource(res, ext_irq->interrupts[index],
|
acpi_dev_get_irqresource(res, ext_irq->interrupts[index],
|
||||||
ext_irq->triggering, ext_irq->polarity,
|
ext_irq->triggering, ext_irq->polarity,
|
||||||
ext_irq->sharable);
|
ext_irq->sharable, false);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user