Commit 47d8b4c1 authored by Bartosz Golaszewski's avatar Bartosz Golaszewski

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: default avatarBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Acked-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
parent 8a5b477b
...@@ -680,6 +680,7 @@ static void gpiodev_release(struct device *dev) ...@@ -680,6 +680,7 @@ static void gpiodev_release(struct device *dev)
ida_free(&gpio_ida, gdev->id); ida_free(&gpio_ida, gdev->id);
kfree_const(gdev->label); kfree_const(gdev->label);
kfree(gdev->descs); kfree(gdev->descs);
cleanup_srcu_struct(&gdev->srcu);
kfree(gdev); kfree(gdev);
} }
...@@ -948,6 +949,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, ...@@ -948,6 +949,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier); BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
init_rwsem(&gdev->sem); init_rwsem(&gdev->sem);
ret = init_srcu_struct(&gdev->srcu);
if (ret)
goto err_remove_from_list;
#ifdef CONFIG_PINCTRL #ifdef CONFIG_PINCTRL
INIT_LIST_HEAD(&gdev->pin_ranges); INIT_LIST_HEAD(&gdev->pin_ranges);
#endif #endif
...@@ -955,15 +960,15 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, ...@@ -955,15 +960,15 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
if (gc->names) { if (gc->names) {
ret = gpiochip_set_desc_names(gc); ret = gpiochip_set_desc_names(gc);
if (ret) if (ret)
goto err_remove_from_list; goto err_cleanup_gdev_srcu;
} }
ret = gpiochip_set_names(gc); ret = gpiochip_set_names(gc);
if (ret) if (ret)
goto err_remove_from_list; goto err_cleanup_gdev_srcu;
ret = gpiochip_init_valid_mask(gc); ret = gpiochip_init_valid_mask(gc);
if (ret) if (ret)
goto err_remove_from_list; goto err_cleanup_gdev_srcu;
ret = of_gpiochip_add(gc); ret = of_gpiochip_add(gc);
if (ret) if (ret)
...@@ -1038,6 +1043,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, ...@@ -1038,6 +1043,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
err_free_gpiochip_mask: err_free_gpiochip_mask:
gpiochip_remove_pin_ranges(gc); gpiochip_remove_pin_ranges(gc);
gpiochip_free_valid_mask(gc); gpiochip_free_valid_mask(gc);
err_cleanup_gdev_srcu:
cleanup_srcu_struct(&gdev->srcu);
err_remove_from_list: err_remove_from_list:
scoped_guard(mutex, &gpio_devices_lock) scoped_guard(mutex, &gpio_devices_lock)
list_del_rcu(&gdev->list); list_del_rcu(&gdev->list);
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
* @sem: protects the structure from a NULL-pointer dereference of @chip by * @sem: protects the structure from a NULL-pointer dereference of @chip by
* user-space operations when the device gets unregistered during * user-space operations when the device gets unregistered during
* a hot-unplug event * a hot-unplug event
* @srcu: protects the pointer to the underlying GPIO chip
* @pin_ranges: range of pins served by the GPIO driver * @pin_ranges: range of pins served by the GPIO driver
* *
* This state container holds most of the runtime variable data * This state container holds most of the runtime variable data
...@@ -73,6 +74,7 @@ struct gpio_device { ...@@ -73,6 +74,7 @@ struct gpio_device {
struct blocking_notifier_head line_state_notifier; struct blocking_notifier_head line_state_notifier;
struct blocking_notifier_head device_notifier; struct blocking_notifier_head device_notifier;
struct rw_semaphore sem; struct rw_semaphore sem;
struct srcu_struct srcu;
#ifdef CONFIG_PINCTRL #ifdef CONFIG_PINCTRL
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment