Commit 235f1eb1 authored by Grygorii Strashko's avatar Grygorii Strashko Committed by Linus Walleij

gpio: omap: protect regs access in omap_gpio_irq_handler

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: default avatarGrygorii Strashko <grygorii.strashko@ti.com>
Acked-by: default avatarSantosh Shilimkar <ssantosh@kernel.org>
Tested-by: default avatarTony Lindgren <tony@atomide.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent e85ec6c3
...@@ -718,6 +718,7 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) ...@@ -718,6 +718,7 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
int unmasked = 0; int unmasked = 0;
struct irq_chip *irqchip = irq_desc_get_chip(desc); struct irq_chip *irqchip = irq_desc_get_chip(desc);
struct gpio_chip *chip = irq_desc_get_handler_data(desc); struct gpio_chip *chip = irq_desc_get_handler_data(desc);
unsigned long lock_flags;
chained_irq_enter(irqchip, desc); chained_irq_enter(irqchip, desc);
...@@ -732,6 +733,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *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 isr_saved, level_mask = 0;
u32 enabled; u32 enabled;
raw_spin_lock_irqsave(&bank->lock, lock_flags);
enabled = omap_get_gpio_irqbank_mask(bank); enabled = omap_get_gpio_irqbank_mask(bank);
isr_saved = isr = readl_relaxed(isr_reg) & enabled; 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) ...@@ -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_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
omap_enable_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 /* if there is only edge sensitive GPIO pin interrupts
configured, we could unmask GPIO bank interrupt immediately */ configured, we could unmask GPIO bank interrupt immediately */
if (!level_mask && !unmasked) { if (!level_mask && !unmasked) {
...@@ -759,6 +764,7 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) ...@@ -759,6 +764,7 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
bit = __ffs(isr); bit = __ffs(isr);
isr &= ~(BIT(bit)); isr &= ~(BIT(bit));
raw_spin_lock_irqsave(&bank->lock, lock_flags);
/* /*
* Some chips can't respond to both rising and falling * Some chips can't respond to both rising and falling
* at the same time. If this irq was requested with * 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) ...@@ -769,6 +775,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
if (bank->toggle_mask & (BIT(bit))) if (bank->toggle_mask & (BIT(bit)))
omap_toggle_gpio_edge_triggering(bank, 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, generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
bit)); bit));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment