gpio: reflect base and ngpio into gpio_device
Some information about the GPIO chip need to stay around also
after the gpio_chip has been removed and only the gpio_device
persist. The base and ngpio are such things, for example we
don't want a new chip arriving to overlap the number space
of a dangling gpio_device, and the chardev may still query
the device for the number of lines etc.
Note that the code that assigns base and insert gpio_device
into the global list no longer check for a missing gpio_chip:
we respect the number space allocated by any other gpio_device.
As a consequence of the gdev being referenced directly from
the gpio_desc, we need to verify it differently from all
in-kernel API calls that fall through to direct queries to
the gpio_chip vtable: we first check that desc is !NULL, then
that desc->gdev is !NULL, then, if desc->gdev->chip is NULL,
we *BAIL OUT* without any error, so as to manage the case
where operations are requested on a device that is gone.
These checks were non-uniform and partly missing in the past:
so to simplify: create the macros VALIDATE_DESC() that will
return -EINVAL if the desc or desc->gdev is missing and just
0 if the chip is gone, and conversely VALIDATE_DESC_VOID()
for the case where the function does not return an error.
By using these macros, we get warning messages about missing
gdev with reference to the right function in the kernel log.
Despite the macro business this simplifies the code and make
it more readable than if we copy/paste the same descriptor
checking code into all code ABI call sites (IMHO).
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index de65633..c563094 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -180,7 +180,7 @@
* Remove this redundant call (along with the corresponding
* unlock) when those drivers have been fixed.
*/
- ret = gpiochip_lock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
+ ret = gpiochip_lock_as_irq(desc->gdev->chip, gpio_chip_hwgpio(desc));
if (ret < 0)
goto err_put_kn;
@@ -194,7 +194,7 @@
return 0;
err_unlock:
- gpiochip_unlock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
+ gpiochip_unlock_as_irq(desc->gdev->chip, gpio_chip_hwgpio(desc));
err_put_kn:
sysfs_put(data->value_kn);
@@ -212,7 +212,7 @@
data->irq_flags = 0;
free_irq(data->irq, data);
- gpiochip_unlock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
+ gpiochip_unlock_as_irq(desc->gdev->chip, gpio_chip_hwgpio(desc));
sysfs_put(data->value_kn);
}
@@ -566,8 +566,8 @@
return -EINVAL;
}
- chip = desc->chip;
- gdev = chip->gpiodev;
+ gdev = desc->gdev;
+ chip = gdev->chip;
mutex_lock(&sysfs_lock);
@@ -765,7 +765,7 @@
/* unregister gpiod class devices owned by sysfs */
for (i = 0; i < chip->ngpio; i++) {
- desc = &chip->gpiodev->descs[i];
+ desc = &gdev->descs[i];
if (test_and_clear_bit(FLAG_SYSFS, &desc->flags))
gpiod_free(desc);
}