Commit be711caa authored by Bartosz Golaszewski's avatar Bartosz Golaszewski

gpio: add SRCU infrastructure to struct gpio_desc

Extend the GPIO descriptor with an SRCU structure in order to serialize
the access to the label. 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 ccfb6ff4
...@@ -672,6 +672,10 @@ EXPORT_SYMBOL_GPL(gpiochip_line_is_valid); ...@@ -672,6 +672,10 @@ EXPORT_SYMBOL_GPL(gpiochip_line_is_valid);
static void gpiodev_release(struct device *dev) static void gpiodev_release(struct device *dev)
{ {
struct gpio_device *gdev = to_gpio_device(dev); struct gpio_device *gdev = to_gpio_device(dev);
unsigned int i;
for (i = 0; i < gdev->ngpio; i++)
cleanup_srcu_struct(&gdev->descs[i].srcu);
ida_free(&gpio_ida, gdev->id); ida_free(&gpio_ida, gdev->id);
kfree_const(gdev->label); kfree_const(gdev->label);
...@@ -836,7 +840,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, ...@@ -836,7 +840,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
struct lock_class_key *request_key) struct lock_class_key *request_key)
{ {
struct gpio_device *gdev; struct gpio_device *gdev;
unsigned int i; unsigned int i, j;
int base = 0; int base = 0;
int ret = 0; int ret = 0;
...@@ -970,6 +974,13 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, ...@@ -970,6 +974,13 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
for (i = 0; i < gc->ngpio; i++) { for (i = 0; i < gc->ngpio; i++) {
struct gpio_desc *desc = &gdev->descs[i]; struct gpio_desc *desc = &gdev->descs[i];
ret = init_srcu_struct(&desc->srcu);
if (ret) {
for (j = 0; j < i; j++)
cleanup_srcu_struct(&gdev->descs[j].srcu);
goto err_remove_of_chip;
}
if (gc->get_direction && gpiochip_line_is_valid(gc, i)) { if (gc->get_direction && gpiochip_line_is_valid(gc, i)) {
assign_bit(FLAG_IS_OUT, assign_bit(FLAG_IS_OUT,
&desc->flags, !gc->get_direction(gc, i)); &desc->flags, !gc->get_direction(gc, i));
...@@ -981,7 +992,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, ...@@ -981,7 +992,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
ret = gpiochip_add_pin_ranges(gc); ret = gpiochip_add_pin_ranges(gc);
if (ret) if (ret)
goto err_remove_of_chip; goto err_cleanup_desc_srcu;
acpi_gpiochip_add(gc); acpi_gpiochip_add(gc);
...@@ -1020,6 +1031,9 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, ...@@ -1020,6 +1031,9 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
gpiochip_irqchip_free_valid_mask(gc); gpiochip_irqchip_free_valid_mask(gc);
err_remove_acpi_chip: err_remove_acpi_chip:
acpi_gpiochip_remove(gc); acpi_gpiochip_remove(gc);
err_cleanup_desc_srcu:
for (i = 0; i < gdev->ngpio; i++)
cleanup_srcu_struct(&gdev->descs[i].srcu);
err_remove_of_chip: err_remove_of_chip:
gpiochip_free_hogs(gc); gpiochip_free_hogs(gc);
of_gpiochip_remove(gc); of_gpiochip_remove(gc);
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/rwsem.h> #include <linux/rwsem.h>
#include <linux/srcu.h>
#define GPIOCHIP_NAME "gpiochip" #define GPIOCHIP_NAME "gpiochip"
...@@ -147,6 +148,7 @@ void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action); ...@@ -147,6 +148,7 @@ void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action);
* @label: Name of the consumer * @label: Name of the consumer
* @name: Line name * @name: Line name
* @hog: Pointer to the device node that hogs this line (if any) * @hog: Pointer to the device node that hogs this line (if any)
* @srcu: SRCU struct protecting the label pointer.
* *
* These are obtained using gpiod_get() and are preferable to the old * These are obtained using gpiod_get() and are preferable to the old
* integer-based handles. * integer-based handles.
...@@ -184,6 +186,7 @@ struct gpio_desc { ...@@ -184,6 +186,7 @@ struct gpio_desc {
#ifdef CONFIG_OF_DYNAMIC #ifdef CONFIG_OF_DYNAMIC
struct device_node *hog; struct device_node *hog;
#endif #endif
struct srcu_struct srcu;
}; };
#define gpiod_not_found(desc) (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) #define gpiod_not_found(desc) (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT)
......
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