]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
gpio: omap: protect regs access in omap_gpio_irq_handler
authorGrygorii Strashko <grygorii.strashko@ti.com>
Tue, 18 Aug 2015 11:10:55 +0000 (14:10 +0300)
committerLinus Walleij <linus.walleij@linaro.org>
Wed, 26 Aug 2015 07:52:53 +0000 (09:52 +0200)
The access to HW registers has to be be protected in
omap_gpio_irq_handler(), as it may race with code executed on
another CPUs.

Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Acked-by: Santosh Shilimkar <ssantosh@kernel.org>
Tested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/gpio/gpio-omap.c

index 9ed5a675564ccef418b22d9c2186a2ff2b11e679..1f02acd577e3429a5c2cf1dd01173ee29f28e576 100644 (file)
@@ -718,6 +718,7 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
        int unmasked = 0;
        struct irq_chip *irqchip = irq_desc_get_chip(desc);
        struct gpio_chip *chip = irq_desc_get_handler_data(desc);
+       unsigned long lock_flags;
 
        chained_irq_enter(irqchip, desc);
 
@@ -732,6 +733,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                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;
 
@@ -745,6 +748,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
                omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask);
 
+               raw_spin_unlock_irqrestore(&bank->lock, lock_flags);
+
                /* if there is only edge sensitive GPIO pin interrupts
                configured, we could unmask GPIO bank interrupt immediately */
                if (!level_mask && !unmasked) {
@@ -759,6 +764,7 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                        bit = __ffs(isr);
                        isr &= ~(BIT(bit));
 
+                       raw_spin_lock_irqsave(&bank->lock, lock_flags);
                        /*
                         * Some chips can't respond to both rising and falling
                         * at the same time.  If this irq was requested with
@@ -769,6 +775,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                        if (bank->toggle_mask & (BIT(bit)))
                                omap_toggle_gpio_edge_triggering(bank, bit);
 
+                       raw_spin_unlock_irqrestore(&bank->lock, lock_flags);
+
                        generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
                                                            bit));
                }