diff options
author | John Crispin <blogic@openwrt.org> | 2016-03-20 14:41:25 +0000 |
---|---|---|
committer | John Crispin <blogic@openwrt.org> | 2016-03-20 14:41:25 +0000 |
commit | b9eb591be55e3c29b2207a3a0e84baa039c11d31 (patch) | |
tree | 9c3d1fd4044941664e3e2bb57269a0332f783a5f /target | |
parent | 4cc7ede8db038cd5c81e3dfc52228f71bf89d612 (diff) | |
download | master-187ad058-b9eb591be55e3c29b2207a3a0e84baa039c11d31.tar.gz master-187ad058-b9eb591be55e3c29b2207a3a0e84baa039c11d31.tar.bz2 master-187ad058-b9eb591be55e3c29b2207a3a0e84baa039c11d31.zip |
oxnas: add spinlock in pinctrl driver
Try to address a race-condition in pinctrl-oxnas.c
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@49043 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target')
-rw-r--r-- | target/linux/oxnas/files/drivers/pinctrl/pinctrl-oxnas.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/target/linux/oxnas/files/drivers/pinctrl/pinctrl-oxnas.c b/target/linux/oxnas/files/drivers/pinctrl/pinctrl-oxnas.c index aa76f40e40..034a7304d4 100644 --- a/target/linux/oxnas/files/drivers/pinctrl/pinctrl-oxnas.c +++ b/target/linux/oxnas/files/drivers/pinctrl/pinctrl-oxnas.c @@ -26,6 +26,7 @@ #include <linux/pinctrl/pinmux.h> /* Since we request GPIOs from ourself */ #include <linux/pinctrl/consumer.h> +#include <linux/spinlock.h> #include <linux/version.h> #include "core.h" @@ -41,6 +42,7 @@ struct oxnas_gpio_chip { void __iomem *regbase; /* GPIOA/B virtual address */ void __iomem *ctrlbase; /* SYS/SEC_CTRL virtual address */ struct irq_domain *domain; /* associated irq domain */ + spinlock_t lock; }; #define to_oxnas_gpio_chip(c) container_of(c, struct oxnas_gpio_chip, chip) @@ -1145,12 +1147,17 @@ static void gpio_irq_mask(struct irq_data *d) void __iomem *pio = oxnas_gpio->regbase; unsigned mask = 1 << d->hwirq; unsigned type = irqd_get_trigger_type(d); + unsigned long flags; - /* FIXME: need proper lock */ + if (!(type & IRQ_TYPE_EDGE_BOTH)) + return; + + spin_lock_irqsave(&oxnas_gpio->lock, flags); if (type & IRQ_TYPE_EDGE_RISING) oxnas_register_clear_mask(pio + RE_IRQ_ENABLE, mask); if (type & IRQ_TYPE_EDGE_FALLING) oxnas_register_clear_mask(pio + FE_IRQ_ENABLE, mask); + spin_unlock_irqrestore(&oxnas_gpio->lock, flags); } static void gpio_irq_unmask(struct irq_data *d) @@ -1159,12 +1166,17 @@ static void gpio_irq_unmask(struct irq_data *d) void __iomem *pio = oxnas_gpio->regbase; unsigned mask = 1 << d->hwirq; unsigned type = irqd_get_trigger_type(d); + unsigned long flags; + + if (!(type & IRQ_TYPE_EDGE_BOTH)) + return; - /* FIXME: need proper lock */ + spin_lock_irqsave(&oxnas_gpio->lock, flags); if (type & IRQ_TYPE_EDGE_RISING) oxnas_register_set_mask(pio + RE_IRQ_ENABLE, mask); if (type & IRQ_TYPE_EDGE_FALLING) oxnas_register_set_mask(pio + FE_IRQ_ENABLE, mask); + spin_unlock_irqrestore(&oxnas_gpio->lock, flags); } @@ -1359,6 +1371,8 @@ static int oxnas_gpio_probe(struct platform_device *pdev) oxnas_chip->chip = oxnas_gpio_template; + spin_lock_init(&oxnas_chip->lock); + chip = &oxnas_chip->chip; chip->of_node = np; chip->label = dev_name(&pdev->dev); |