From b64f159bc8d94d5554792f46aacdad4d5bf643ca Mon Sep 17 00:00:00 2001
From: John Crispin <john@openwrt.org>
Date: Sun, 20 Mar 2016 14:41:25 +0000
Subject: [PATCH] oxnas: add spinlock in pinctrl driver

Try to address a race-condition in pinctrl-oxnas.c

Signed-off-by: Daniel Golle <daniel@makrotopia.org>

SVN-Revision: 49043
---
 .../files/drivers/pinctrl/pinctrl-oxnas.c      | 18 ++++++++++++++++--
 1 file 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);
-- 
GitLab