diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2016-04-06 06:31:06 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2016-04-19 14:58:14 -0400 |
commit | 8bf872d8d261feefcdf67027522e3f717cad2bfe (patch) | |
tree | d3e646a5e68314e744468fdec20d17c24248785e | |
parent | 5f991a921a08279f573fa5ecf84261a3a6fac0cc (diff) |
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>
-rw-r--r-- | drivers/iio/inkern.c | 48 | ||||
-rw-r--r-- | include/linux/iio/consumer.h | 27 |
2 files changed, 75 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) | |||
356 | } | 356 | } |
357 | EXPORT_SYMBOL_GPL(iio_channel_release); | 357 | EXPORT_SYMBOL_GPL(iio_channel_release); |
358 | 358 | ||
359 | static void devm_iio_channel_free(struct device *dev, void *res) | ||
360 | { | ||
361 | struct iio_channel *channel = *(struct iio_channel **)res; | ||
362 | |||
363 | iio_channel_release(channel); | ||
364 | } | ||
365 | |||
366 | static int devm_iio_channel_match(struct device *dev, void *res, void *data) | ||
367 | { | ||
368 | struct iio_channel **r = res; | ||
369 | |||
370 | if (!r || !*r) { | ||
371 | WARN_ON(!r || !*r); | ||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | return *r == data; | ||
376 | } | ||
377 | |||
378 | struct iio_channel *devm_iio_channel_get(struct device *dev, | ||
379 | const char *channel_name) | ||
380 | { | ||
381 | struct iio_channel **ptr, *channel; | ||
382 | |||
383 | ptr = devres_alloc(devm_iio_channel_free, sizeof(*ptr), GFP_KERNEL); | ||
384 | if (!ptr) | ||
385 | return ERR_PTR(-ENOMEM); | ||
386 | |||
387 | channel = iio_channel_get(dev, channel_name); | ||
388 | if (IS_ERR(channel)) { | ||
389 | devres_free(ptr); | ||
390 | return channel; | ||
391 | } | ||
392 | |||
393 | *ptr = channel; | ||
394 | devres_add(dev, ptr); | ||
395 | |||
396 | return channel; | ||
397 | } | ||
398 | EXPORT_SYMBOL_GPL(devm_iio_channel_get); | ||
399 | |||
400 | void devm_iio_channel_release(struct device *dev, struct iio_channel *channel) | ||
401 | { | ||
402 | WARN_ON(devres_release(dev, devm_iio_channel_free, | ||
403 | devm_iio_channel_match, channel)); | ||
404 | } | ||
405 | EXPORT_SYMBOL_GPL(devm_iio_channel_release); | ||
406 | |||
359 | struct iio_channel *iio_channel_get_all(struct device *dev) | 407 | struct iio_channel *iio_channel_get_all(struct device *dev) |
360 | { | 408 | { |
361 | const char *name; | 409 | const char *name; |
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index fad58671c49e..e1e033d6a81f 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h | |||
@@ -49,6 +49,33 @@ struct iio_channel *iio_channel_get(struct device *dev, | |||
49 | void iio_channel_release(struct iio_channel *chan); | 49 | void iio_channel_release(struct iio_channel *chan); |
50 | 50 | ||
51 | /** | 51 | /** |
52 | * devm_iio_channel_get() - Resource managed version of iio_channel_get(). | ||
53 | * @dev: Pointer to consumer device. Device name must match | ||
54 | * the name of the device as provided in the iio_map | ||
55 | * with which the desired provider to consumer mapping | ||
56 | * was registered. | ||
57 | * @consumer_channel: Unique name to identify the channel on the consumer | ||
58 | * side. This typically describes the channels use within | ||
59 | * the consumer. E.g. 'battery_voltage' | ||
60 | * | ||
61 | * Returns a pointer to negative errno if it is not able to get the iio channel | ||
62 | * otherwise returns valid pointer for iio channel. | ||
63 | * | ||
64 | * The allocated iio channel is automatically released when the device is | ||
65 | * unbound. | ||
66 | */ | ||
67 | struct iio_channel *devm_iio_channel_get(struct device *dev, | ||
68 | const char *consumer_channel); | ||
69 | /** | ||
70 | * devm_iio_channel_release() - Resource managed version of | ||
71 | * iio_channel_release(). | ||
72 | * @dev: Pointer to consumer device for which resource | ||
73 | * is allocared. | ||
74 | * @chan: The channel to be released. | ||
75 | */ | ||
76 | void devm_iio_channel_release(struct device *dev, struct iio_channel *chan); | ||
77 | |||
78 | /** | ||
52 | * iio_channel_get_all() - get all channels associated with a client | 79 | * iio_channel_get_all() - get all channels associated with a client |
53 | * @dev: Pointer to consumer device. | 80 | * @dev: Pointer to consumer device. |
54 | * | 81 | * |