aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrygorii Strashko <grygorii.strashko@ti.com>2015-08-18 07:10:55 -0400
committerLinus Walleij <linus.walleij@linaro.org>2015-08-26 03:52:53 -0400
commit235f1eb1ab93a8e30a66c38949e6d2aeda136aec (patch)
treeeb77e88339e3b672f684fa91df3bdb2c8a8332b1
parente85ec6c3047be0646e7c572e24869c212b685c7c (diff)
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>
-rw-r--r--drivers/gpio/gpio-omap.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 9ed5a675564c..1f02acd577e3 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -718,6 +718,7 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
718 int unmasked = 0; 718 int unmasked = 0;
719 struct irq_chip *irqchip = irq_desc_get_chip(desc); 719 struct irq_chip *irqchip = irq_desc_get_chip(desc);
720 struct gpio_chip *chip = irq_desc_get_handler_data(desc); 720 struct gpio_chip *chip = irq_desc_get_handler_data(desc);
721 unsigned long lock_flags;
721 722
722 chained_irq_enter(irqchip, desc); 723 chained_irq_enter(irqchip, desc);
723 724
@@ -732,6 +733,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
732 u32 isr_saved, level_mask = 0; 733 u32 isr_saved, level_mask = 0;
733 u32 enabled; 734 u32 enabled;
734 735
736 raw_spin_lock_irqsave(&bank->lock, lock_flags);
737
735 enabled = omap_get_gpio_irqbank_mask(bank); 738 enabled = omap_get_gpio_irqbank_mask(bank);
736 isr_saved = isr = readl_relaxed(isr_reg) & enabled; 739 isr_saved = isr = readl_relaxed(isr_reg) & enabled;
737 740
@@ -745,6 +748,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
745 omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask); 748 omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
746 omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask); 749 omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask);
747 750
751 raw_spin_unlock_irqrestore(&bank->lock, lock_flags);
752
748 /* if there is only edge sensitive GPIO pin interrupts 753 /* if there is only edge sensitive GPIO pin interrupts
749 configured, we could unmask GPIO bank interrupt immediately */ 754 configured, we could unmask GPIO bank interrupt immediately */
750 if (!level_mask && !unmasked) { 755 if (!level_mask && !unmasked) {
@@ -759,6 +764,7 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
759 bit = __ffs(isr); 764 bit = __ffs(isr);
760 isr &= ~(BIT(bit)); 765 isr &= ~(BIT(bit));
761 766
767 raw_spin_lock_irqsave(&bank->lock, lock_flags);
762 /* 768 /*
763 * Some chips can't respond to both rising and falling 769 * Some chips can't respond to both rising and falling
764 * at the same time. If this irq was requested with 770 * 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 if (bank->toggle_mask & (BIT(bit))) 775 if (bank->toggle_mask & (BIT(bit)))
770 omap_toggle_gpio_edge_triggering(bank, bit); 776 omap_toggle_gpio_edge_triggering(bank, bit);
771 777
778 raw_spin_unlock_irqrestore(&bank->lock, lock_flags);
779
772 generic_handle_irq(irq_find_mapping(bank->chip.irqdomain, 780 generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
773 bit)); 781 bit));
774 } 782 }