lkml.org 
[lkml]   [2017]   [Dec]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 080/148] gpio: altera: Use handle_level_irq when configured as a level_high
    Date
    4.9-stable review patch.  If anyone has any objections, please let me know.

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

    From: Phil Reid <preid@electromag.com.au>


    [ Upstream commit f759921cfbf4847319d197a6ed7c9534d593f8bc ]

    When a threaded irq handler is chained attached to one of the gpio
    pins when configure for level irq the altera_gpio_irq_leveL_high_handler
    does not mask the interrupt while being handled by the chained irq.
    This resulting in the threaded irq not getting enough cycles to complete
    quickly enough before the irq was disabled as faulty. handle_level_irq
    should be used in this situation instead of handle_simple_irq.

    In gpiochip_irqchip_add set default handler to handle_bad_irq as
    per Documentation/gpio/driver.txt. Then set the correct handler in
    the set_type callback.

    Signed-off-by: Phil Reid <preid@electromag.com.au>
    Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
    Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/gpio/gpio-altera.c | 26 +++++++++++---------------
    1 file changed, 11 insertions(+), 15 deletions(-)

    --- a/drivers/gpio/gpio-altera.c
    +++ b/drivers/gpio/gpio-altera.c
    @@ -90,21 +90,18 @@ static int altera_gpio_irq_set_type(stru

    altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d));

    - if (type == IRQ_TYPE_NONE)
    + if (type == IRQ_TYPE_NONE) {
    + irq_set_handler_locked(d, handle_bad_irq);
    return 0;
    - if (type == IRQ_TYPE_LEVEL_HIGH &&
    - altera_gc->interrupt_trigger == IRQ_TYPE_LEVEL_HIGH)
    - return 0;
    - if (type == IRQ_TYPE_EDGE_RISING &&
    - altera_gc->interrupt_trigger == IRQ_TYPE_EDGE_RISING)
    - return 0;
    - if (type == IRQ_TYPE_EDGE_FALLING &&
    - altera_gc->interrupt_trigger == IRQ_TYPE_EDGE_FALLING)
    - return 0;
    - if (type == IRQ_TYPE_EDGE_BOTH &&
    - altera_gc->interrupt_trigger == IRQ_TYPE_EDGE_BOTH)
    + }
    + if (type == altera_gc->interrupt_trigger) {
    + if (type == IRQ_TYPE_LEVEL_HIGH)
    + irq_set_handler_locked(d, handle_level_irq);
    + else
    + irq_set_handler_locked(d, handle_simple_irq);
    return 0;
    -
    + }
    + irq_set_handler_locked(d, handle_bad_irq);
    return -EINVAL;
    }

    @@ -230,7 +227,6 @@ static void altera_gpio_irq_edge_handler
    chained_irq_exit(chip, desc);
    }

    -
    static void altera_gpio_irq_leveL_high_handler(struct irq_desc *desc)
    {
    struct altera_gpio_chip *altera_gc;
    @@ -310,7 +306,7 @@ static int altera_gpio_probe(struct plat
    altera_gc->interrupt_trigger = reg;

    ret = gpiochip_irqchip_add(&altera_gc->mmchip.gc, &altera_irq_chip, 0,
    - handle_simple_irq, IRQ_TYPE_NONE);
    + handle_bad_irq, IRQ_TYPE_NONE);

    if (ret) {
    dev_err(&pdev->dev, "could not add irqchip\n");

    \
     
     \ /
      Last update: 2017-12-12 14:11    [W:2.113 / U:0.536 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site