diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-amd.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-amd.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index 9b9c61e3f065..2c61141519f8 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -565,15 +565,25 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id) !(regval & BIT(INTERRUPT_MASK_OFF))) continue; irq = irq_find_mapping(gc->irq.domain, irqnr + i); - generic_handle_irq(irq); + if (irq != 0) + generic_handle_irq(irq); /* Clear interrupt. * We must read the pin register again, in case the * value was changed while executing * generic_handle_irq() above. + * If we didn't find a mapping for the interrupt, + * disable it in order to avoid a system hang caused + * by an interrupt storm. */ raw_spin_lock_irqsave(&gpio_dev->lock, flags); regval = readl(regs + i); + if (irq == 0) { + regval &= ~BIT(INTERRUPT_ENABLE_OFF); + dev_dbg(&gpio_dev->pdev->dev, + "Disabling spurious GPIO IRQ %d\n", + irqnr + i); + } writel(regval, regs + i); raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); ret = IRQ_HANDLED; @@ -861,10 +871,8 @@ static int amd_gpio_probe(struct platform_device *pdev) return -ENOMEM; irq_base = platform_get_irq(pdev, 0); - if (irq_base < 0) { - dev_err(&pdev->dev, "Failed to get gpio IRQ: %d\n", irq_base); + if (irq_base < 0) return irq_base; - } #ifdef CONFIG_PM_SLEEP gpio_dev->saved_regs = devm_kcalloc(&pdev->dev, amd_pinctrl_desc.npins, |