Message ID | 20181205124721.26624-11-linus.walleij@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | Regulator ena_gpiod fixups | expand |
Hi Linus, On 2018-12-05 13:47, Linus Walleij wrote: > 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); 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); 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; Best regards -- Marek Szyprowski, PhD Samsung R&D Institute Poland
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;
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(-) -- 2.19.2