Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pinctrl/at91: Fix lockup when IRQ on PIOC and PIOD occurs

With commit 80cc3732 (pinctrl/at91: convert driver to use gpiolib irqchip)
gpiochip_set_chained_irqchip is called for PIOC, PIOD and PIOE. The
associated GPIO chip for the IRQ chip is overwritten each time, because
they share the same hard IRQ line.
Thus if an IRQ occurs on PIOC or PIOD, gpio_irq_handler will only check on
PIOE (the assigned GPIO chip) where no event occured. Thus the IRQ will
not be cleared, retriggering the ISR.
Fix that (like done before) by only set the PIOC GPIO chip to the IRQ chip
and walk the list in the irq handler.

Signed-off-by: Alexander Stein <alexanders83@web.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Alexander Stein and committed by
Linus Walleij
cccb0c3e cdcb0ab6

+13
+13
drivers/pinctrl/pinctrl-at91.c
··· 1453 1453 break; 1454 1454 at91_gpio = at91_gpio->next; 1455 1455 pio = at91_gpio->regbase; 1456 + gpio_chip = &at91_gpio->chip; 1456 1457 continue; 1457 1458 } 1458 1459 ··· 1469 1468 static int at91_gpio_of_irq_setup(struct device_node *node, 1470 1469 struct at91_gpio_chip *at91_gpio) 1471 1470 { 1471 + struct at91_gpio_chip *prev = NULL; 1472 1472 struct irq_data *d = irq_get_irq_data(at91_gpio->pioc_virq); 1473 1473 int ret; 1474 1474 ··· 1494 1492 if (ret) 1495 1493 panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n", 1496 1494 at91_gpio->pioc_idx); 1495 + 1496 + /* Setup chained handler */ 1497 + if (at91_gpio->pioc_idx) 1498 + prev = gpio_chips[at91_gpio->pioc_idx - 1]; 1499 + 1500 + /* The top level handler handles one bank of GPIOs, except 1501 + * on some SoC it can handle up to three... 1502 + * We only set up the handler for the first of the list. 1503 + */ 1504 + if (prev && prev->next == at91_gpio) 1505 + return 0; 1497 1506 1498 1507 /* Then register the chain on the parent IRQ */ 1499 1508 gpiochip_set_chained_irqchip(&at91_gpio->chip,