lkml.org 
[lkml]   [2018]   [Nov]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 124/124] gpio: brcmstb: release the bgpio lock during irq handlers
    Date
    4.14-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Doug Berger <opendmb@gmail.com>

    commit 142c168e0e50164e67c9399c28dedd65a307cfe5 upstream.

    The basic memory-mapped GPIO controller lock must be released
    before calling the registered GPIO interrupt handlers to allow
    the interrupt handlers to access the hardware.

    Examples of why a GPIO interrupt handler might want to access
    the GPIO hardware include an interrupt that is configured to
    trigger on rising and falling edges that needs to read the
    current level of the input to know how to respond, or an
    interrupt that causes a change in a GPIO output in the same
    bank. If the lock is not released before enterring the handler
    the hardware accesses will deadlock when they attempt to grab
    the lock.

    Since the lock is only needed to protect the calculation of
    unmasked pending interrupts create a dedicated function to
    perform this and hide the complexity.

    Fixes: 19a7b6940b78 ("gpio: brcmstb: Add interrupt and wakeup source support")
    Signed-off-by: Doug Berger <opendmb@gmail.com>
    Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
    Acked-by: Gregory Fong <gregory.0xf0@gmail.com>
    Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
    Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/gpio/gpio-brcmstb.c | 21 ++++++++++++++++-----
    1 file changed, 16 insertions(+), 5 deletions(-)

    --- a/drivers/gpio/gpio-brcmstb.c
    +++ b/drivers/gpio/gpio-brcmstb.c
    @@ -63,6 +63,21 @@ brcmstb_gpio_gc_to_priv(struct gpio_chip
    return bank->parent_priv;
    }

    +static unsigned long
    +brcmstb_gpio_get_active_irqs(struct brcmstb_gpio_bank *bank)
    +{
    + void __iomem *reg_base = bank->parent_priv->reg_base;
    + unsigned long status;
    + unsigned long flags;
    +
    + spin_lock_irqsave(&bank->gc.bgpio_lock, flags);
    + status = bank->gc.read_reg(reg_base + GIO_STAT(bank->id)) &
    + bank->gc.read_reg(reg_base + GIO_MASK(bank->id));
    + spin_unlock_irqrestore(&bank->gc.bgpio_lock, flags);
    +
    + return status;
    +}
    +
    static void brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank,
    unsigned int offset, bool enable)
    {
    @@ -205,11 +220,8 @@ static void brcmstb_gpio_irq_bank_handle
    struct irq_domain *irq_domain = bank->gc.irqdomain;
    void __iomem *reg_base = priv->reg_base;
    unsigned long status;
    - unsigned long flags;

    - spin_lock_irqsave(&bank->gc.bgpio_lock, flags);
    - while ((status = bank->gc.read_reg(reg_base + GIO_STAT(bank->id)) &
    - bank->gc.read_reg(reg_base + GIO_MASK(bank->id)))) {
    + while ((status = brcmstb_gpio_get_active_irqs(bank))) {
    int bit;

    for_each_set_bit(bit, &status, 32) {
    @@ -224,7 +236,6 @@ static void brcmstb_gpio_irq_bank_handle
    generic_handle_irq(irq_find_mapping(irq_domain, bit));
    }
    }
    - spin_unlock_irqrestore(&bank->gc.bgpio_lock, flags);
    }

    /* Each UPG GIO block has one IRQ for all banks */

    \
     
     \ /
      Last update: 2018-11-19 19:19    [W:4.899 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site