[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220530080842.37024-4-manivannan.sadhasivam@linaro.org>
Date: Mon, 30 May 2022 13:38:42 +0530
From: Manivannan Sadhasivam <manivannan.sadhasivam@...aro.org>
To: tglx@...utronix.de, maz@...nel.org, bjorn.andersson@...aro.org
Cc: linux-kernel@...r.kernel.org, linux-arm-msm@...r.kernel.org,
Manivannan Sadhasivam <manivannan.sadhasivam@...aro.org>
Subject: [PATCH 3/3] genirq: Check for trigger type mismatch in __setup_irq()
Currently, if the trigger type defined by the platform like DT does not
match the driver requested trigger type, the below warning is shown
during platform_get_irq() but only during the second time of the drive
probe (due to probe deferral or module unload/load).
irq: type mismatch, failed to map hwirq-9 for interrupt-controller@...0000!
Consider a typical usecase of requesting an IRQ in a driver:
```
/* Assume DT has set the trigger type to IRQF_TYPE_LEVEL_HIGH */
q6v5->wdog_irq = platform_get_irq_byname(pdev, "wdog");
if (q6v5->wdog_irq <= 0)
return q6v5->wdog_irq;
ret = devm_request_threaded_irq(&pdev->dev, q6v5->wdog_irq,
NULL, q6v5_wdog_interrupt,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"q6v5 wdog", q6v5);
if (ret) {
dev_err(&pdev->dev, "failed to acquire wdog IRQ\n");
return ret;
}
```
For the first time probe of a driver, platform_get_irq_byname() does not
return an error and it sets the platform requested trigger type. Then,
request_irq() also does not check for the trigger type mismatch and sets
the driver requested trigger type. Later if the driver gets probed again,
platform_get_irq() throws the "type mismatch" warning and fails.
Ideally, request_irq() should throw the error during the first time itself,
when it detects the trigger type mismatch. So let's add a check in
__setup_irq() for checking the trigger type mismatch.
It should be noted that the platform trigger type could be IRQ_TYPE_NONE
in some cases like IRQ controller inside the GPIOCHIP. For those cases,
the check should be skipped.
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@...aro.org>
---
kernel/irq/manage.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index c03f71d5ec10..dd28c4944172 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1480,8 +1480,18 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
* If the trigger type is not specified by the caller,
* then use the default for this interrupt.
*/
- if (!(new->flags & IRQF_TRIGGER_MASK))
- new->flags |= irqd_get_trigger_type(&desc->irq_data);
+ flags = irqd_get_trigger_type(&desc->irq_data);
+ if (!(new->flags & IRQF_TRIGGER_MASK)) {
+ new->flags |= flags;
+ } else if (flags && ((new->flags & IRQF_TRIGGER_MASK) != flags)) {
+ /*
+ * Bail out if the default trigger is not IRQ_TYPE_NONE and the
+ * caller specified trigger does not match the default trigger type.
+ */
+ pr_err("Trigger type %u does not match default type %lu for %s (irq %d)\n",
+ new->flags & IRQF_TRIGGER_MASK, flags, new->name, irq);
+ return -EINVAL;
+ }
/*
* Check whether the interrupt nests into another interrupt
--
2.25.1
Powered by blists - more mailing lists