diff options
-rw-r--r-- | drivers/iio/industrialio-core.c | 47 | ||||
-rw-r--r-- | include/linux/iio/iio.h | 25 |
2 files changed, 72 insertions, 0 deletions
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index e145931ef1b8..d56d1229e2d6 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -912,6 +912,53 @@ void iio_device_free(struct iio_dev *dev) } EXPORT_SYMBOL(iio_device_free); +static void devm_iio_device_release(struct device *dev, void *res) +{ + iio_device_free(*(struct iio_dev **)res); +} + +static int devm_iio_device_match(struct device *dev, void *res, void *data) +{ + struct iio_dev **r = res; + if (!r || !*r) { + WARN_ON(!r || !*r); + return 0; + } + return *r == data; +} + +struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv) +{ + struct iio_dev **ptr, *iio_dev; + + ptr = devres_alloc(devm_iio_device_release, sizeof(*ptr), + GFP_KERNEL); + if (!ptr) + return NULL; + + /* use raw alloc_dr for kmalloc caller tracing */ + iio_dev = iio_device_alloc(sizeof_priv); + if (iio_dev) { + *ptr = iio_dev; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return iio_dev; +} +EXPORT_SYMBOL_GPL(devm_iio_device_alloc); + +void devm_iio_device_free(struct device *dev, struct iio_dev *iio_dev) +{ + int rc; + + rc = devres_release(dev, devm_iio_device_release, + devm_iio_device_match, iio_dev); + WARN_ON(rc); +} +EXPORT_SYMBOL_GPL(devm_iio_device_free); + /** * iio_chrdev_open() - chrdev file open for buffer access and ioctls **/ diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 3d35b7023591..61d220f89aca 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -532,6 +532,31 @@ static inline struct iio_dev *iio_priv_to_dev(void *priv) void iio_device_free(struct iio_dev *indio_dev); /** + * devm_iio_device_alloc - Resource-managed iio_device_alloc() + * @dev: Device to allocate iio_dev for + * @sizeof_priv: Space to allocate for private structure. + * + * Managed iio_device_alloc. iio_dev allocated with this function is + * automatically freed on driver detach. + * + * If an iio_dev allocated with this function needs to be freed separately, + * devm_iio_device_free() must be used. + * + * RETURNS: + * Pointer to allocated iio_dev on success, NULL on failure. + */ +struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv); + +/** + * devm_iio_device_free - Resource-managed iio_device_free() + * @dev: Device this iio_dev belongs to + * @indio_dev: the iio_dev associated with the device + * + * Free indio_dev allocated with devm_iio_device_alloc(). + */ +void devm_iio_device_free(struct device *dev, struct iio_dev *iio_dev); + +/** * iio_buffer_enabled() - helper function to test if the buffer is enabled * @indio_dev: IIO device structure for device **/ |