lkml.org 
[lkml]   [2020]   [Mar]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 083/155] gpiolib: Fix irq_disable() semantics
    Date
    From: Linus Walleij <linus.walleij@linaro.org>

    commit 8959b304c7062889b1276092cc8590dc1ba98f65 upstream.

    The implementation if .irq_disable() which kicks in between
    the gpiolib and the driver is not properly mimicking the
    expected semantics of the irqchip core: the irqchip will
    call .irq_disable() if that exists, else it will call
    mask_irq() which first checks if .irq_mask() is defined
    before calling it.

    Since we are calling it unconditionally, we get this bug
    from drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c, as it only
    defines .irq_mask_ack and not .irq_mask:

    Unable to handle kernel NULL pointer dereference at virtual address 00000000
    pgd = (ptrval)
    (...)
    PC is at 0x0
    LR is at gpiochip_irq_disable+0x20/0x30

    Fix this by only calling .irq_mask() if it exists.

    Cc: Brian Masney <masneyb@onstation.org>
    Cc: Hans Verkuil <hans.verkuil@cisco.com>
    Cc: stable@vger.kernel.org
    Reviewed-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
    Fixes: 461c1a7d4733 ("gpiolib: override irq_enable/disable")
    Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
    Link: https://lore.kernel.org/r/20200306132326.1329640-1-linus.walleij@linaro.org
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/gpio/gpiolib.c | 9 ++++++++-
    1 file changed, 8 insertions(+), 1 deletion(-)

    --- a/drivers/gpio/gpiolib.c
    +++ b/drivers/gpio/gpiolib.c
    @@ -2194,9 +2194,16 @@ static void gpiochip_irq_disable(struct
    {
    struct gpio_chip *chip = irq_data_get_irq_chip_data(d);

    + /*
    + * Since we override .irq_disable() we need to mimic the
    + * behaviour of __irq_disable() in irq/chip.c.
    + * First call .irq_disable() if it exists, else mimic the
    + * behaviour of mask_irq() which calls .irq_mask() if
    + * it exists.
    + */
    if (chip->irq.irq_disable)
    chip->irq.irq_disable(d);
    - else
    + else if (chip->irq.chip->irq_mask)
    chip->irq.chip->irq_mask(d);
    gpiochip_disable_irq(chip, d->hwirq);
    }

    \
     
     \ /
      Last update: 2020-03-31 11:15    [W:2.441 / U:0.172 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site