UPSTREAM: iio: core: Add devm_ APIs for iio_channel_{get,release}
authorLaxman Dewangan <ldewangan@nvidia.com>
Wed, 6 Apr 2016 10:31:06 +0000 (16:01 +0530)
committerHuang, Tao <huangtao@rock-chips.com>
Fri, 13 Jan 2017 11:40:57 +0000 (19:40 +0800)
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.

Change-Id: Ia00f42dab2f66aefa0b26523db849e75927003af
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Huang, Tao <huangtao@rock-chips.com>
(cherry picked from commit 8bf872d8d261feefcdf67027522e3f717cad2bfe)

drivers/iio/inkern.c
include/linux/iio/consumer.h

index 217e9306aa0ffbe3e952554501cf6ddf362abac1..228f3999b2c934513f8cedcdf0fc17f1e60f7972 100644 (file)
@@ -358,6 +358,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;
index fad58671c49e00217907275865eed4987bdd87ea..e1e033d6a81f034b249f032235c393892dafd196 100644 (file)
@@ -48,6 +48,33 @@ struct iio_channel *iio_channel_get(struct device *dev,
  */
 void iio_channel_release(struct iio_channel *chan);
 
+/**
+ * devm_iio_channel_get() - Resource managed version of iio_channel_get().
+ * @dev:               Pointer to consumer device. Device name must match
+ *                     the name of the device as provided in the iio_map
+ *                     with which the desired provider to consumer mapping
+ *                     was registered.
+ * @consumer_channel:  Unique name to identify the channel on the consumer
+ *                     side. This typically describes the channels use within
+ *                     the consumer. E.g. 'battery_voltage'
+ *
+ * Returns a pointer to negative errno if it is not able to get the iio channel
+ * otherwise returns valid pointer for iio channel.
+ *
+ * The allocated iio channel is automatically released when the device is
+ * unbound.
+ */
+struct iio_channel *devm_iio_channel_get(struct device *dev,
+                                        const char *consumer_channel);
+/**
+ * devm_iio_channel_release() - Resource managed version of
+ *                             iio_channel_release().
+ * @dev:               Pointer to consumer device for which resource
+ *                     is allocared.
+ * @chan:              The channel to be released.
+ */
+void devm_iio_channel_release(struct device *dev, struct iio_channel *chan);
+
 /**
  * iio_channel_get_all() - get all channels associated with a client
  * @dev:               Pointer to consumer device.