Commit 0ec4e55e authored by Hui Wang's avatar Hui Wang Committed by Rafael J. Wysocki

ACPI: resources: Add checks for ACPI IRQ override

The laptop keyboard doesn't work on many MEDION notebooks, but the
keyboard works well under Windows and Unix.

Through debugging, we found this log in the dmesg:

 ACPI: IRQ 1 override to edge, high
 pnp 00:03: Plug and Play ACPI device, IDs PNP0303 (active)

 And we checked the IRQ definition in the DSDT, it is:

    IRQ (Level, ActiveLow, Exclusive, )
        {1}

So the BIOS defines the keyboard IRQ to Level_Low, but the Linux
kernel override it to Edge_High. If the Linux kernel is modified
to skip the IRQ override, the keyboard will work normally.

From the existing comment in acpi_dev_get_irqresource(), the override
function only needs to be called when IRQ() or IRQNoFlags() is used
to populate the resource descriptor, and according to Section 6.4.2.1
of ACPI 6.4 [1], if IRQ() is empty or IRQNoFlags() is used, the IRQ
is High true, edge sensitive and non-shareable. ACPICA also assumes
that to be the case (see acpi_rs_set_irq[] in rsirq.c).

In accordance with the above, check 3 additional conditions
(EdgeSensitive, ActiveHigh and Exclusive) when deciding whether or
not to treat an ACPI_RESOURCE_TYPE_IRQ resource as "legacy", in which
case the IRQ override is applicable to it.

Link: https://uefi.org/specs/ACPI/6.4/06_Device_Configuration/Device_Configuration.html#irq-descriptor # [1]
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=213031
BugLink: http://bugs.launchpad.net/bugs/1909814Suggested-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Reported-by: default avatarManuel Krause <manuelkrause@netscape.net>
Tested-by: default avatarManuel Krause <manuelkrause@netscape.net>
Signed-off-by: default avatarHui Wang <hui.wang@canonical.com>
[ rjw: Subject rewrite, changelog edits ]
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 614124be
...@@ -423,6 +423,13 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, ...@@ -423,6 +423,13 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
} }
} }
static bool irq_is_legacy(struct acpi_resource_irq *irq)
{
return irq->triggering == ACPI_EDGE_SENSITIVE &&
irq->polarity == ACPI_ACTIVE_HIGH &&
irq->shareable == ACPI_EXCLUSIVE;
}
/** /**
* acpi_dev_resource_interrupt - Extract ACPI interrupt resource information. * acpi_dev_resource_interrupt - Extract ACPI interrupt resource information.
* @ares: Input ACPI resource object. * @ares: Input ACPI resource object.
...@@ -461,7 +468,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, ...@@ -461,7 +468,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->shareable, true); irq->shareable, irq_is_legacy(irq));
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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment