Re: [PATCH v2] gpio: omap: Fix lost edge interrupts

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

 



cc: Linus, linux-gpio

On 09/26/2017 06:32 AM, Ladislav Michl wrote:
From: Grygorii Strashko <grygorii.strashko@xxxxxx>

Use handle_simple_irq and clear edge interrupts early in
omap_gpio_irq_handler to avoid loosing interrupts.

Acked-by: Grygorii Strashko <grygorii.strashko@xxxxxx>

not sure, but you might need to re-send it with proper cc list.


Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Grygorii Strashko <grygorii.strashko@xxxxxx>
Signed-off-by: Ladislav Michl <ladis@xxxxxxxxxxxxxx>
---
  drivers/gpio/gpio-omap.c |   22 +++++++++++++---------
  1 file changed, 13 insertions(+), 9 deletions(-)

  Changes:
  -v2: use handle_simple_irq to handle edge interrupts

diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index dbf869fb63ce..0c8005285124 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -518,7 +518,13 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
  	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
  		irq_set_handler_locked(d, handle_level_irq);
  	else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-		irq_set_handler_locked(d, handle_edge_irq);
+		/*
+		 * Edge IRQs are already cleared/acked in irq_handler and
+		 * not need to be masked, as result handle_edge_irq()
+		 * logic is excessed here and may cause lose of interrupts.
+		 * So just use handle_simple_irq.
+		 */
+		irq_set_handler_locked(d, handle_simple_irq);
return 0; @@ -678,7 +684,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
  static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
  {
  	void __iomem *isr_reg = NULL;
-	u32 isr;
+	u32 enabled, isr, level_mask;
  	unsigned int bit;
  	struct gpio_bank *bank = gpiobank;
  	unsigned long wa_lock_flags;
@@ -691,23 +697,21 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
  	pm_runtime_get_sync(bank->chip.parent);
while (1) {
-		u32 isr_saved, level_mask = 0;
-		u32 enabled;
-
  		raw_spin_lock_irqsave(&bank->lock, lock_flags);
enabled = omap_get_gpio_irqbank_mask(bank);
-		isr_saved = isr = readl_relaxed(isr_reg) & enabled;
+		isr = readl_relaxed(isr_reg) & enabled;
if (bank->level_mask)
  			level_mask = bank->level_mask & enabled;
+		else
+			level_mask = 0;
/* clear edge sensitive interrupts before handler(s) are
  		called so that we don't miss any interrupt occurred while
  		executing them */
-		omap_disable_gpio_irqbank(bank, isr_saved & ~level_mask);
-		omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
-		omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask);
+		if (isr & ~level_mask)
+			omap_clear_gpio_irqbank(bank, isr & ~level_mask);
raw_spin_unlock_irqrestore(&bank->lock, lock_flags);

--
regards,
-grygorii
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux