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: 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>
This commit is contained in:

committed by
Linus Walleij

parent
e85ec6c304
commit
235f1eb1ab
@@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user