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);