linux-gpio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] gpio: vf610: add locking to gpio direction functions
@ 2025-02-06 18:17 Johan Korsnes
  2025-02-06 18:23 ` Bartosz Golaszewski
  2025-02-06 18:29 ` Linus Walleij
  0 siblings, 2 replies; 10+ messages in thread
From: Johan Korsnes @ 2025-02-06 18:17 UTC (permalink / raw)
  To: linux-gpio; +Cc: Johan Korsnes, Linus Walleij, Bartosz Golaszewski, Haibo Chen

Add locking to `vf610_gpio_direction_input|output()` functions. Without
this locking, a race condition exists between concurrent calls to these
functions, potentially leading to incorrect GPIO direction settings.

Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Cc: Haibo Chen <haibo.chen@nxp.com>
Signed-off-by: Johan Korsnes <johan.korsnes@remarkable.no>

---
To verify the correctness of this fix, a `trylock` patch was applied,
where after a couple of reboots the race was confirmed. I.e., one user
had to wait before acquiring the lock. With this patch the race has not
been encountered. It's worth mentioning that any type of debugging
(printing, tracing, etc.) would "resolve" the issue.
---
 drivers/gpio/gpio-vf610.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
index c4f34a347cb6..3527487d42c8 100644
--- a/drivers/gpio/gpio-vf610.c
+++ b/drivers/gpio/gpio-vf610.c
@@ -36,6 +36,7 @@ struct vf610_gpio_port {
 	struct clk *clk_port;
 	struct clk *clk_gpio;
 	int irq;
+	spinlock_t lock; /* protect gpio direction registers */
 };
 
 #define GPIO_PDOR		0x00
@@ -121,12 +122,15 @@ static int vf610_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio)
 {
 	struct vf610_gpio_port *port = gpiochip_get_data(chip);
 	u32 mask = BIT(gpio);
+	unsigned long flags;
 	u32 val;
 
 	if (port->sdata->have_paddr) {
+		spin_lock_irqsave(&port->lock, flags);
 		val = vf610_gpio_readl(port->gpio_base + GPIO_PDDR);
 		val &= ~mask;
 		vf610_gpio_writel(val, port->gpio_base + GPIO_PDDR);
+		spin_unlock_irqrestore(&port->lock, flags);
 	}
 
 	return pinctrl_gpio_direction_input(chip, gpio);
@@ -137,14 +141,17 @@ static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio
 {
 	struct vf610_gpio_port *port = gpiochip_get_data(chip);
 	u32 mask = BIT(gpio);
+	unsigned long flags;
 	u32 val;
 
 	vf610_gpio_set(chip, gpio, value);
 
 	if (port->sdata->have_paddr) {
+		spin_lock_irqsave(&port->lock, flags);
 		val = vf610_gpio_readl(port->gpio_base + GPIO_PDDR);
 		val |= mask;
 		vf610_gpio_writel(val, port->gpio_base + GPIO_PDDR);
+		spin_unlock_irqrestore(&port->lock, flags);
 	}
 
 	return pinctrl_gpio_direction_output(chip, gpio);
@@ -297,6 +304,7 @@ static int vf610_gpio_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	port->sdata = device_get_match_data(dev);
+	spin_lock_init(&port->lock);
 
 	dual_base = port->sdata->have_dual_base;
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2025-02-13 23:08 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-06 18:17 [PATCH] gpio: vf610: add locking to gpio direction functions Johan Korsnes
2025-02-06 18:23 ` Bartosz Golaszewski
2025-02-06 18:29 ` Linus Walleij
2025-02-07  6:21   ` Bough Chen
2025-02-10  8:52     ` Johan Korsnes
2025-02-10  9:35       ` Bough Chen
2025-02-13  6:12         ` Johan Korsnes
2025-02-13  6:39           ` Bough Chen
2025-02-13 21:45     ` Linus Walleij
2025-02-13 23:08       ` Linus Walleij

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).