gpio: mockup: add locking
authorBartosz Golaszewski <bgolaszewski@baylibre.com>
Wed, 31 Oct 2018 13:55:47 +0000 (14:55 +0100)
committerBartosz Golaszewski <bgolaszewski@baylibre.com>
Tue, 19 Feb 2019 16:42:28 +0000 (17:42 +0100)
While no user reported any race condition problems with gpio-mockup,
let's be on the safe side and use a mutex when performing any changes
on the dummy chip structures.

Suggested-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
drivers/gpio/gpio-mockup.c

index 6a50f9f..b4c1de6 100644 (file)
@@ -54,6 +54,7 @@ struct gpio_mockup_chip {
        struct gpio_mockup_line_status *lines;
        struct irq_sim irqsim;
        struct dentry *dbg_dir;
+       struct mutex lock;
 };
 
 struct gpio_mockup_dbgfs_private {
@@ -82,29 +83,53 @@ static int gpio_mockup_range_ngpio(unsigned int index)
        return gpio_mockup_ranges[index * 2 + 1];
 }
 
-static int gpio_mockup_get(struct gpio_chip *gc, unsigned int offset)
+static int __gpio_mockup_get(struct gpio_chip *gc, unsigned int offset)
 {
        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
 
        return chip->lines[offset].value;
 }
 
-static void gpio_mockup_set(struct gpio_chip *gc,
-                           unsigned int offset, int value)
+static int gpio_mockup_get(struct gpio_chip *gc, unsigned int offset)
+{
+       struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
+       int val;
+
+       mutex_lock(&chip->lock);
+       val = __gpio_mockup_get(gc, offset);
+       mutex_unlock(&chip->lock);
+
+       return val;
+}
+
+static void __gpio_mockup_set(struct gpio_chip *gc,
+                             unsigned int offset, int value)
 {
        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
 
        chip->lines[offset].value = !!value;
 }
 
+static void gpio_mockup_set(struct gpio_chip *gc,
+                          unsigned int offset, int value)
+{
+       struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
+
+       mutex_lock(&chip->lock);
+       __gpio_mockup_set(gc, offset, value);
+       mutex_unlock(&chip->lock);
+}
+
 static void gpio_mockup_set_multiple(struct gpio_chip *gc,
                                     unsigned long *mask, unsigned long *bits)
 {
+       struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
        unsigned int bit;
 
+       mutex_lock(&chip->lock);
        for_each_set_bit(bit, mask, gc->ngpio)
-               gpio_mockup_set(gc, bit, test_bit(bit, bits));
-
+               __gpio_mockup_set(gc, bit, test_bit(bit, bits));
+       mutex_unlock(&chip->lock);
 }
 
 static int gpio_mockup_dirout(struct gpio_chip *gc,
@@ -112,8 +137,10 @@ static int gpio_mockup_dirout(struct gpio_chip *gc,
 {
        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
 
-       gpio_mockup_set(gc, offset, value);
+       mutex_lock(&chip->lock);
        chip->lines[offset].dir = GPIO_MOCKUP_DIR_OUT;
+       __gpio_mockup_set(gc, offset, value);
+       mutex_unlock(&chip->lock);
 
        return 0;
 }
@@ -122,7 +149,9 @@ static int gpio_mockup_dirin(struct gpio_chip *gc, unsigned int offset)
 {
        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
 
+       mutex_lock(&chip->lock);
        chip->lines[offset].dir = GPIO_MOCKUP_DIR_IN;
+       mutex_unlock(&chip->lock);
 
        return 0;
 }
@@ -130,8 +159,13 @@ static int gpio_mockup_dirin(struct gpio_chip *gc, unsigned int offset)
 static int gpio_mockup_get_direction(struct gpio_chip *gc, unsigned int offset)
 {
        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
+       int direction;
 
-       return !chip->lines[offset].dir;
+       mutex_lock(&chip->lock);
+       direction = !chip->lines[offset].dir;
+       mutex_unlock(&chip->lock);
+
+       return direction;
 }
 
 static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset)
@@ -283,6 +317,8 @@ static int gpio_mockup_probe(struct platform_device *pdev)
                        return -ENOMEM;
        }
 
+       mutex_init(&chip->lock);
+
        gc = &chip->gc;
        gc->base = base;
        gc->ngpio = ngpio;