[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <ZtUuYXSq8g2Mphuq@den-build>
Date: Mon, 2 Sep 2024 11:17:53 +0800
From: Richard Clark <richard.xnu.clark@...il.com>
To: tglx@...utronix.de
Cc: linux-kernel@...r.kernel.org, linux-arm-kernel@...ts.infradead.org,
torvalds@...ux-foundation.org, richard.xnu.clark@...il.com
Subject: [PATCH] irq: fix the interrupt trigger type override issue
In current implementation, the trigger type in 'flags' when calling request_irq
will override the type value get from the firmware(dt/acpi node) if they are
not consistent, and the overrided trigger type value will be retained by irq_data,
consequently the type value get from the firmware will not match the retained one
next time in case the virq is available.
Thus below error message will be observed by the __2nd__ 'insmod' within the
'insmod - rmmod - insmod' operation sequence for the same device driver kernel
module, in which request_irq(..., IRQ_TYPE_LEVEL_HIGH, ...) is used:
irq: type mismatch, failed to map hwirq-182 for interrupt-controller!
The corresponding 'interrupts' property of that device node is:
interrupts = <0 150 1>;
This commit fixes the above issue by adding a new checker - irqd_trigger_type_was_set:
the irq_create_fwspec_mapping(...) will return the interrupt number directly if the
trigger type has been set previously.
Signed-off-by: Richard Clark <richard.xnu.clark@...il.com>
---
kernel/irq/irqdomain.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index cea8f6874b1f..fb0be8e73c5b 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -895,25 +895,25 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
*/
virq = irq_find_mapping(domain, hwirq);
if (virq) {
+ irq_data = irq_get_irq_data(virq);
+ if (!irq_data) {
+ virq = 0;
+ goto out;
+ }
+
/*
* If the trigger type is not specified or matches the
- * current trigger type then we are done so return the
- * interrupt number.
+ * current trigger type or has been set previously then we are done so
+ * return the interrupt number.
*/
- if (type == IRQ_TYPE_NONE || type == irq_get_trigger_type(virq))
+ if (type == IRQ_TYPE_NONE || type == irq_get_trigger_type(virq) ||
+ irqd_trigger_type_was_set(irq_data))
goto out;
-
/*
* If the trigger type has not been set yet, then set
* it now and return the interrupt number.
*/
if (irq_get_trigger_type(virq) == IRQ_TYPE_NONE) {
- irq_data = irq_get_irq_data(virq);
- if (!irq_data) {
- virq = 0;
- goto out;
- }
-
irqd_set_trigger_type(irq_data, type);
goto out;
}
--
2.34.1
Powered by blists - more mailing lists