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: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
This commit is contained in:
parent
ccfb6ff4f6
commit
be711caa87
2 changed files with 19 additions and 2 deletions
|
@ -672,6 +672,10 @@ EXPORT_SYMBOL_GPL(gpiochip_line_is_valid);
|
|||
static void gpiodev_release(struct 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);
|
||||
kfree_const(gdev->label);
|
||||
|
@ -836,7 +840,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
|
|||
struct lock_class_key *request_key)
|
||||
{
|
||||
struct gpio_device *gdev;
|
||||
unsigned int i;
|
||||
unsigned int i, j;
|
||||
int base = 0;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -970,6 +974,13 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
|
|||
for (i = 0; i < gc->ngpio; 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)) {
|
||||
assign_bit(FLAG_IS_OUT,
|
||||
&desc->flags, !gc->get_direction(gc, i));
|
||||
|
@ -981,7 +992,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
|
|||
|
||||
ret = gpiochip_add_pin_ranges(gc);
|
||||
if (ret)
|
||||
goto err_remove_of_chip;
|
||||
goto err_cleanup_desc_srcu;
|
||||
|
||||
acpi_gpiochip_add(gc);
|
||||
|
||||
|
@ -1020,6 +1031,9 @@ err_remove_irqchip_mask:
|
|||
gpiochip_irqchip_free_valid_mask(gc);
|
||||
err_remove_acpi_chip:
|
||||
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:
|
||||
gpiochip_free_hogs(gc);
|
||||
of_gpiochip_remove(gc);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/srcu.h>
|
||||
|
||||
#define GPIOCHIP_NAME "gpiochip"
|
||||
|
||||
|
@ -147,6 +148,7 @@ void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action);
|
|||
* @label: Name of the consumer
|
||||
* @name: Line name
|
||||
* @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
|
||||
* integer-based handles.
|
||||
|
@ -184,6 +186,7 @@ struct gpio_desc {
|
|||
#ifdef CONFIG_OF_DYNAMIC
|
||||
struct device_node *hog;
|
||||
#endif
|
||||
struct srcu_struct srcu;
|
||||
};
|
||||
|
||||
#define gpiod_not_found(desc) (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT)
|
||||
|
|
Loading…
Add table
Reference in a new issue