diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2016-04-06 13:31:06 +0300 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2016-04-19 21:58:14 +0300 |
commit | 8bf872d8d261feefcdf67027522e3f717cad2bfe (patch) | |
tree | d3e646a5e68314e744468fdec20d17c24248785e /drivers/iio/inkern.c | |
parent | 5f991a921a08279f573fa5ecf84261a3a6fac0cc (diff) | |
download | linux-8bf872d8d261feefcdf67027522e3f717cad2bfe.tar.xz |
iio: core: Add devm_ APIs for iio_channel_{get,release}
Some of kernel driver uses the IIO framework to get the sensor
value via ADC or IIO HW driver. The client driver get iio channel
by iio_channel_get() and release it by calling iio_channel_release().
Add resource managed version (devm_*) of these APIs so that if client
calls the devm_iio_channel_get() then it need not to release it explicitly,
it can be done by managed device framework when driver get un-binded.
This reduces the code in error path and also need of .remove callback in
some cases.
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio/inkern.c')
-rw-r--r-- | drivers/iio/inkern.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 2fc7928f401d..9fd8934c1887 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -356,6 +356,54 @@ void iio_channel_release(struct iio_channel *channel) } EXPORT_SYMBOL_GPL(iio_channel_release); +static void devm_iio_channel_free(struct device *dev, void *res) +{ + struct iio_channel *channel = *(struct iio_channel **)res; + + iio_channel_release(channel); +} + +static int devm_iio_channel_match(struct device *dev, void *res, void *data) +{ + struct iio_channel **r = res; + + if (!r || !*r) { + WARN_ON(!r || !*r); + return 0; + } + + return *r == data; +} + +struct iio_channel *devm_iio_channel_get(struct device *dev, + const char *channel_name) +{ + struct iio_channel **ptr, *channel; + + ptr = devres_alloc(devm_iio_channel_free, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + channel = iio_channel_get(dev, channel_name); + if (IS_ERR(channel)) { + devres_free(ptr); + return channel; + } + + *ptr = channel; + devres_add(dev, ptr); + + return channel; +} +EXPORT_SYMBOL_GPL(devm_iio_channel_get); + +void devm_iio_channel_release(struct device *dev, struct iio_channel *channel) +{ + WARN_ON(devres_release(dev, devm_iio_channel_free, + devm_iio_channel_match, channel)); +} +EXPORT_SYMBOL_GPL(devm_iio_channel_release); + struct iio_channel *iio_channel_get_all(struct device *dev) { const char *name; |