|
Takashi Iwai |
d7156e |
From 8bbed1eef001fdfc0ee9595f64cc4f769d265af4 Mon Sep 17 00:00:00 2001
|
|
Takashi Iwai |
d7156e |
From: Daniel Kurtz <djkurtz@chromium.org>
|
|
Takashi Iwai |
d7156e |
Date: Mon, 16 Jul 2018 18:57:18 -0600
|
|
Takashi Iwai |
d7156e |
Subject: [PATCH] pinctrl/amd: only handle irq if it is pending and unmasked
|
|
Takashi Iwai |
d7156e |
Git-commit: 8bbed1eef001fdfc0ee9595f64cc4f769d265af4
|
|
Takashi Iwai |
d7156e |
Patch-mainline: v4.19-rc1
|
|
Takashi Iwai |
d7156e |
References: bsc#1051510
|
|
Takashi Iwai |
d7156e |
|
|
Takashi Iwai |
d7156e |
The AMD pinctrl driver demultiplexes GPIO interrupts and fires off their
|
|
Takashi Iwai |
d7156e |
individual handlers.
|
|
Takashi Iwai |
d7156e |
|
|
Takashi Iwai |
d7156e |
If one of these GPIO irqs is configured as a level interrupt, and its
|
|
Takashi Iwai |
d7156e |
downstream handler is a threaded ONESHOT interrupt, the GPIO interrupt
|
|
Takashi Iwai |
d7156e |
source is masked by handle_level_irq() until the eventual return of the
|
|
Takashi Iwai |
d7156e |
threaded irq handler. During this time the level GPIO interrupt status
|
|
Takashi Iwai |
d7156e |
will still report as high until the actual gpio source is cleared - both
|
|
Takashi Iwai |
d7156e |
in the individual GPIO interrupt status bit (INTERRUPT_STS_OFF) and in
|
|
Takashi Iwai |
d7156e |
its corresponding "WAKE_INT_STATUS_REG" bit.
|
|
Takashi Iwai |
d7156e |
|
|
Takashi Iwai |
d7156e |
Thus, if another GPIO interrupt occurs during this time,
|
|
Takashi Iwai |
d7156e |
amd_gpio_irq_handler() will see that the (masked-and-not-yet-cleared)
|
|
Takashi Iwai |
d7156e |
level irq is still pending and incorrectly call its handler again.
|
|
Takashi Iwai |
d7156e |
|
|
Takashi Iwai |
d7156e |
To fix this, have amd_gpio_irq_handler() check for both interrupts status
|
|
Takashi Iwai |
d7156e |
and mask before calling generic_handle_irq().
|
|
Takashi Iwai |
d7156e |
|
|
Takashi Iwai |
d7156e |
Note: Is it possible that this bug was the source of the interrupt storm
|
|
Takashi Iwai |
d7156e |
on Ryzen when using chained interrupts before commit ba714a9c1dea85
|
|
Takashi Iwai |
d7156e |
("pinctrl/amd: Use regular interrupt instead of chained")?
|
|
Takashi Iwai |
d7156e |
|
|
Takashi Iwai |
d7156e |
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
|
|
Takashi Iwai |
d7156e |
Acked-by: Thomas Gleixner <tglx@linutronix.de>
|
|
Takashi Iwai |
d7156e |
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
|
Takashi Iwai |
d7156e |
Acked-by: Takashi Iwai <tiwai@suse.de>
|
|
Takashi Iwai |
d7156e |
|
|
Takashi Iwai |
d7156e |
---
|
|
Takashi Iwai |
d7156e |
drivers/pinctrl/pinctrl-amd.c | 3 ++-
|
|
Takashi Iwai |
d7156e |
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
Takashi Iwai |
d7156e |
|
|
Takashi Iwai |
d7156e |
--- a/drivers/pinctrl/pinctrl-amd.c
|
|
Takashi Iwai |
d7156e |
+++ b/drivers/pinctrl/pinctrl-amd.c
|
|
Takashi Iwai |
d7156e |
@@ -526,7 +526,8 @@ static irqreturn_t amd_gpio_irq_handler(
|
|
Takashi Iwai |
d7156e |
/* Each status bit covers four pins */
|
|
Takashi Iwai |
d7156e |
for (i = 0; i < 4; i++) {
|
|
Takashi Iwai |
d7156e |
regval = readl(regs + i);
|
|
Takashi Iwai |
d7156e |
- if (!(regval & PIN_IRQ_PENDING))
|
|
Takashi Iwai |
d7156e |
+ if (!(regval & PIN_IRQ_PENDING) ||
|
|
Takashi Iwai |
d7156e |
+ !(regval & BIT(INTERRUPT_MASK_OFF)))
|
|
Takashi Iwai |
d7156e |
continue;
|
|
Takashi Iwai |
d7156e |
irq = irq_find_mapping(gc->irqdomain, irqnr + i);
|
|
Takashi Iwai |
d7156e |
generic_handle_irq(irq);
|