gpiolib: devres: Finish the conversion to use devm_add_action()

With a recently added helper we can complete the conversion of
the GPIOLIB code to use devm_add_action() in all suitable cases.
So do this.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://lore.kernel.org/r/20250220162238.2738038-4-andriy.shevchenko@linux.intel.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
This commit is contained in:
Andy Shevchenko 2025-02-20 18:20:28 +02:00 committed by Bartosz Golaszewski
parent 063a2b45d6
commit d1d52c6622

View file

@ -6,7 +6,7 @@
* Copyright (c) 2011 John Crispin <john@phrozen.org> * Copyright (c) 2011 John Crispin <john@phrozen.org>
*/ */
#include <linux/device.h> #include <linux/device/devres.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/gfp.h> #include <linux/gfp.h>
@ -19,32 +19,14 @@
struct fwnode_handle; struct fwnode_handle;
struct lock_class_key; struct lock_class_key;
static void devm_gpiod_release(struct device *dev, void *res) static void devm_gpiod_release(void *desc)
{ {
struct gpio_desc **desc = res; gpiod_put(desc);
gpiod_put(*desc);
} }
static int devm_gpiod_match(struct device *dev, void *res, void *data) static void devm_gpiod_release_array(void *descs)
{ {
struct gpio_desc **this = res, **gpio = data; gpiod_put_array(descs);
return *this == *gpio;
}
static void devm_gpiod_release_array(struct device *dev, void *res)
{
struct gpio_descs **descs = res;
gpiod_put_array(*descs);
}
static int devm_gpiod_match_array(struct device *dev, void *res, void *data)
{
struct gpio_descs **this = res, **gpios = data;
return *this == *gpios;
} }
/** /**
@ -114,8 +96,8 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
unsigned int idx, unsigned int idx,
enum gpiod_flags flags) enum gpiod_flags flags)
{ {
struct gpio_desc **dr;
struct gpio_desc *desc; struct gpio_desc *desc;
int ret;
desc = gpiod_get_index(dev, con_id, idx, flags); desc = gpiod_get_index(dev, con_id, idx, flags);
if (IS_ERR(desc)) if (IS_ERR(desc))
@ -126,23 +108,16 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
* already under resource management by this device. * already under resource management by this device.
*/ */
if (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) { if (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) {
struct devres *dres; bool dres;
dres = devres_find(dev, devm_gpiod_release, dres = devm_is_action_added(dev, devm_gpiod_release, desc);
devm_gpiod_match, &desc);
if (dres) if (dres)
return desc; return desc;
} }
dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *), ret = devm_add_action_or_reset(dev, devm_gpiod_release, desc);
GFP_KERNEL); if (ret)
if (!dr) { return ERR_PTR(ret);
gpiod_put(desc);
return ERR_PTR(-ENOMEM);
}
*dr = desc;
devres_add(dev, dr);
return desc; return desc;
} }
@ -171,22 +146,16 @@ struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev,
enum gpiod_flags flags, enum gpiod_flags flags,
const char *label) const char *label)
{ {
struct gpio_desc **dr;
struct gpio_desc *desc; struct gpio_desc *desc;
int ret;
dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
GFP_KERNEL);
if (!dr)
return ERR_PTR(-ENOMEM);
desc = gpiod_find_and_request(dev, fwnode, con_id, index, flags, label, false); desc = gpiod_find_and_request(dev, fwnode, con_id, index, flags, label, false);
if (IS_ERR(desc)) { if (IS_ERR(desc))
devres_free(dr);
return desc; return desc;
}
*dr = desc; ret = devm_add_action_or_reset(dev, devm_gpiod_release, desc);
devres_add(dev, dr); if (ret)
return ERR_PTR(ret);
return desc; return desc;
} }
@ -244,22 +213,16 @@ struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,
const char *con_id, const char *con_id,
enum gpiod_flags flags) enum gpiod_flags flags)
{ {
struct gpio_descs **dr;
struct gpio_descs *descs; struct gpio_descs *descs;
int ret;
dr = devres_alloc(devm_gpiod_release_array,
sizeof(struct gpio_descs *), GFP_KERNEL);
if (!dr)
return ERR_PTR(-ENOMEM);
descs = gpiod_get_array(dev, con_id, flags); descs = gpiod_get_array(dev, con_id, flags);
if (IS_ERR(descs)) { if (IS_ERR(descs))
devres_free(dr);
return descs; return descs;
}
*dr = descs; ret = devm_add_action_or_reset(dev, devm_gpiod_release_array, descs);
devres_add(dev, dr); if (ret)
return ERR_PTR(ret);
return descs; return descs;
} }
@ -307,8 +270,7 @@ EXPORT_SYMBOL_GPL(devm_gpiod_get_array_optional);
*/ */
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
{ {
WARN_ON(devres_release(dev, devm_gpiod_release, devm_gpiod_match, devm_release_action(dev, devm_gpiod_release, desc);
&desc));
} }
EXPORT_SYMBOL_GPL(devm_gpiod_put); EXPORT_SYMBOL_GPL(devm_gpiod_put);
@ -321,20 +283,19 @@ EXPORT_SYMBOL_GPL(devm_gpiod_put);
* you want to hand over lifecycle management of a descriptor to another * you want to hand over lifecycle management of a descriptor to another
* mechanism. * mechanism.
*/ */
void devm_gpiod_unhinge(struct device *dev, struct gpio_desc *desc) void devm_gpiod_unhinge(struct device *dev, struct gpio_desc *desc)
{ {
int ret; int ret;
if (IS_ERR_OR_NULL(desc)) if (IS_ERR_OR_NULL(desc))
return; return;
ret = devres_destroy(dev, devm_gpiod_release,
devm_gpiod_match, &desc);
/* /*
* If the GPIO descriptor is requested as nonexclusive, we * If the GPIO descriptor is requested as nonexclusive, we
* may call this function several times on the same descriptor * may call this function several times on the same descriptor
* so it is OK if devres_destroy() returns -ENOENT. * so it is OK if devres_destroy() returns -ENOENT.
*/ */
ret = devm_remove_action_nowarn(dev, devm_gpiod_release, desc);
if (ret == -ENOENT) if (ret == -ENOENT)
return; return;
/* Anything else we should warn about */ /* Anything else we should warn about */
@ -353,8 +314,7 @@ EXPORT_SYMBOL_GPL(devm_gpiod_unhinge);
*/ */
void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs) void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs)
{ {
WARN_ON(devres_release(dev, devm_gpiod_release_array, devm_remove_action(dev, devm_gpiod_release_array, descs);
devm_gpiod_match_array, &descs));
} }
EXPORT_SYMBOL_GPL(devm_gpiod_put_array); EXPORT_SYMBOL_GPL(devm_gpiod_put_array);