Skip to content

Commit c2ddeb2

Browse files
rafaeljwKAGA-KOKO
authored andcommitted
genirq: Introduce IRQF_COND_ONESHOT and use it in pinctrl-amd
There is a problem when a driver requests a shared interrupt line to run a threaded handler on it without IRQF_ONESHOT set if that flag has been set already for the IRQ in question by somebody else. Namely, the request fails which usually leads to a probe failure even though the driver might have worked just fine with IRQF_ONESHOT, but it does not want to use it by default. Currently, the only way to handle this is to try to request the IRQ without IRQF_ONESHOT, but with IRQF_PROBE_SHARED set and if this fails, try again with IRQF_ONESHOT set. However, this is a bit cumbersome and not very clean. When commit 7a36b90 ("ACPI: OSL: Use a threaded interrupt handler for SCI") switched the ACPI subsystem over to using a threaded interrupt handler for the SCI, it had to use IRQF_ONESHOT for it because that's required due to the way the SCI handler works (it needs to walk all of the enabled GPEs before the interrupt line can be unmasked). The SCI interrupt line is not shared with other users very often due to the SCI handling overhead, but on sone systems it is shared and when the other user of it attempts to install a threaded handler, a flags mismatch related to IRQF_ONESHOT may occur. As it turned out, that happened to the pinctrl-amd driver and so commit 4451e8e ("pinctrl: amd: Add IRQF_ONESHOT to the interrupt request") attempted to address the issue by adding IRQF_ONESHOT to the interrupt flags in that driver, but this is now causing an IRQF_ONESHOT-related mismatch to occur on another system which cannot boot as a result of it. Clearly, pinctrl-amd can work with IRQF_ONESHOT if need be, but it should not set that flag by default, so it needs a way to indicate that to the interrupt subsystem. To that end, introdcuce a new interrupt flag, IRQF_COND_ONESHOT, which will only have effect when the IRQ line is shared and IRQF_ONESHOT has been set for it already, in which case it will be promoted to the latter. This is sufficient for drivers sharing the interrupt line with the SCI as it is requested by the ACPI subsystem before any drivers are probed, so they will always see IRQF_ONESHOT set for the interrupt in question. Fixes: 4451e8e ("pinctrl: amd: Add IRQF_ONESHOT to the interrupt request") Reported-by: Francisco Ayala Le Brun <francisco@videowindow.eu> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Cc: 6.8+ <stable@vger.kernel.org> # 6.8+ Closes: https://lore.kernel.org/lkml/CAN-StX1HqWqi+YW=t+V52-38Mfp5fAz7YHx4aH-CQjgyNiKx3g@mail.gmail.com/ Link: https://lore.kernel.org/r/12417336.O9o76ZdvQC@kreacher
1 parent 4cece76 commit c2ddeb2

File tree

3 files changed

+11
-3
lines changed

3 files changed

+11
-3
lines changed

drivers/pinctrl/pinctrl-amd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1159,7 +1159,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
11591159
}
11601160

11611161
ret = devm_request_irq(&pdev->dev, gpio_dev->irq, amd_gpio_irq_handler,
1162-
IRQF_SHARED | IRQF_ONESHOT, KBUILD_MODNAME, gpio_dev);
1162+
IRQF_SHARED | IRQF_COND_ONESHOT, KBUILD_MODNAME, gpio_dev);
11631163
if (ret)
11641164
goto out2;
11651165

include/linux/interrupt.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@
6767
* later.
6868
* IRQF_NO_DEBUG - Exclude from runnaway detection for IPI and similar handlers,
6969
* depends on IRQF_PERCPU.
70+
* IRQF_COND_ONESHOT - Agree to do IRQF_ONESHOT if already set for a shared
71+
* interrupt.
7072
*/
7173
#define IRQF_SHARED 0x00000080
7274
#define IRQF_PROBE_SHARED 0x00000100
@@ -82,6 +84,7 @@
8284
#define IRQF_COND_SUSPEND 0x00040000
8385
#define IRQF_NO_AUTOEN 0x00080000
8486
#define IRQF_NO_DEBUG 0x00100000
87+
#define IRQF_COND_ONESHOT 0x00200000
8588

8689
#define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND | IRQF_NO_THREAD)
8790

kernel/irq/manage.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,8 +1643,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
16431643
}
16441644

16451645
if (!((old->flags & new->flags) & IRQF_SHARED) ||
1646-
(oldtype != (new->flags & IRQF_TRIGGER_MASK)) ||
1647-
((old->flags ^ new->flags) & IRQF_ONESHOT))
1646+
(oldtype != (new->flags & IRQF_TRIGGER_MASK)))
1647+
goto mismatch;
1648+
1649+
if ((old->flags & IRQF_ONESHOT) &&
1650+
(new->flags & IRQF_COND_ONESHOT))
1651+
new->flags |= IRQF_ONESHOT;
1652+
else if ((old->flags ^ new->flags) & IRQF_ONESHOT)
16481653
goto mismatch;
16491654

16501655
/* All handlers must agree on per-cpuness */

0 commit comments

Comments
 (0)