Patch "pinctrl: ocelot: Fix incorrect trigger of the interrupt." has been added to the 6.0-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    pinctrl: ocelot: Fix incorrect trigger of the interrupt.

to the 6.0-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     pinctrl-ocelot-fix-incorrect-trigger-of-the-interrup.patch
and it can be found in the queue-6.0 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 1b5ab5b4fdf875d73792408199ef27638be73e7a
Author: Horatiu Vultur <horatiu.vultur@xxxxxxxxxxxxx>
Date:   Tue Oct 18 09:09:59 2022 +0200

    pinctrl: ocelot: Fix incorrect trigger of the interrupt.
    
    [ Upstream commit e9945b2633deccda74a769d94060df49c53ff181 ]
    
    The interrupt controller can detect only link changes. So in case an
    external device generated a level based interrupt, then the interrupt
    controller detected correctly the first edge. But the problem was that
    the interrupt controller was detecting also the edge when the interrupt
    was cleared. So it would generate another interrupt.
    The fix for this is to clear the second interrupt but still check the
    interrupt line status.
    
    Fixes: c297561bc98a ("pinctrl: ocelot: Fix interrupt controller")
    Signed-off-by: Horatiu Vultur <horatiu.vultur@xxxxxxxxxxxxx>
    Tested-by: Michael Walle <michael@xxxxxxxx>
    Link: https://lore.kernel.org/r/20221018070959.1322606-1-horatiu.vultur@xxxxxxxxxxxxx
    Signed-off-by: Linus Walleij <linus.walleij@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c
index c7df8c5fe585..105771ff82e6 100644
--- a/drivers/pinctrl/pinctrl-ocelot.c
+++ b/drivers/pinctrl/pinctrl-ocelot.c
@@ -1863,19 +1863,28 @@ static void ocelot_irq_unmask_level(struct irq_data *data)
 	if (val & bit)
 		ack = true;
 
+	/* Try to clear any rising edges */
+	if (!active && ack)
+		regmap_write_bits(info->map, REG(OCELOT_GPIO_INTR, info, gpio),
+				  bit, bit);
+
 	/* Enable the interrupt now */
 	gpiochip_enable_irq(chip, gpio);
 	regmap_update_bits(info->map, REG(OCELOT_GPIO_INTR_ENA, info, gpio),
 			   bit, bit);
 
 	/*
-	 * In case the interrupt line is still active and the interrupt
-	 * controller has not seen any changes in the interrupt line, then it
-	 * means that there happen another interrupt while the line was active.
+	 * In case the interrupt line is still active then it means that
+	 * there happen another interrupt while the line was active.
 	 * So we missed that one, so we need to kick the interrupt again
 	 * handler.
 	 */
-	if (active && !ack) {
+	regmap_read(info->map, REG(OCELOT_GPIO_IN, info, gpio), &val);
+	if ((!(val & bit) && trigger_level == IRQ_TYPE_LEVEL_LOW) ||
+	      (val & bit && trigger_level == IRQ_TYPE_LEVEL_HIGH))
+		active = true;
+
+	if (active) {
 		struct ocelot_irq_work *work;
 
 		work = kmalloc(sizeof(*work), GFP_ATOMIC);



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux