diff options
author | Grygorii Strashko <grygorii.strashko@ti.com> | 2015-08-18 07:10:55 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2015-08-26 03:52:53 -0400 |
commit | 235f1eb1ab93a8e30a66c38949e6d2aeda136aec (patch) | |
tree | eb77e88339e3b672f684fa91df3bdb2c8a8332b1 | |
parent | e85ec6c3047be0646e7c572e24869c212b685c7c (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.c | 8 |
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 | } |