]> git.proxmox.com Git - pve-kernel.git/blame - pinctl-amd-ryzen-02-Use-regular-interrupt-instead-of-chained.patch
update kernel source to Ubuntu-4.10.0-26.30
[pve-kernel.git] / pinctl-amd-ryzen-02-Use-regular-interrupt-instead-of-chained.patch
CommitLineData
5aa54b75
FG
1From c075f8efc5513551233dabce366eed01e32b62a4 Mon Sep 17 00:00:00 2001
2From: Thomas Gleixner <tglx@linutronix.de>
3Date: Thu, 1 Jun 2017 13:12:18 +0800
4Subject: [PATCH] pinctrl/amd: Use regular interrupt instead of chained
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9BugLink: https://bugs.launchpad.net/bugs/1671360
10
11The AMD pinctrl driver uses a chained interrupt to demultiplex the GPIO
12interrupts. Kevin Vandeventer reported, that his new AMD Ryzen locks up
13hard on boot when the AMD pinctrl driver is initialized. The reason is an
14interrupt storm. It's not clear whether that's caused by hardware or
15firmware or both.
16
17Using chained interrupts on X86 is a dangerous endavour. If a system is
18misconfigured or the hardware buggy there is no safety net to catch an
19interrupt storm.
20
21Convert the driver to use a regular interrupt for the demultiplex
22handler. This allows the interrupt storm detector to catch the malfunction
23and lets the system boot up.
24
25This should be backported to stable because it's likely that more users run
26into this problem as the AMD Ryzen machines are spreading.
27
28Reported-by: Kevin Vandeventer
29Link: https://bugzilla.suse.com/show_bug.cgi?id=1034261
30Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
31Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
32(backported from commit babdc22b0ccf4ef5a3075ce6e4afc26b7a279faf linux-next)
33Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
34Acked-by: Stefan Bader <stefan.bader@canonical.com>
35Acked-by: Seth Forshee <seth.forshee@canonical.com>
36Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
37
38Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
39---
40 drivers/pinctrl/pinctrl-amd.c | 90 +++++++++++++++++++------------------------
41 1 file changed, 40 insertions(+), 50 deletions(-)
42
43diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
44index cfcf9db02c7d..07a88b83e02b 100644
45--- a/drivers/pinctrl/pinctrl-amd.c
46+++ b/drivers/pinctrl/pinctrl-amd.c
47@@ -478,64 +478,54 @@ static struct irq_chip amd_gpio_irqchip = {
48 .irq_set_type = amd_gpio_irq_set_type,
49 };
50
51-static void amd_gpio_irq_handler(struct irq_desc *desc)
52+#define PIN_IRQ_PENDING (BIT(INTERRUPT_STS_OFF) | BIT(WAKE_STS_OFF))
53+
54+static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
55 {
56- u32 i;
57- u32 off;
58- u32 reg;
59- u32 pin_reg;
60- u64 reg64;
61- int handled = 0;
62- unsigned int irq;
63+ struct amd_gpio *gpio_dev = dev_id;
64+ struct gpio_chip *gc = &gpio_dev->gc;
65+ irqreturn_t ret = IRQ_NONE;
66+ unsigned int i, irqnr;
67 unsigned long flags;
68- struct irq_chip *chip = irq_desc_get_chip(desc);
69- struct gpio_chip *gc = irq_desc_get_handler_data(desc);
70- struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
71+ u32 *regs, regval;
72+ u64 status, mask;
73
74- chained_irq_enter(chip, desc);
75- /*enable GPIO interrupt again*/
76+ /* Read the wake status */
77 raw_spin_lock_irqsave(&gpio_dev->lock, flags);
78- reg = readl(gpio_dev->base + WAKE_INT_STATUS_REG1);
79- reg64 = reg;
80- reg64 = reg64 << 32;
81-
82- reg = readl(gpio_dev->base + WAKE_INT_STATUS_REG0);
83- reg64 |= reg;
84+ status = readl(gpio_dev->base + WAKE_INT_STATUS_REG1);
85+ status <<= 32;
86+ status |= readl(gpio_dev->base + WAKE_INT_STATUS_REG0);
87 raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
88
89- /*
90- * first 46 bits indicates interrupt status.
91- * one bit represents four interrupt sources.
92- */
93- for (off = 0; off < 46 ; off++) {
94- if (reg64 & BIT(off)) {
95- for (i = 0; i < 4; i++) {
96- pin_reg = readl(gpio_dev->base +
97- (off * 4 + i) * 4);
98- if ((pin_reg & BIT(INTERRUPT_STS_OFF)) ||
99- (pin_reg & BIT(WAKE_STS_OFF))) {
100- irq = irq_find_mapping(gc->irqdomain,
101- off * 4 + i);
102- generic_handle_irq(irq);
103- writel(pin_reg,
104- gpio_dev->base
105- + (off * 4 + i) * 4);
106- handled++;
107- }
108- }
109+ /* Bit 0-45 contain the relevant status bits */
110+ status &= (1ULL << 46) - 1;
111+ regs = gpio_dev->base;
112+ for (mask = 1, irqnr = 0; status; mask <<= 1, regs += 4, irqnr += 4) {
113+ if (!(status & mask))
114+ continue;
115+ status &= ~mask;
116+
117+ /* Each status bit covers four pins */
118+ for (i = 0; i < 4; i++) {
119+ regval = readl(regs + i);
120+ if (!(regval & PIN_IRQ_PENDING))
121+ continue;
122+ irq = irq_find_mapping(gc->irqdomain, irqnr + i);
123+ generic_handle_irq(irq);
124+ /* Clear interrupt */
125+ writel(regval, regs + i);
126+ ret = IRQ_HANDLED;
127 }
128 }
129
130- if (handled == 0)
131- handle_bad_irq(desc);
132-
133+ /* Signal EOI to the GPIO unit */
134 raw_spin_lock_irqsave(&gpio_dev->lock, flags);
135- reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
136- reg |= EOI_MASK;
137- writel(reg, gpio_dev->base + WAKE_INT_MASTER_REG);
138+ regval = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
139+ regval |= EOI_MASK;
140+ writel(regval, gpio_dev->base + WAKE_INT_MASTER_REG);
141 raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
142
143- chained_irq_exit(chip, desc);
144+ return ret;
145 }
146
147 static int amd_get_groups_count(struct pinctrl_dev *pctldev)
148@@ -803,10 +793,10 @@ static int amd_gpio_probe(struct platform_device *pdev)
149 goto out2;
150 }
151
152- gpiochip_set_chained_irqchip(&gpio_dev->gc,
153- &amd_gpio_irqchip,
154- irq_base,
155- amd_gpio_irq_handler);
156+ ret = devm_request_irq(&pdev->dev, irq_base, amd_gpio_irq_handler, 0,
157+ KBUILD_MODNAME, gpio_dev);
158+ if (ret)
159+ goto out2;
160
161 platform_set_drvdata(pdev, gpio_dev);
162
163--
1642.11.0
165