summaryrefslogtreecommitdiff
path: root/drivers/gpio
diff options
context:
space:
mode:
authorBartosz Golaszewski <bartosz.golaszewski@linaro.org>2024-01-05 20:42:44 +0100
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>2024-02-12 10:51:29 +0100
commit47d8b4c1d868148c8fb51b785a89e58ca2d02c4d (patch)
tree6d5415669bf65cdd09feaed8ec46053de68e4721 /drivers/gpio
parent8a5b477bb3e9c891eb064accabb3162ccf2c590e (diff)
gpio: add SRCU infrastructure to struct gpio_device
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>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpiolib.c13
-rw-r--r--drivers/gpio/gpiolib.h2
2 files changed, 12 insertions, 3 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 40052de2361c..4e0c6df4a880 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -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);
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 43ff4931e2c3..35d71e30c546 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -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
/*