lkml.org 
[lkml]   [2022]   [Jan]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 5.16 071/217] gpiolib: acpi: Do not set the IRQ type if the IRQ is already in use
    Date
    From: Hans de Goede <hdegoede@redhat.com>

    [ Upstream commit bdfd6ab8fdccd8b138837efff66f4a1911496378 ]

    If the IRQ is already in use, then acpi_dev_gpio_irq_get_by() really
    should not change the type underneath the current owner.

    I specifically hit an issue with this an a Chuwi Hi8 Super (CWI509) Bay
    Trail tablet, when the Boot OS selection in the BIOS is set to Android.
    In this case _STA for a MAX17047 ACPI I2C device wrongly returns 0xf and
    the _CRS resources for this device include a GpioInt pointing to a GPIO
    already in use by an _AEI handler, with a different type then specified
    in the _CRS for the MAX17047 device. Leading to the acpi_dev_gpio_irq_get()
    call done by the i2c-core-acpi.c code changing the type breaking the
    _AEI handler.

    Now this clearly is a bug in the DSDT of this tablet (in Android mode),
    but in general calling irq_set_irq_type() on an IRQ which already is
    in use seems like a bad idea.

    Signed-off-by: Hans de Goede <hdegoede@redhat.com>
    Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/gpio/gpiolib-acpi.c | 15 +++++++++++----
    1 file changed, 11 insertions(+), 4 deletions(-)

    diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
    index 985e8589c58ba..feb8157d2d672 100644
    --- a/drivers/gpio/gpiolib-acpi.c
    +++ b/drivers/gpio/gpiolib-acpi.c
    @@ -1056,10 +1056,17 @@ int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int ind
    irq_flags = acpi_dev_get_irq_type(info.triggering,
    info.polarity);

    - /* Set type if specified and different than the current one */
    - if (irq_flags != IRQ_TYPE_NONE &&
    - irq_flags != irq_get_trigger_type(irq))
    - irq_set_irq_type(irq, irq_flags);
    + /*
    + * If the IRQ is not already in use then set type
    + * if specified and different than the current one.
    + */
    + if (can_request_irq(irq, irq_flags)) {
    + if (irq_flags != IRQ_TYPE_NONE &&
    + irq_flags != irq_get_trigger_type(irq))
    + irq_set_irq_type(irq, irq_flags);
    + } else {
    + dev_dbg(&adev->dev, "IRQ %d already in use\n", irq);
    + }

    return irq;
    }
    --
    2.34.1
    \
     
     \ /
      Last update: 2022-01-18 03:26    [W:4.229 / U:1.176 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site