gpio: add SRCU infrastructure to struct gpio_device
authorBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Fri, 5 Jan 2024 19:42:44 +0000 (20:42 +0100)
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Mon, 12 Feb 2024 09:51:29 +0000 (10:51 +0100)
Add the SRCU struct to GPIO device. It will be used to serialize access
to the GPIO chip pointer. Initialize and clean it up where applicable.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
drivers/gpio/gpiolib.c
drivers/gpio/gpiolib.h

index 40052de2361c7d18274c3fdf52b7c14188063ef1..4e0c6df4a880366789ead4d7200ef032ceed255e 100644 (file)
@@ -680,6 +680,7 @@ static void gpiodev_release(struct device *dev)
        ida_free(&gpio_ida, gdev->id);
        kfree_const(gdev->label);
        kfree(gdev->descs);
+       cleanup_srcu_struct(&gdev->srcu);
        kfree(gdev);
 }
 
@@ -948,6 +949,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
        BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
        init_rwsem(&gdev->sem);
 
+       ret = init_srcu_struct(&gdev->srcu);
+       if (ret)
+               goto err_remove_from_list;
+
 #ifdef CONFIG_PINCTRL
        INIT_LIST_HEAD(&gdev->pin_ranges);
 #endif
@@ -955,15 +960,15 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
        if (gc->names) {
                ret = gpiochip_set_desc_names(gc);
                if (ret)
-                       goto err_remove_from_list;
+                       goto err_cleanup_gdev_srcu;
        }
        ret = gpiochip_set_names(gc);
        if (ret)
-               goto err_remove_from_list;
+               goto err_cleanup_gdev_srcu;
 
        ret = gpiochip_init_valid_mask(gc);
        if (ret)
-               goto err_remove_from_list;
+               goto err_cleanup_gdev_srcu;
 
        ret = of_gpiochip_add(gc);
        if (ret)
@@ -1038,6 +1043,8 @@ err_remove_of_chip:
 err_free_gpiochip_mask:
        gpiochip_remove_pin_ranges(gc);
        gpiochip_free_valid_mask(gc);
+err_cleanup_gdev_srcu:
+       cleanup_srcu_struct(&gdev->srcu);
 err_remove_from_list:
        scoped_guard(mutex, &gpio_devices_lock)
                list_del_rcu(&gdev->list);
index 43ff4931e2c369f9cc2a927fda6006d1f19d7ad2..35d71e30c546ced6bd3fd2ab90d556cb9b507755 100644 (file)
@@ -49,6 +49,7 @@
  * @sem: protects the structure from a NULL-pointer dereference of @chip by
  *       user-space operations when the device gets unregistered during
  *       a hot-unplug event
+ * @srcu: protects the pointer to the underlying GPIO chip
  * @pin_ranges: range of pins served by the GPIO driver
  *
  * This state container holds most of the runtime variable data
@@ -73,6 +74,7 @@ struct gpio_device {
        struct blocking_notifier_head line_state_notifier;
        struct blocking_notifier_head device_notifier;
        struct rw_semaphore     sem;
+       struct srcu_struct      srcu;
 
 #ifdef CONFIG_PINCTRL
        /*