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);
struct lock_class_key *request_key)
{
struct gpio_device *gdev;
- unsigned int i;
+ unsigned int i, j;
int base = 0;
int ret = 0;
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));
ret = gpiochip_add_pin_ranges(gc);
if (ret)
- goto err_remove_of_chip;
+ goto err_cleanup_desc_srcu;
acpi_gpiochip_add(gc);
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);
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/rwsem.h>
+#include <linux/srcu.h>
#define GPIOCHIP_NAME "gpiochip"
* @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.
#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)