Messages in this thread Patch in this message | | | From | Linus Walleij <> | Subject | [PATCH 10/15 v3] gpio: devres: Handle nonexclusive GPIOs | Date | Wed, 5 Dec 2018 13:47:16 +0100 |
| |
When we get a nonexeclusive GPIO descriptor using managed resources, we should only add it to the list of managed resources once: on the first user. Augment the devm_gpiod_get_index() and devm_gpiod_get_from_of_node() calls to account for this by checking if the descriptor is already resource managed before we proceed to allocate a new resource management struct.
Cc: Mark Brown <broonie@kernel.org> Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com> Cc: Marek Szyprowski <m.szyprowski@samsung.com> Fixes: b0ce7b29bfcd ("regulator/gpio: Allow nonexclusive GPIO access") Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> --- ChangeLog v1->v3: - New patch. - This fix is in response to an issue Marek saw in the fixups for resource-managed GPIO descriptors used with ena_gpiod in the regulator subsystem. - I first thought to apply it to the GPIO tree directly, but since it is not a regression it is better to put it into the regulator tree with the rest of the patches. --- drivers/gpio/gpiolib-devres.c | 50 ++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 12 deletions(-)
diff --git a/drivers/gpio/gpiolib-devres.c b/drivers/gpio/gpiolib-devres.c index 01959369360b..a57e968025a8 100644 --- a/drivers/gpio/gpiolib-devres.c +++ b/drivers/gpio/gpiolib-devres.c @@ -98,15 +98,28 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, struct gpio_desc **dr; struct gpio_desc *desc; + desc = gpiod_get_index(dev, con_id, idx, flags); + if (IS_ERR(desc)) + return desc; + + /* + * For non-exclusive GPIO descriptors, check if this descriptor is + * already under resource management by this device. + */ + if (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) { + struct devres *dres; + + dres = devres_find(dev, devm_gpiod_release, + devm_gpiod_match, desc); + if (dres) + return desc; + } + dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *), GFP_KERNEL); - if (!dr) + if (!dr) { + gpiod_put(desc); return ERR_PTR(-ENOMEM); - - desc = gpiod_get_index(dev, con_id, idx, flags); - if (IS_ERR(desc)) { - devres_free(dr); - return desc; } *dr = desc; @@ -140,15 +153,28 @@ struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, struct gpio_desc **dr; struct gpio_desc *desc; + desc = gpiod_get_from_of_node(node, propname, index, dflags, label); + if (IS_ERR(desc)) + return desc; + + /* + * For non-exclusive GPIO descriptors, check if this descriptor is + * already under resource management by this device. + */ + if (dflags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) { + struct devres *dres; + + dres = devres_find(dev, devm_gpiod_release, + devm_gpiod_match, desc); + if (dres) + return desc; + } + dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *), GFP_KERNEL); - if (!dr) + if (!dr) { + gpiod_put(desc); return ERR_PTR(-ENOMEM); - - desc = gpiod_get_from_of_node(node, propname, index, dflags, label); - if (IS_ERR(desc)) { - devres_free(dr); - return desc; } *dr = desc; -- 2.19.2
| |