18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/* The industrial I/O core
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (c) 2008 Jonathan Cameron
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Handling of buffer allocation / resizing.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Things to look at here.
98c2ecf20Sopenharmony_ci * - Better memory allocation techniques?
108c2ecf20Sopenharmony_ci * - Alternative access techniques?
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci#include <linux/kernel.h>
138c2ecf20Sopenharmony_ci#include <linux/export.h>
148c2ecf20Sopenharmony_ci#include <linux/device.h>
158c2ecf20Sopenharmony_ci#include <linux/fs.h>
168c2ecf20Sopenharmony_ci#include <linux/cdev.h>
178c2ecf20Sopenharmony_ci#include <linux/slab.h>
188c2ecf20Sopenharmony_ci#include <linux/poll.h>
198c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#include <linux/iio/iio.h>
228c2ecf20Sopenharmony_ci#include <linux/iio/iio-opaque.h>
238c2ecf20Sopenharmony_ci#include "iio_core.h"
248c2ecf20Sopenharmony_ci#include "iio_core_trigger.h"
258c2ecf20Sopenharmony_ci#include <linux/iio/sysfs.h>
268c2ecf20Sopenharmony_ci#include <linux/iio/buffer.h>
278c2ecf20Sopenharmony_ci#include <linux/iio/buffer_impl.h>
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic const char * const iio_endian_prefix[] = {
308c2ecf20Sopenharmony_ci	[IIO_BE] = "be",
318c2ecf20Sopenharmony_ci	[IIO_LE] = "le",
328c2ecf20Sopenharmony_ci};
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic bool iio_buffer_is_active(struct iio_buffer *buf)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	return !list_empty(&buf->buffer_list);
378c2ecf20Sopenharmony_ci}
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_cistatic size_t iio_buffer_data_available(struct iio_buffer *buf)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	return buf->access->data_available(buf);
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic int iio_buffer_flush_hwfifo(struct iio_dev *indio_dev,
458c2ecf20Sopenharmony_ci				   struct iio_buffer *buf, size_t required)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	if (!indio_dev->info->hwfifo_flush_to_buffer)
488c2ecf20Sopenharmony_ci		return -ENODEV;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	return indio_dev->info->hwfifo_flush_to_buffer(indio_dev, required);
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistatic bool iio_buffer_ready(struct iio_dev *indio_dev, struct iio_buffer *buf,
548c2ecf20Sopenharmony_ci			     size_t to_wait, int to_flush)
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	size_t avail;
578c2ecf20Sopenharmony_ci	int flushed = 0;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	/* wakeup if the device was unregistered */
608c2ecf20Sopenharmony_ci	if (!indio_dev->info)
618c2ecf20Sopenharmony_ci		return true;
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	/* drain the buffer if it was disabled */
648c2ecf20Sopenharmony_ci	if (!iio_buffer_is_active(buf)) {
658c2ecf20Sopenharmony_ci		to_wait = min_t(size_t, to_wait, 1);
668c2ecf20Sopenharmony_ci		to_flush = 0;
678c2ecf20Sopenharmony_ci	}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	avail = iio_buffer_data_available(buf);
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	if (avail >= to_wait) {
728c2ecf20Sopenharmony_ci		/* force a flush for non-blocking reads */
738c2ecf20Sopenharmony_ci		if (!to_wait && avail < to_flush)
748c2ecf20Sopenharmony_ci			iio_buffer_flush_hwfifo(indio_dev, buf,
758c2ecf20Sopenharmony_ci						to_flush - avail);
768c2ecf20Sopenharmony_ci		return true;
778c2ecf20Sopenharmony_ci	}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	if (to_flush)
808c2ecf20Sopenharmony_ci		flushed = iio_buffer_flush_hwfifo(indio_dev, buf,
818c2ecf20Sopenharmony_ci						  to_wait - avail);
828c2ecf20Sopenharmony_ci	if (flushed <= 0)
838c2ecf20Sopenharmony_ci		return false;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	if (avail + flushed >= to_wait)
868c2ecf20Sopenharmony_ci		return true;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	return false;
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci/**
928c2ecf20Sopenharmony_ci * iio_buffer_read_outer() - chrdev read for buffer access
938c2ecf20Sopenharmony_ci * @filp:	File structure pointer for the char device
948c2ecf20Sopenharmony_ci * @buf:	Destination buffer for iio buffer read
958c2ecf20Sopenharmony_ci * @n:		First n bytes to read
968c2ecf20Sopenharmony_ci * @f_ps:	Long offset provided by the user as a seek position
978c2ecf20Sopenharmony_ci *
988c2ecf20Sopenharmony_ci * This function relies on all buffer implementations having an
998c2ecf20Sopenharmony_ci * iio_buffer as their first element.
1008c2ecf20Sopenharmony_ci *
1018c2ecf20Sopenharmony_ci * Return: negative values corresponding to error codes or ret != 0
1028c2ecf20Sopenharmony_ci *	   for ending the reading activity
1038c2ecf20Sopenharmony_ci **/
1048c2ecf20Sopenharmony_cissize_t iio_buffer_read_outer(struct file *filp, char __user *buf,
1058c2ecf20Sopenharmony_ci			      size_t n, loff_t *f_ps)
1068c2ecf20Sopenharmony_ci{
1078c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev = filp->private_data;
1088c2ecf20Sopenharmony_ci	struct iio_buffer *rb = indio_dev->buffer;
1098c2ecf20Sopenharmony_ci	DEFINE_WAIT_FUNC(wait, woken_wake_function);
1108c2ecf20Sopenharmony_ci	size_t datum_size;
1118c2ecf20Sopenharmony_ci	size_t to_wait;
1128c2ecf20Sopenharmony_ci	int ret = 0;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	if (!indio_dev->info)
1158c2ecf20Sopenharmony_ci		return -ENODEV;
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	if (!rb || !rb->access->read)
1188c2ecf20Sopenharmony_ci		return -EINVAL;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	datum_size = rb->bytes_per_datum;
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	/*
1238c2ecf20Sopenharmony_ci	 * If datum_size is 0 there will never be anything to read from the
1248c2ecf20Sopenharmony_ci	 * buffer, so signal end of file now.
1258c2ecf20Sopenharmony_ci	 */
1268c2ecf20Sopenharmony_ci	if (!datum_size)
1278c2ecf20Sopenharmony_ci		return 0;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	if (filp->f_flags & O_NONBLOCK)
1308c2ecf20Sopenharmony_ci		to_wait = 0;
1318c2ecf20Sopenharmony_ci	else
1328c2ecf20Sopenharmony_ci		to_wait = min_t(size_t, n / datum_size, rb->watermark);
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	add_wait_queue(&rb->pollq, &wait);
1358c2ecf20Sopenharmony_ci	do {
1368c2ecf20Sopenharmony_ci		if (!indio_dev->info) {
1378c2ecf20Sopenharmony_ci			ret = -ENODEV;
1388c2ecf20Sopenharmony_ci			break;
1398c2ecf20Sopenharmony_ci		}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci		if (!iio_buffer_ready(indio_dev, rb, to_wait, n / datum_size)) {
1428c2ecf20Sopenharmony_ci			if (signal_pending(current)) {
1438c2ecf20Sopenharmony_ci				ret = -ERESTARTSYS;
1448c2ecf20Sopenharmony_ci				break;
1458c2ecf20Sopenharmony_ci			}
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci			wait_woken(&wait, TASK_INTERRUPTIBLE,
1488c2ecf20Sopenharmony_ci				   MAX_SCHEDULE_TIMEOUT);
1498c2ecf20Sopenharmony_ci			continue;
1508c2ecf20Sopenharmony_ci		}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci		ret = rb->access->read(rb, n, buf);
1538c2ecf20Sopenharmony_ci		if (ret == 0 && (filp->f_flags & O_NONBLOCK))
1548c2ecf20Sopenharmony_ci			ret = -EAGAIN;
1558c2ecf20Sopenharmony_ci	} while (ret == 0);
1568c2ecf20Sopenharmony_ci	remove_wait_queue(&rb->pollq, &wait);
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	return ret;
1598c2ecf20Sopenharmony_ci}
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci/**
1628c2ecf20Sopenharmony_ci * iio_buffer_poll() - poll the buffer to find out if it has data
1638c2ecf20Sopenharmony_ci * @filp:	File structure pointer for device access
1648c2ecf20Sopenharmony_ci * @wait:	Poll table structure pointer for which the driver adds
1658c2ecf20Sopenharmony_ci *		a wait queue
1668c2ecf20Sopenharmony_ci *
1678c2ecf20Sopenharmony_ci * Return: (EPOLLIN | EPOLLRDNORM) if data is available for reading
1688c2ecf20Sopenharmony_ci *	   or 0 for other cases
1698c2ecf20Sopenharmony_ci */
1708c2ecf20Sopenharmony_ci__poll_t iio_buffer_poll(struct file *filp,
1718c2ecf20Sopenharmony_ci			     struct poll_table_struct *wait)
1728c2ecf20Sopenharmony_ci{
1738c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev = filp->private_data;
1748c2ecf20Sopenharmony_ci	struct iio_buffer *rb = indio_dev->buffer;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	if (!indio_dev->info || rb == NULL)
1778c2ecf20Sopenharmony_ci		return 0;
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	poll_wait(filp, &rb->pollq, wait);
1808c2ecf20Sopenharmony_ci	if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0))
1818c2ecf20Sopenharmony_ci		return EPOLLIN | EPOLLRDNORM;
1828c2ecf20Sopenharmony_ci	return 0;
1838c2ecf20Sopenharmony_ci}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci/**
1868c2ecf20Sopenharmony_ci * iio_buffer_wakeup_poll - Wakes up the buffer waitqueue
1878c2ecf20Sopenharmony_ci * @indio_dev: The IIO device
1888c2ecf20Sopenharmony_ci *
1898c2ecf20Sopenharmony_ci * Wakes up the event waitqueue used for poll(). Should usually
1908c2ecf20Sopenharmony_ci * be called when the device is unregistered.
1918c2ecf20Sopenharmony_ci */
1928c2ecf20Sopenharmony_civoid iio_buffer_wakeup_poll(struct iio_dev *indio_dev)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	struct iio_buffer *buffer = indio_dev->buffer;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	if (!buffer)
1978c2ecf20Sopenharmony_ci		return;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	wake_up(&buffer->pollq);
2008c2ecf20Sopenharmony_ci}
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_civoid iio_buffer_init(struct iio_buffer *buffer)
2038c2ecf20Sopenharmony_ci{
2048c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&buffer->demux_list);
2058c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&buffer->buffer_list);
2068c2ecf20Sopenharmony_ci	init_waitqueue_head(&buffer->pollq);
2078c2ecf20Sopenharmony_ci	kref_init(&buffer->ref);
2088c2ecf20Sopenharmony_ci	if (!buffer->watermark)
2098c2ecf20Sopenharmony_ci		buffer->watermark = 1;
2108c2ecf20Sopenharmony_ci}
2118c2ecf20Sopenharmony_ciEXPORT_SYMBOL(iio_buffer_init);
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci/**
2148c2ecf20Sopenharmony_ci * iio_buffer_set_attrs - Set buffer specific attributes
2158c2ecf20Sopenharmony_ci * @buffer: The buffer for which we are setting attributes
2168c2ecf20Sopenharmony_ci * @attrs: Pointer to a null terminated list of pointers to attributes
2178c2ecf20Sopenharmony_ci */
2188c2ecf20Sopenharmony_civoid iio_buffer_set_attrs(struct iio_buffer *buffer,
2198c2ecf20Sopenharmony_ci			 const struct attribute **attrs)
2208c2ecf20Sopenharmony_ci{
2218c2ecf20Sopenharmony_ci	buffer->attrs = attrs;
2228c2ecf20Sopenharmony_ci}
2238c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(iio_buffer_set_attrs);
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_cistatic ssize_t iio_show_scan_index(struct device *dev,
2268c2ecf20Sopenharmony_ci				   struct device_attribute *attr,
2278c2ecf20Sopenharmony_ci				   char *buf)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	return sprintf(buf, "%u\n", to_iio_dev_attr(attr)->c->scan_index);
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic ssize_t iio_show_fixed_type(struct device *dev,
2338c2ecf20Sopenharmony_ci				   struct device_attribute *attr,
2348c2ecf20Sopenharmony_ci				   char *buf)
2358c2ecf20Sopenharmony_ci{
2368c2ecf20Sopenharmony_ci	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
2378c2ecf20Sopenharmony_ci	u8 type = this_attr->c->scan_type.endianness;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	if (type == IIO_CPU) {
2408c2ecf20Sopenharmony_ci#ifdef __LITTLE_ENDIAN
2418c2ecf20Sopenharmony_ci		type = IIO_LE;
2428c2ecf20Sopenharmony_ci#else
2438c2ecf20Sopenharmony_ci		type = IIO_BE;
2448c2ecf20Sopenharmony_ci#endif
2458c2ecf20Sopenharmony_ci	}
2468c2ecf20Sopenharmony_ci	if (this_attr->c->scan_type.repeat > 1)
2478c2ecf20Sopenharmony_ci		return sprintf(buf, "%s:%c%d/%dX%d>>%u\n",
2488c2ecf20Sopenharmony_ci		       iio_endian_prefix[type],
2498c2ecf20Sopenharmony_ci		       this_attr->c->scan_type.sign,
2508c2ecf20Sopenharmony_ci		       this_attr->c->scan_type.realbits,
2518c2ecf20Sopenharmony_ci		       this_attr->c->scan_type.storagebits,
2528c2ecf20Sopenharmony_ci		       this_attr->c->scan_type.repeat,
2538c2ecf20Sopenharmony_ci		       this_attr->c->scan_type.shift);
2548c2ecf20Sopenharmony_ci		else
2558c2ecf20Sopenharmony_ci			return sprintf(buf, "%s:%c%d/%d>>%u\n",
2568c2ecf20Sopenharmony_ci		       iio_endian_prefix[type],
2578c2ecf20Sopenharmony_ci		       this_attr->c->scan_type.sign,
2588c2ecf20Sopenharmony_ci		       this_attr->c->scan_type.realbits,
2598c2ecf20Sopenharmony_ci		       this_attr->c->scan_type.storagebits,
2608c2ecf20Sopenharmony_ci		       this_attr->c->scan_type.shift);
2618c2ecf20Sopenharmony_ci}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_cistatic ssize_t iio_scan_el_show(struct device *dev,
2648c2ecf20Sopenharmony_ci				struct device_attribute *attr,
2658c2ecf20Sopenharmony_ci				char *buf)
2668c2ecf20Sopenharmony_ci{
2678c2ecf20Sopenharmony_ci	int ret;
2688c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
2698c2ecf20Sopenharmony_ci	struct iio_buffer *buffer = indio_dev->buffer;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	/* Ensure ret is 0 or 1. */
2728c2ecf20Sopenharmony_ci	ret = !!test_bit(to_iio_dev_attr(attr)->address,
2738c2ecf20Sopenharmony_ci		       buffer->scan_mask);
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", ret);
2768c2ecf20Sopenharmony_ci}
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci/* Note NULL used as error indicator as it doesn't make sense. */
2798c2ecf20Sopenharmony_cistatic const unsigned long *iio_scan_mask_match(const unsigned long *av_masks,
2808c2ecf20Sopenharmony_ci					  unsigned int masklength,
2818c2ecf20Sopenharmony_ci					  const unsigned long *mask,
2828c2ecf20Sopenharmony_ci					  bool strict)
2838c2ecf20Sopenharmony_ci{
2848c2ecf20Sopenharmony_ci	if (bitmap_empty(mask, masklength))
2858c2ecf20Sopenharmony_ci		return NULL;
2868c2ecf20Sopenharmony_ci	while (*av_masks) {
2878c2ecf20Sopenharmony_ci		if (strict) {
2888c2ecf20Sopenharmony_ci			if (bitmap_equal(mask, av_masks, masklength))
2898c2ecf20Sopenharmony_ci				return av_masks;
2908c2ecf20Sopenharmony_ci		} else {
2918c2ecf20Sopenharmony_ci			if (bitmap_subset(mask, av_masks, masklength))
2928c2ecf20Sopenharmony_ci				return av_masks;
2938c2ecf20Sopenharmony_ci		}
2948c2ecf20Sopenharmony_ci		av_masks += BITS_TO_LONGS(masklength);
2958c2ecf20Sopenharmony_ci	}
2968c2ecf20Sopenharmony_ci	return NULL;
2978c2ecf20Sopenharmony_ci}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_cistatic bool iio_validate_scan_mask(struct iio_dev *indio_dev,
3008c2ecf20Sopenharmony_ci	const unsigned long *mask)
3018c2ecf20Sopenharmony_ci{
3028c2ecf20Sopenharmony_ci	if (!indio_dev->setup_ops->validate_scan_mask)
3038c2ecf20Sopenharmony_ci		return true;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	return indio_dev->setup_ops->validate_scan_mask(indio_dev, mask);
3068c2ecf20Sopenharmony_ci}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci/**
3098c2ecf20Sopenharmony_ci * iio_scan_mask_set() - set particular bit in the scan mask
3108c2ecf20Sopenharmony_ci * @indio_dev: the iio device
3118c2ecf20Sopenharmony_ci * @buffer: the buffer whose scan mask we are interested in
3128c2ecf20Sopenharmony_ci * @bit: the bit to be set.
3138c2ecf20Sopenharmony_ci *
3148c2ecf20Sopenharmony_ci * Note that at this point we have no way of knowing what other
3158c2ecf20Sopenharmony_ci * buffers might request, hence this code only verifies that the
3168c2ecf20Sopenharmony_ci * individual buffers request is plausible.
3178c2ecf20Sopenharmony_ci */
3188c2ecf20Sopenharmony_cistatic int iio_scan_mask_set(struct iio_dev *indio_dev,
3198c2ecf20Sopenharmony_ci		      struct iio_buffer *buffer, int bit)
3208c2ecf20Sopenharmony_ci{
3218c2ecf20Sopenharmony_ci	const unsigned long *mask;
3228c2ecf20Sopenharmony_ci	unsigned long *trialmask;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	trialmask = bitmap_zalloc(indio_dev->masklength, GFP_KERNEL);
3258c2ecf20Sopenharmony_ci	if (trialmask == NULL)
3268c2ecf20Sopenharmony_ci		return -ENOMEM;
3278c2ecf20Sopenharmony_ci	if (!indio_dev->masklength) {
3288c2ecf20Sopenharmony_ci		WARN(1, "Trying to set scanmask prior to registering buffer\n");
3298c2ecf20Sopenharmony_ci		goto err_invalid_mask;
3308c2ecf20Sopenharmony_ci	}
3318c2ecf20Sopenharmony_ci	bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength);
3328c2ecf20Sopenharmony_ci	set_bit(bit, trialmask);
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	if (!iio_validate_scan_mask(indio_dev, trialmask))
3358c2ecf20Sopenharmony_ci		goto err_invalid_mask;
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	if (indio_dev->available_scan_masks) {
3388c2ecf20Sopenharmony_ci		mask = iio_scan_mask_match(indio_dev->available_scan_masks,
3398c2ecf20Sopenharmony_ci					   indio_dev->masklength,
3408c2ecf20Sopenharmony_ci					   trialmask, false);
3418c2ecf20Sopenharmony_ci		if (!mask)
3428c2ecf20Sopenharmony_ci			goto err_invalid_mask;
3438c2ecf20Sopenharmony_ci	}
3448c2ecf20Sopenharmony_ci	bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength);
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	bitmap_free(trialmask);
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	return 0;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_cierr_invalid_mask:
3518c2ecf20Sopenharmony_ci	bitmap_free(trialmask);
3528c2ecf20Sopenharmony_ci	return -EINVAL;
3538c2ecf20Sopenharmony_ci}
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_cistatic int iio_scan_mask_clear(struct iio_buffer *buffer, int bit)
3568c2ecf20Sopenharmony_ci{
3578c2ecf20Sopenharmony_ci	clear_bit(bit, buffer->scan_mask);
3588c2ecf20Sopenharmony_ci	return 0;
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_cistatic int iio_scan_mask_query(struct iio_dev *indio_dev,
3628c2ecf20Sopenharmony_ci			       struct iio_buffer *buffer, int bit)
3638c2ecf20Sopenharmony_ci{
3648c2ecf20Sopenharmony_ci	if (bit > indio_dev->masklength)
3658c2ecf20Sopenharmony_ci		return -EINVAL;
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	if (!buffer->scan_mask)
3688c2ecf20Sopenharmony_ci		return 0;
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	/* Ensure return value is 0 or 1. */
3718c2ecf20Sopenharmony_ci	return !!test_bit(bit, buffer->scan_mask);
3728c2ecf20Sopenharmony_ci};
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_cistatic ssize_t iio_scan_el_store(struct device *dev,
3758c2ecf20Sopenharmony_ci				 struct device_attribute *attr,
3768c2ecf20Sopenharmony_ci				 const char *buf,
3778c2ecf20Sopenharmony_ci				 size_t len)
3788c2ecf20Sopenharmony_ci{
3798c2ecf20Sopenharmony_ci	int ret;
3808c2ecf20Sopenharmony_ci	bool state;
3818c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
3828c2ecf20Sopenharmony_ci	struct iio_buffer *buffer = indio_dev->buffer;
3838c2ecf20Sopenharmony_ci	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	ret = strtobool(buf, &state);
3868c2ecf20Sopenharmony_ci	if (ret < 0)
3878c2ecf20Sopenharmony_ci		return ret;
3888c2ecf20Sopenharmony_ci	mutex_lock(&indio_dev->mlock);
3898c2ecf20Sopenharmony_ci	if (iio_buffer_is_active(buffer)) {
3908c2ecf20Sopenharmony_ci		ret = -EBUSY;
3918c2ecf20Sopenharmony_ci		goto error_ret;
3928c2ecf20Sopenharmony_ci	}
3938c2ecf20Sopenharmony_ci	ret = iio_scan_mask_query(indio_dev, buffer, this_attr->address);
3948c2ecf20Sopenharmony_ci	if (ret < 0)
3958c2ecf20Sopenharmony_ci		goto error_ret;
3968c2ecf20Sopenharmony_ci	if (!state && ret) {
3978c2ecf20Sopenharmony_ci		ret = iio_scan_mask_clear(buffer, this_attr->address);
3988c2ecf20Sopenharmony_ci		if (ret)
3998c2ecf20Sopenharmony_ci			goto error_ret;
4008c2ecf20Sopenharmony_ci	} else if (state && !ret) {
4018c2ecf20Sopenharmony_ci		ret = iio_scan_mask_set(indio_dev, buffer, this_attr->address);
4028c2ecf20Sopenharmony_ci		if (ret)
4038c2ecf20Sopenharmony_ci			goto error_ret;
4048c2ecf20Sopenharmony_ci	}
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_cierror_ret:
4078c2ecf20Sopenharmony_ci	mutex_unlock(&indio_dev->mlock);
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	return ret < 0 ? ret : len;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci}
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_cistatic ssize_t iio_scan_el_ts_show(struct device *dev,
4148c2ecf20Sopenharmony_ci				   struct device_attribute *attr,
4158c2ecf20Sopenharmony_ci				   char *buf)
4168c2ecf20Sopenharmony_ci{
4178c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
4188c2ecf20Sopenharmony_ci	struct iio_buffer *buffer = indio_dev->buffer;
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", buffer->scan_timestamp);
4218c2ecf20Sopenharmony_ci}
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_cistatic ssize_t iio_scan_el_ts_store(struct device *dev,
4248c2ecf20Sopenharmony_ci				    struct device_attribute *attr,
4258c2ecf20Sopenharmony_ci				    const char *buf,
4268c2ecf20Sopenharmony_ci				    size_t len)
4278c2ecf20Sopenharmony_ci{
4288c2ecf20Sopenharmony_ci	int ret;
4298c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
4308c2ecf20Sopenharmony_ci	struct iio_buffer *buffer = indio_dev->buffer;
4318c2ecf20Sopenharmony_ci	bool state;
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	ret = strtobool(buf, &state);
4348c2ecf20Sopenharmony_ci	if (ret < 0)
4358c2ecf20Sopenharmony_ci		return ret;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	mutex_lock(&indio_dev->mlock);
4388c2ecf20Sopenharmony_ci	if (iio_buffer_is_active(buffer)) {
4398c2ecf20Sopenharmony_ci		ret = -EBUSY;
4408c2ecf20Sopenharmony_ci		goto error_ret;
4418c2ecf20Sopenharmony_ci	}
4428c2ecf20Sopenharmony_ci	buffer->scan_timestamp = state;
4438c2ecf20Sopenharmony_cierror_ret:
4448c2ecf20Sopenharmony_ci	mutex_unlock(&indio_dev->mlock);
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	return ret ? ret : len;
4478c2ecf20Sopenharmony_ci}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_cistatic int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
4508c2ecf20Sopenharmony_ci					struct iio_buffer *buffer,
4518c2ecf20Sopenharmony_ci					const struct iio_chan_spec *chan)
4528c2ecf20Sopenharmony_ci{
4538c2ecf20Sopenharmony_ci	int ret, attrcount = 0;
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	ret = __iio_add_chan_devattr("index",
4568c2ecf20Sopenharmony_ci				     chan,
4578c2ecf20Sopenharmony_ci				     &iio_show_scan_index,
4588c2ecf20Sopenharmony_ci				     NULL,
4598c2ecf20Sopenharmony_ci				     0,
4608c2ecf20Sopenharmony_ci				     IIO_SEPARATE,
4618c2ecf20Sopenharmony_ci				     &indio_dev->dev,
4628c2ecf20Sopenharmony_ci				     &buffer->scan_el_dev_attr_list);
4638c2ecf20Sopenharmony_ci	if (ret)
4648c2ecf20Sopenharmony_ci		return ret;
4658c2ecf20Sopenharmony_ci	attrcount++;
4668c2ecf20Sopenharmony_ci	ret = __iio_add_chan_devattr("type",
4678c2ecf20Sopenharmony_ci				     chan,
4688c2ecf20Sopenharmony_ci				     &iio_show_fixed_type,
4698c2ecf20Sopenharmony_ci				     NULL,
4708c2ecf20Sopenharmony_ci				     0,
4718c2ecf20Sopenharmony_ci				     0,
4728c2ecf20Sopenharmony_ci				     &indio_dev->dev,
4738c2ecf20Sopenharmony_ci				     &buffer->scan_el_dev_attr_list);
4748c2ecf20Sopenharmony_ci	if (ret)
4758c2ecf20Sopenharmony_ci		return ret;
4768c2ecf20Sopenharmony_ci	attrcount++;
4778c2ecf20Sopenharmony_ci	if (chan->type != IIO_TIMESTAMP)
4788c2ecf20Sopenharmony_ci		ret = __iio_add_chan_devattr("en",
4798c2ecf20Sopenharmony_ci					     chan,
4808c2ecf20Sopenharmony_ci					     &iio_scan_el_show,
4818c2ecf20Sopenharmony_ci					     &iio_scan_el_store,
4828c2ecf20Sopenharmony_ci					     chan->scan_index,
4838c2ecf20Sopenharmony_ci					     0,
4848c2ecf20Sopenharmony_ci					     &indio_dev->dev,
4858c2ecf20Sopenharmony_ci					     &buffer->scan_el_dev_attr_list);
4868c2ecf20Sopenharmony_ci	else
4878c2ecf20Sopenharmony_ci		ret = __iio_add_chan_devattr("en",
4888c2ecf20Sopenharmony_ci					     chan,
4898c2ecf20Sopenharmony_ci					     &iio_scan_el_ts_show,
4908c2ecf20Sopenharmony_ci					     &iio_scan_el_ts_store,
4918c2ecf20Sopenharmony_ci					     chan->scan_index,
4928c2ecf20Sopenharmony_ci					     0,
4938c2ecf20Sopenharmony_ci					     &indio_dev->dev,
4948c2ecf20Sopenharmony_ci					     &buffer->scan_el_dev_attr_list);
4958c2ecf20Sopenharmony_ci	if (ret)
4968c2ecf20Sopenharmony_ci		return ret;
4978c2ecf20Sopenharmony_ci	attrcount++;
4988c2ecf20Sopenharmony_ci	ret = attrcount;
4998c2ecf20Sopenharmony_ci	return ret;
5008c2ecf20Sopenharmony_ci}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_cistatic ssize_t iio_buffer_read_length(struct device *dev,
5038c2ecf20Sopenharmony_ci				      struct device_attribute *attr,
5048c2ecf20Sopenharmony_ci				      char *buf)
5058c2ecf20Sopenharmony_ci{
5068c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
5078c2ecf20Sopenharmony_ci	struct iio_buffer *buffer = indio_dev->buffer;
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", buffer->length);
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_cistatic ssize_t iio_buffer_write_length(struct device *dev,
5138c2ecf20Sopenharmony_ci				       struct device_attribute *attr,
5148c2ecf20Sopenharmony_ci				       const char *buf, size_t len)
5158c2ecf20Sopenharmony_ci{
5168c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
5178c2ecf20Sopenharmony_ci	struct iio_buffer *buffer = indio_dev->buffer;
5188c2ecf20Sopenharmony_ci	unsigned int val;
5198c2ecf20Sopenharmony_ci	int ret;
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	ret = kstrtouint(buf, 10, &val);
5228c2ecf20Sopenharmony_ci	if (ret)
5238c2ecf20Sopenharmony_ci		return ret;
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	if (val == buffer->length)
5268c2ecf20Sopenharmony_ci		return len;
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci	mutex_lock(&indio_dev->mlock);
5298c2ecf20Sopenharmony_ci	if (iio_buffer_is_active(buffer)) {
5308c2ecf20Sopenharmony_ci		ret = -EBUSY;
5318c2ecf20Sopenharmony_ci	} else {
5328c2ecf20Sopenharmony_ci		buffer->access->set_length(buffer, val);
5338c2ecf20Sopenharmony_ci		ret = 0;
5348c2ecf20Sopenharmony_ci	}
5358c2ecf20Sopenharmony_ci	if (ret)
5368c2ecf20Sopenharmony_ci		goto out;
5378c2ecf20Sopenharmony_ci	if (buffer->length && buffer->length < buffer->watermark)
5388c2ecf20Sopenharmony_ci		buffer->watermark = buffer->length;
5398c2ecf20Sopenharmony_ciout:
5408c2ecf20Sopenharmony_ci	mutex_unlock(&indio_dev->mlock);
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	return ret ? ret : len;
5438c2ecf20Sopenharmony_ci}
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_cistatic ssize_t iio_buffer_show_enable(struct device *dev,
5468c2ecf20Sopenharmony_ci				      struct device_attribute *attr,
5478c2ecf20Sopenharmony_ci				      char *buf)
5488c2ecf20Sopenharmony_ci{
5498c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
5508c2ecf20Sopenharmony_ci	struct iio_buffer *buffer = indio_dev->buffer;
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", iio_buffer_is_active(buffer));
5538c2ecf20Sopenharmony_ci}
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_cistatic unsigned int iio_storage_bytes_for_si(struct iio_dev *indio_dev,
5568c2ecf20Sopenharmony_ci					     unsigned int scan_index)
5578c2ecf20Sopenharmony_ci{
5588c2ecf20Sopenharmony_ci	const struct iio_chan_spec *ch;
5598c2ecf20Sopenharmony_ci	unsigned int bytes;
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	ch = iio_find_channel_from_si(indio_dev, scan_index);
5628c2ecf20Sopenharmony_ci	bytes = ch->scan_type.storagebits / 8;
5638c2ecf20Sopenharmony_ci	if (ch->scan_type.repeat > 1)
5648c2ecf20Sopenharmony_ci		bytes *= ch->scan_type.repeat;
5658c2ecf20Sopenharmony_ci	return bytes;
5668c2ecf20Sopenharmony_ci}
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_cistatic unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev)
5698c2ecf20Sopenharmony_ci{
5708c2ecf20Sopenharmony_ci	return iio_storage_bytes_for_si(indio_dev,
5718c2ecf20Sopenharmony_ci					indio_dev->scan_index_timestamp);
5728c2ecf20Sopenharmony_ci}
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_cistatic int iio_compute_scan_bytes(struct iio_dev *indio_dev,
5758c2ecf20Sopenharmony_ci				const unsigned long *mask, bool timestamp)
5768c2ecf20Sopenharmony_ci{
5778c2ecf20Sopenharmony_ci	unsigned bytes = 0;
5788c2ecf20Sopenharmony_ci	int length, i, largest = 0;
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	/* How much space will the demuxed element take? */
5818c2ecf20Sopenharmony_ci	for_each_set_bit(i, mask,
5828c2ecf20Sopenharmony_ci			 indio_dev->masklength) {
5838c2ecf20Sopenharmony_ci		length = iio_storage_bytes_for_si(indio_dev, i);
5848c2ecf20Sopenharmony_ci		bytes = ALIGN(bytes, length);
5858c2ecf20Sopenharmony_ci		bytes += length;
5868c2ecf20Sopenharmony_ci		largest = max(largest, length);
5878c2ecf20Sopenharmony_ci	}
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	if (timestamp) {
5908c2ecf20Sopenharmony_ci		length = iio_storage_bytes_for_timestamp(indio_dev);
5918c2ecf20Sopenharmony_ci		bytes = ALIGN(bytes, length);
5928c2ecf20Sopenharmony_ci		bytes += length;
5938c2ecf20Sopenharmony_ci		largest = max(largest, length);
5948c2ecf20Sopenharmony_ci	}
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	bytes = ALIGN(bytes, largest);
5978c2ecf20Sopenharmony_ci	return bytes;
5988c2ecf20Sopenharmony_ci}
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_cistatic void iio_buffer_activate(struct iio_dev *indio_dev,
6018c2ecf20Sopenharmony_ci	struct iio_buffer *buffer)
6028c2ecf20Sopenharmony_ci{
6038c2ecf20Sopenharmony_ci	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	iio_buffer_get(buffer);
6068c2ecf20Sopenharmony_ci	list_add(&buffer->buffer_list, &iio_dev_opaque->buffer_list);
6078c2ecf20Sopenharmony_ci}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_cistatic void iio_buffer_deactivate(struct iio_buffer *buffer)
6108c2ecf20Sopenharmony_ci{
6118c2ecf20Sopenharmony_ci	list_del_init(&buffer->buffer_list);
6128c2ecf20Sopenharmony_ci	wake_up_interruptible(&buffer->pollq);
6138c2ecf20Sopenharmony_ci	iio_buffer_put(buffer);
6148c2ecf20Sopenharmony_ci}
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_cistatic void iio_buffer_deactivate_all(struct iio_dev *indio_dev)
6178c2ecf20Sopenharmony_ci{
6188c2ecf20Sopenharmony_ci	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
6198c2ecf20Sopenharmony_ci	struct iio_buffer *buffer, *_buffer;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	list_for_each_entry_safe(buffer, _buffer,
6228c2ecf20Sopenharmony_ci			&iio_dev_opaque->buffer_list, buffer_list)
6238c2ecf20Sopenharmony_ci		iio_buffer_deactivate(buffer);
6248c2ecf20Sopenharmony_ci}
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_cistatic int iio_buffer_enable(struct iio_buffer *buffer,
6278c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev)
6288c2ecf20Sopenharmony_ci{
6298c2ecf20Sopenharmony_ci	if (!buffer->access->enable)
6308c2ecf20Sopenharmony_ci		return 0;
6318c2ecf20Sopenharmony_ci	return buffer->access->enable(buffer, indio_dev);
6328c2ecf20Sopenharmony_ci}
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_cistatic int iio_buffer_disable(struct iio_buffer *buffer,
6358c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev)
6368c2ecf20Sopenharmony_ci{
6378c2ecf20Sopenharmony_ci	if (!buffer->access->disable)
6388c2ecf20Sopenharmony_ci		return 0;
6398c2ecf20Sopenharmony_ci	return buffer->access->disable(buffer, indio_dev);
6408c2ecf20Sopenharmony_ci}
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_cistatic void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev,
6438c2ecf20Sopenharmony_ci	struct iio_buffer *buffer)
6448c2ecf20Sopenharmony_ci{
6458c2ecf20Sopenharmony_ci	unsigned int bytes;
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	if (!buffer->access->set_bytes_per_datum)
6488c2ecf20Sopenharmony_ci		return;
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	bytes = iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
6518c2ecf20Sopenharmony_ci		buffer->scan_timestamp);
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	buffer->access->set_bytes_per_datum(buffer, bytes);
6548c2ecf20Sopenharmony_ci}
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_cistatic int iio_buffer_request_update(struct iio_dev *indio_dev,
6578c2ecf20Sopenharmony_ci	struct iio_buffer *buffer)
6588c2ecf20Sopenharmony_ci{
6598c2ecf20Sopenharmony_ci	int ret;
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	iio_buffer_update_bytes_per_datum(indio_dev, buffer);
6628c2ecf20Sopenharmony_ci	if (buffer->access->request_update) {
6638c2ecf20Sopenharmony_ci		ret = buffer->access->request_update(buffer);
6648c2ecf20Sopenharmony_ci		if (ret) {
6658c2ecf20Sopenharmony_ci			dev_dbg(&indio_dev->dev,
6668c2ecf20Sopenharmony_ci			       "Buffer not started: buffer parameter update failed (%d)\n",
6678c2ecf20Sopenharmony_ci				ret);
6688c2ecf20Sopenharmony_ci			return ret;
6698c2ecf20Sopenharmony_ci		}
6708c2ecf20Sopenharmony_ci	}
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	return 0;
6738c2ecf20Sopenharmony_ci}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_cistatic void iio_free_scan_mask(struct iio_dev *indio_dev,
6768c2ecf20Sopenharmony_ci	const unsigned long *mask)
6778c2ecf20Sopenharmony_ci{
6788c2ecf20Sopenharmony_ci	/* If the mask is dynamically allocated free it, otherwise do nothing */
6798c2ecf20Sopenharmony_ci	if (!indio_dev->available_scan_masks)
6808c2ecf20Sopenharmony_ci		bitmap_free(mask);
6818c2ecf20Sopenharmony_ci}
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_cistruct iio_device_config {
6848c2ecf20Sopenharmony_ci	unsigned int mode;
6858c2ecf20Sopenharmony_ci	unsigned int watermark;
6868c2ecf20Sopenharmony_ci	const unsigned long *scan_mask;
6878c2ecf20Sopenharmony_ci	unsigned int scan_bytes;
6888c2ecf20Sopenharmony_ci	bool scan_timestamp;
6898c2ecf20Sopenharmony_ci};
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_cistatic int iio_verify_update(struct iio_dev *indio_dev,
6928c2ecf20Sopenharmony_ci	struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer,
6938c2ecf20Sopenharmony_ci	struct iio_device_config *config)
6948c2ecf20Sopenharmony_ci{
6958c2ecf20Sopenharmony_ci	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
6968c2ecf20Sopenharmony_ci	unsigned long *compound_mask;
6978c2ecf20Sopenharmony_ci	const unsigned long *scan_mask;
6988c2ecf20Sopenharmony_ci	bool strict_scanmask = false;
6998c2ecf20Sopenharmony_ci	struct iio_buffer *buffer;
7008c2ecf20Sopenharmony_ci	bool scan_timestamp;
7018c2ecf20Sopenharmony_ci	unsigned int modes;
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci	if (insert_buffer &&
7048c2ecf20Sopenharmony_ci	    bitmap_empty(insert_buffer->scan_mask, indio_dev->masklength)) {
7058c2ecf20Sopenharmony_ci		dev_dbg(&indio_dev->dev,
7068c2ecf20Sopenharmony_ci			"At least one scan element must be enabled first\n");
7078c2ecf20Sopenharmony_ci		return -EINVAL;
7088c2ecf20Sopenharmony_ci	}
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	memset(config, 0, sizeof(*config));
7118c2ecf20Sopenharmony_ci	config->watermark = ~0;
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	/*
7148c2ecf20Sopenharmony_ci	 * If there is just one buffer and we are removing it there is nothing
7158c2ecf20Sopenharmony_ci	 * to verify.
7168c2ecf20Sopenharmony_ci	 */
7178c2ecf20Sopenharmony_ci	if (remove_buffer && !insert_buffer &&
7188c2ecf20Sopenharmony_ci		list_is_singular(&iio_dev_opaque->buffer_list))
7198c2ecf20Sopenharmony_ci			return 0;
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci	modes = indio_dev->modes;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
7248c2ecf20Sopenharmony_ci		if (buffer == remove_buffer)
7258c2ecf20Sopenharmony_ci			continue;
7268c2ecf20Sopenharmony_ci		modes &= buffer->access->modes;
7278c2ecf20Sopenharmony_ci		config->watermark = min(config->watermark, buffer->watermark);
7288c2ecf20Sopenharmony_ci	}
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	if (insert_buffer) {
7318c2ecf20Sopenharmony_ci		modes &= insert_buffer->access->modes;
7328c2ecf20Sopenharmony_ci		config->watermark = min(config->watermark,
7338c2ecf20Sopenharmony_ci			insert_buffer->watermark);
7348c2ecf20Sopenharmony_ci	}
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	/* Definitely possible for devices to support both of these. */
7378c2ecf20Sopenharmony_ci	if ((modes & INDIO_BUFFER_TRIGGERED) && indio_dev->trig) {
7388c2ecf20Sopenharmony_ci		config->mode = INDIO_BUFFER_TRIGGERED;
7398c2ecf20Sopenharmony_ci	} else if (modes & INDIO_BUFFER_HARDWARE) {
7408c2ecf20Sopenharmony_ci		/*
7418c2ecf20Sopenharmony_ci		 * Keep things simple for now and only allow a single buffer to
7428c2ecf20Sopenharmony_ci		 * be connected in hardware mode.
7438c2ecf20Sopenharmony_ci		 */
7448c2ecf20Sopenharmony_ci		if (insert_buffer && !list_empty(&iio_dev_opaque->buffer_list))
7458c2ecf20Sopenharmony_ci			return -EINVAL;
7468c2ecf20Sopenharmony_ci		config->mode = INDIO_BUFFER_HARDWARE;
7478c2ecf20Sopenharmony_ci		strict_scanmask = true;
7488c2ecf20Sopenharmony_ci	} else if (modes & INDIO_BUFFER_SOFTWARE) {
7498c2ecf20Sopenharmony_ci		config->mode = INDIO_BUFFER_SOFTWARE;
7508c2ecf20Sopenharmony_ci	} else {
7518c2ecf20Sopenharmony_ci		/* Can only occur on first buffer */
7528c2ecf20Sopenharmony_ci		if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
7538c2ecf20Sopenharmony_ci			dev_dbg(&indio_dev->dev, "Buffer not started: no trigger\n");
7548c2ecf20Sopenharmony_ci		return -EINVAL;
7558c2ecf20Sopenharmony_ci	}
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	/* What scan mask do we actually have? */
7588c2ecf20Sopenharmony_ci	compound_mask = bitmap_zalloc(indio_dev->masklength, GFP_KERNEL);
7598c2ecf20Sopenharmony_ci	if (compound_mask == NULL)
7608c2ecf20Sopenharmony_ci		return -ENOMEM;
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	scan_timestamp = false;
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
7658c2ecf20Sopenharmony_ci		if (buffer == remove_buffer)
7668c2ecf20Sopenharmony_ci			continue;
7678c2ecf20Sopenharmony_ci		bitmap_or(compound_mask, compound_mask, buffer->scan_mask,
7688c2ecf20Sopenharmony_ci			  indio_dev->masklength);
7698c2ecf20Sopenharmony_ci		scan_timestamp |= buffer->scan_timestamp;
7708c2ecf20Sopenharmony_ci	}
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci	if (insert_buffer) {
7738c2ecf20Sopenharmony_ci		bitmap_or(compound_mask, compound_mask,
7748c2ecf20Sopenharmony_ci			  insert_buffer->scan_mask, indio_dev->masklength);
7758c2ecf20Sopenharmony_ci		scan_timestamp |= insert_buffer->scan_timestamp;
7768c2ecf20Sopenharmony_ci	}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	if (indio_dev->available_scan_masks) {
7798c2ecf20Sopenharmony_ci		scan_mask = iio_scan_mask_match(indio_dev->available_scan_masks,
7808c2ecf20Sopenharmony_ci				    indio_dev->masklength,
7818c2ecf20Sopenharmony_ci				    compound_mask,
7828c2ecf20Sopenharmony_ci				    strict_scanmask);
7838c2ecf20Sopenharmony_ci		bitmap_free(compound_mask);
7848c2ecf20Sopenharmony_ci		if (scan_mask == NULL)
7858c2ecf20Sopenharmony_ci			return -EINVAL;
7868c2ecf20Sopenharmony_ci	} else {
7878c2ecf20Sopenharmony_ci	    scan_mask = compound_mask;
7888c2ecf20Sopenharmony_ci	}
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	config->scan_bytes = iio_compute_scan_bytes(indio_dev,
7918c2ecf20Sopenharmony_ci				    scan_mask, scan_timestamp);
7928c2ecf20Sopenharmony_ci	config->scan_mask = scan_mask;
7938c2ecf20Sopenharmony_ci	config->scan_timestamp = scan_timestamp;
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	return 0;
7968c2ecf20Sopenharmony_ci}
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci/**
7998c2ecf20Sopenharmony_ci * struct iio_demux_table - table describing demux memcpy ops
8008c2ecf20Sopenharmony_ci * @from:	index to copy from
8018c2ecf20Sopenharmony_ci * @to:		index to copy to
8028c2ecf20Sopenharmony_ci * @length:	how many bytes to copy
8038c2ecf20Sopenharmony_ci * @l:		list head used for management
8048c2ecf20Sopenharmony_ci */
8058c2ecf20Sopenharmony_cistruct iio_demux_table {
8068c2ecf20Sopenharmony_ci	unsigned from;
8078c2ecf20Sopenharmony_ci	unsigned to;
8088c2ecf20Sopenharmony_ci	unsigned length;
8098c2ecf20Sopenharmony_ci	struct list_head l;
8108c2ecf20Sopenharmony_ci};
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_cistatic void iio_buffer_demux_free(struct iio_buffer *buffer)
8138c2ecf20Sopenharmony_ci{
8148c2ecf20Sopenharmony_ci	struct iio_demux_table *p, *q;
8158c2ecf20Sopenharmony_ci	list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
8168c2ecf20Sopenharmony_ci		list_del(&p->l);
8178c2ecf20Sopenharmony_ci		kfree(p);
8188c2ecf20Sopenharmony_ci	}
8198c2ecf20Sopenharmony_ci}
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_cistatic int iio_buffer_add_demux(struct iio_buffer *buffer,
8228c2ecf20Sopenharmony_ci	struct iio_demux_table **p, unsigned int in_loc, unsigned int out_loc,
8238c2ecf20Sopenharmony_ci	unsigned int length)
8248c2ecf20Sopenharmony_ci{
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	if (*p && (*p)->from + (*p)->length == in_loc &&
8278c2ecf20Sopenharmony_ci		(*p)->to + (*p)->length == out_loc) {
8288c2ecf20Sopenharmony_ci		(*p)->length += length;
8298c2ecf20Sopenharmony_ci	} else {
8308c2ecf20Sopenharmony_ci		*p = kmalloc(sizeof(**p), GFP_KERNEL);
8318c2ecf20Sopenharmony_ci		if (*p == NULL)
8328c2ecf20Sopenharmony_ci			return -ENOMEM;
8338c2ecf20Sopenharmony_ci		(*p)->from = in_loc;
8348c2ecf20Sopenharmony_ci		(*p)->to = out_loc;
8358c2ecf20Sopenharmony_ci		(*p)->length = length;
8368c2ecf20Sopenharmony_ci		list_add_tail(&(*p)->l, &buffer->demux_list);
8378c2ecf20Sopenharmony_ci	}
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	return 0;
8408c2ecf20Sopenharmony_ci}
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_cistatic int iio_buffer_update_demux(struct iio_dev *indio_dev,
8438c2ecf20Sopenharmony_ci				   struct iio_buffer *buffer)
8448c2ecf20Sopenharmony_ci{
8458c2ecf20Sopenharmony_ci	int ret, in_ind = -1, out_ind, length;
8468c2ecf20Sopenharmony_ci	unsigned in_loc = 0, out_loc = 0;
8478c2ecf20Sopenharmony_ci	struct iio_demux_table *p = NULL;
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	/* Clear out any old demux */
8508c2ecf20Sopenharmony_ci	iio_buffer_demux_free(buffer);
8518c2ecf20Sopenharmony_ci	kfree(buffer->demux_bounce);
8528c2ecf20Sopenharmony_ci	buffer->demux_bounce = NULL;
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci	/* First work out which scan mode we will actually have */
8558c2ecf20Sopenharmony_ci	if (bitmap_equal(indio_dev->active_scan_mask,
8568c2ecf20Sopenharmony_ci			 buffer->scan_mask,
8578c2ecf20Sopenharmony_ci			 indio_dev->masklength))
8588c2ecf20Sopenharmony_ci		return 0;
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	/* Now we have the two masks, work from least sig and build up sizes */
8618c2ecf20Sopenharmony_ci	for_each_set_bit(out_ind,
8628c2ecf20Sopenharmony_ci			 buffer->scan_mask,
8638c2ecf20Sopenharmony_ci			 indio_dev->masklength) {
8648c2ecf20Sopenharmony_ci		in_ind = find_next_bit(indio_dev->active_scan_mask,
8658c2ecf20Sopenharmony_ci				       indio_dev->masklength,
8668c2ecf20Sopenharmony_ci				       in_ind + 1);
8678c2ecf20Sopenharmony_ci		while (in_ind != out_ind) {
8688c2ecf20Sopenharmony_ci			length = iio_storage_bytes_for_si(indio_dev, in_ind);
8698c2ecf20Sopenharmony_ci			/* Make sure we are aligned */
8708c2ecf20Sopenharmony_ci			in_loc = roundup(in_loc, length) + length;
8718c2ecf20Sopenharmony_ci			in_ind = find_next_bit(indio_dev->active_scan_mask,
8728c2ecf20Sopenharmony_ci					       indio_dev->masklength,
8738c2ecf20Sopenharmony_ci					       in_ind + 1);
8748c2ecf20Sopenharmony_ci		}
8758c2ecf20Sopenharmony_ci		length = iio_storage_bytes_for_si(indio_dev, in_ind);
8768c2ecf20Sopenharmony_ci		out_loc = roundup(out_loc, length);
8778c2ecf20Sopenharmony_ci		in_loc = roundup(in_loc, length);
8788c2ecf20Sopenharmony_ci		ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length);
8798c2ecf20Sopenharmony_ci		if (ret)
8808c2ecf20Sopenharmony_ci			goto error_clear_mux_table;
8818c2ecf20Sopenharmony_ci		out_loc += length;
8828c2ecf20Sopenharmony_ci		in_loc += length;
8838c2ecf20Sopenharmony_ci	}
8848c2ecf20Sopenharmony_ci	/* Relies on scan_timestamp being last */
8858c2ecf20Sopenharmony_ci	if (buffer->scan_timestamp) {
8868c2ecf20Sopenharmony_ci		length = iio_storage_bytes_for_timestamp(indio_dev);
8878c2ecf20Sopenharmony_ci		out_loc = roundup(out_loc, length);
8888c2ecf20Sopenharmony_ci		in_loc = roundup(in_loc, length);
8898c2ecf20Sopenharmony_ci		ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length);
8908c2ecf20Sopenharmony_ci		if (ret)
8918c2ecf20Sopenharmony_ci			goto error_clear_mux_table;
8928c2ecf20Sopenharmony_ci		out_loc += length;
8938c2ecf20Sopenharmony_ci		in_loc += length;
8948c2ecf20Sopenharmony_ci	}
8958c2ecf20Sopenharmony_ci	buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL);
8968c2ecf20Sopenharmony_ci	if (buffer->demux_bounce == NULL) {
8978c2ecf20Sopenharmony_ci		ret = -ENOMEM;
8988c2ecf20Sopenharmony_ci		goto error_clear_mux_table;
8998c2ecf20Sopenharmony_ci	}
9008c2ecf20Sopenharmony_ci	return 0;
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_cierror_clear_mux_table:
9038c2ecf20Sopenharmony_ci	iio_buffer_demux_free(buffer);
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	return ret;
9068c2ecf20Sopenharmony_ci}
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_cistatic int iio_update_demux(struct iio_dev *indio_dev)
9098c2ecf20Sopenharmony_ci{
9108c2ecf20Sopenharmony_ci	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
9118c2ecf20Sopenharmony_ci	struct iio_buffer *buffer;
9128c2ecf20Sopenharmony_ci	int ret;
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
9158c2ecf20Sopenharmony_ci		ret = iio_buffer_update_demux(indio_dev, buffer);
9168c2ecf20Sopenharmony_ci		if (ret < 0)
9178c2ecf20Sopenharmony_ci			goto error_clear_mux_table;
9188c2ecf20Sopenharmony_ci	}
9198c2ecf20Sopenharmony_ci	return 0;
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_cierror_clear_mux_table:
9228c2ecf20Sopenharmony_ci	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list)
9238c2ecf20Sopenharmony_ci		iio_buffer_demux_free(buffer);
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci	return ret;
9268c2ecf20Sopenharmony_ci}
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_cistatic int iio_enable_buffers(struct iio_dev *indio_dev,
9298c2ecf20Sopenharmony_ci	struct iio_device_config *config)
9308c2ecf20Sopenharmony_ci{
9318c2ecf20Sopenharmony_ci	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
9328c2ecf20Sopenharmony_ci	struct iio_buffer *buffer;
9338c2ecf20Sopenharmony_ci	int ret;
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_ci	indio_dev->active_scan_mask = config->scan_mask;
9368c2ecf20Sopenharmony_ci	indio_dev->scan_timestamp = config->scan_timestamp;
9378c2ecf20Sopenharmony_ci	indio_dev->scan_bytes = config->scan_bytes;
9388c2ecf20Sopenharmony_ci	indio_dev->currentmode = config->mode;
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci	iio_update_demux(indio_dev);
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	/* Wind up again */
9438c2ecf20Sopenharmony_ci	if (indio_dev->setup_ops->preenable) {
9448c2ecf20Sopenharmony_ci		ret = indio_dev->setup_ops->preenable(indio_dev);
9458c2ecf20Sopenharmony_ci		if (ret) {
9468c2ecf20Sopenharmony_ci			dev_dbg(&indio_dev->dev,
9478c2ecf20Sopenharmony_ci			       "Buffer not started: buffer preenable failed (%d)\n", ret);
9488c2ecf20Sopenharmony_ci			goto err_undo_config;
9498c2ecf20Sopenharmony_ci		}
9508c2ecf20Sopenharmony_ci	}
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	if (indio_dev->info->update_scan_mode) {
9538c2ecf20Sopenharmony_ci		ret = indio_dev->info
9548c2ecf20Sopenharmony_ci			->update_scan_mode(indio_dev,
9558c2ecf20Sopenharmony_ci					   indio_dev->active_scan_mask);
9568c2ecf20Sopenharmony_ci		if (ret < 0) {
9578c2ecf20Sopenharmony_ci			dev_dbg(&indio_dev->dev,
9588c2ecf20Sopenharmony_ci				"Buffer not started: update scan mode failed (%d)\n",
9598c2ecf20Sopenharmony_ci				ret);
9608c2ecf20Sopenharmony_ci			goto err_run_postdisable;
9618c2ecf20Sopenharmony_ci		}
9628c2ecf20Sopenharmony_ci	}
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci	if (indio_dev->info->hwfifo_set_watermark)
9658c2ecf20Sopenharmony_ci		indio_dev->info->hwfifo_set_watermark(indio_dev,
9668c2ecf20Sopenharmony_ci			config->watermark);
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
9698c2ecf20Sopenharmony_ci		ret = iio_buffer_enable(buffer, indio_dev);
9708c2ecf20Sopenharmony_ci		if (ret)
9718c2ecf20Sopenharmony_ci			goto err_disable_buffers;
9728c2ecf20Sopenharmony_ci	}
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
9758c2ecf20Sopenharmony_ci		ret = iio_trigger_attach_poll_func(indio_dev->trig,
9768c2ecf20Sopenharmony_ci						   indio_dev->pollfunc);
9778c2ecf20Sopenharmony_ci		if (ret)
9788c2ecf20Sopenharmony_ci			goto err_disable_buffers;
9798c2ecf20Sopenharmony_ci	}
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	if (indio_dev->setup_ops->postenable) {
9828c2ecf20Sopenharmony_ci		ret = indio_dev->setup_ops->postenable(indio_dev);
9838c2ecf20Sopenharmony_ci		if (ret) {
9848c2ecf20Sopenharmony_ci			dev_dbg(&indio_dev->dev,
9858c2ecf20Sopenharmony_ci			       "Buffer not started: postenable failed (%d)\n", ret);
9868c2ecf20Sopenharmony_ci			goto err_detach_pollfunc;
9878c2ecf20Sopenharmony_ci		}
9888c2ecf20Sopenharmony_ci	}
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	return 0;
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_cierr_detach_pollfunc:
9938c2ecf20Sopenharmony_ci	if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
9948c2ecf20Sopenharmony_ci		iio_trigger_detach_poll_func(indio_dev->trig,
9958c2ecf20Sopenharmony_ci					     indio_dev->pollfunc);
9968c2ecf20Sopenharmony_ci	}
9978c2ecf20Sopenharmony_cierr_disable_buffers:
9988c2ecf20Sopenharmony_ci	list_for_each_entry_continue_reverse(buffer, &iio_dev_opaque->buffer_list,
9998c2ecf20Sopenharmony_ci					     buffer_list)
10008c2ecf20Sopenharmony_ci		iio_buffer_disable(buffer, indio_dev);
10018c2ecf20Sopenharmony_cierr_run_postdisable:
10028c2ecf20Sopenharmony_ci	if (indio_dev->setup_ops->postdisable)
10038c2ecf20Sopenharmony_ci		indio_dev->setup_ops->postdisable(indio_dev);
10048c2ecf20Sopenharmony_cierr_undo_config:
10058c2ecf20Sopenharmony_ci	indio_dev->currentmode = INDIO_DIRECT_MODE;
10068c2ecf20Sopenharmony_ci	indio_dev->active_scan_mask = NULL;
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	return ret;
10098c2ecf20Sopenharmony_ci}
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_cistatic int iio_disable_buffers(struct iio_dev *indio_dev)
10128c2ecf20Sopenharmony_ci{
10138c2ecf20Sopenharmony_ci	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
10148c2ecf20Sopenharmony_ci	struct iio_buffer *buffer;
10158c2ecf20Sopenharmony_ci	int ret = 0;
10168c2ecf20Sopenharmony_ci	int ret2;
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci	/* Wind down existing buffers - iff there are any */
10198c2ecf20Sopenharmony_ci	if (list_empty(&iio_dev_opaque->buffer_list))
10208c2ecf20Sopenharmony_ci		return 0;
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci	/*
10238c2ecf20Sopenharmony_ci	 * If things go wrong at some step in disable we still need to continue
10248c2ecf20Sopenharmony_ci	 * to perform the other steps, otherwise we leave the device in a
10258c2ecf20Sopenharmony_ci	 * inconsistent state. We return the error code for the first error we
10268c2ecf20Sopenharmony_ci	 * encountered.
10278c2ecf20Sopenharmony_ci	 */
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	if (indio_dev->setup_ops->predisable) {
10308c2ecf20Sopenharmony_ci		ret2 = indio_dev->setup_ops->predisable(indio_dev);
10318c2ecf20Sopenharmony_ci		if (ret2 && !ret)
10328c2ecf20Sopenharmony_ci			ret = ret2;
10338c2ecf20Sopenharmony_ci	}
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_ci	if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
10368c2ecf20Sopenharmony_ci		iio_trigger_detach_poll_func(indio_dev->trig,
10378c2ecf20Sopenharmony_ci					     indio_dev->pollfunc);
10388c2ecf20Sopenharmony_ci	}
10398c2ecf20Sopenharmony_ci
10408c2ecf20Sopenharmony_ci	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
10418c2ecf20Sopenharmony_ci		ret2 = iio_buffer_disable(buffer, indio_dev);
10428c2ecf20Sopenharmony_ci		if (ret2 && !ret)
10438c2ecf20Sopenharmony_ci			ret = ret2;
10448c2ecf20Sopenharmony_ci	}
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci	if (indio_dev->setup_ops->postdisable) {
10478c2ecf20Sopenharmony_ci		ret2 = indio_dev->setup_ops->postdisable(indio_dev);
10488c2ecf20Sopenharmony_ci		if (ret2 && !ret)
10498c2ecf20Sopenharmony_ci			ret = ret2;
10508c2ecf20Sopenharmony_ci	}
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ci	iio_free_scan_mask(indio_dev, indio_dev->active_scan_mask);
10538c2ecf20Sopenharmony_ci	indio_dev->active_scan_mask = NULL;
10548c2ecf20Sopenharmony_ci	indio_dev->currentmode = INDIO_DIRECT_MODE;
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci	return ret;
10578c2ecf20Sopenharmony_ci}
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_cistatic int __iio_update_buffers(struct iio_dev *indio_dev,
10608c2ecf20Sopenharmony_ci		       struct iio_buffer *insert_buffer,
10618c2ecf20Sopenharmony_ci		       struct iio_buffer *remove_buffer)
10628c2ecf20Sopenharmony_ci{
10638c2ecf20Sopenharmony_ci	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
10648c2ecf20Sopenharmony_ci	struct iio_device_config new_config;
10658c2ecf20Sopenharmony_ci	int ret;
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci	ret = iio_verify_update(indio_dev, insert_buffer, remove_buffer,
10688c2ecf20Sopenharmony_ci		&new_config);
10698c2ecf20Sopenharmony_ci	if (ret)
10708c2ecf20Sopenharmony_ci		return ret;
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci	if (insert_buffer) {
10738c2ecf20Sopenharmony_ci		ret = iio_buffer_request_update(indio_dev, insert_buffer);
10748c2ecf20Sopenharmony_ci		if (ret)
10758c2ecf20Sopenharmony_ci			goto err_free_config;
10768c2ecf20Sopenharmony_ci	}
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci	ret = iio_disable_buffers(indio_dev);
10798c2ecf20Sopenharmony_ci	if (ret)
10808c2ecf20Sopenharmony_ci		goto err_deactivate_all;
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci	if (remove_buffer)
10838c2ecf20Sopenharmony_ci		iio_buffer_deactivate(remove_buffer);
10848c2ecf20Sopenharmony_ci	if (insert_buffer)
10858c2ecf20Sopenharmony_ci		iio_buffer_activate(indio_dev, insert_buffer);
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	/* If no buffers in list, we are done */
10888c2ecf20Sopenharmony_ci	if (list_empty(&iio_dev_opaque->buffer_list))
10898c2ecf20Sopenharmony_ci		return 0;
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	ret = iio_enable_buffers(indio_dev, &new_config);
10928c2ecf20Sopenharmony_ci	if (ret)
10938c2ecf20Sopenharmony_ci		goto err_deactivate_all;
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci	return 0;
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_cierr_deactivate_all:
10988c2ecf20Sopenharmony_ci	/*
10998c2ecf20Sopenharmony_ci	 * We've already verified that the config is valid earlier. If things go
11008c2ecf20Sopenharmony_ci	 * wrong in either enable or disable the most likely reason is an IO
11018c2ecf20Sopenharmony_ci	 * error from the device. In this case there is no good recovery
11028c2ecf20Sopenharmony_ci	 * strategy. Just make sure to disable everything and leave the device
11038c2ecf20Sopenharmony_ci	 * in a sane state.  With a bit of luck the device might come back to
11048c2ecf20Sopenharmony_ci	 * life again later and userspace can try again.
11058c2ecf20Sopenharmony_ci	 */
11068c2ecf20Sopenharmony_ci	iio_buffer_deactivate_all(indio_dev);
11078c2ecf20Sopenharmony_ci
11088c2ecf20Sopenharmony_cierr_free_config:
11098c2ecf20Sopenharmony_ci	iio_free_scan_mask(indio_dev, new_config.scan_mask);
11108c2ecf20Sopenharmony_ci	return ret;
11118c2ecf20Sopenharmony_ci}
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_ciint iio_update_buffers(struct iio_dev *indio_dev,
11148c2ecf20Sopenharmony_ci		       struct iio_buffer *insert_buffer,
11158c2ecf20Sopenharmony_ci		       struct iio_buffer *remove_buffer)
11168c2ecf20Sopenharmony_ci{
11178c2ecf20Sopenharmony_ci	int ret;
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_ci	if (insert_buffer == remove_buffer)
11208c2ecf20Sopenharmony_ci		return 0;
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci	mutex_lock(&indio_dev->info_exist_lock);
11238c2ecf20Sopenharmony_ci	mutex_lock(&indio_dev->mlock);
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci	if (insert_buffer && iio_buffer_is_active(insert_buffer))
11268c2ecf20Sopenharmony_ci		insert_buffer = NULL;
11278c2ecf20Sopenharmony_ci
11288c2ecf20Sopenharmony_ci	if (remove_buffer && !iio_buffer_is_active(remove_buffer))
11298c2ecf20Sopenharmony_ci		remove_buffer = NULL;
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	if (!insert_buffer && !remove_buffer) {
11328c2ecf20Sopenharmony_ci		ret = 0;
11338c2ecf20Sopenharmony_ci		goto out_unlock;
11348c2ecf20Sopenharmony_ci	}
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_ci	if (indio_dev->info == NULL) {
11378c2ecf20Sopenharmony_ci		ret = -ENODEV;
11388c2ecf20Sopenharmony_ci		goto out_unlock;
11398c2ecf20Sopenharmony_ci	}
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ci	ret = __iio_update_buffers(indio_dev, insert_buffer, remove_buffer);
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_ciout_unlock:
11448c2ecf20Sopenharmony_ci	mutex_unlock(&indio_dev->mlock);
11458c2ecf20Sopenharmony_ci	mutex_unlock(&indio_dev->info_exist_lock);
11468c2ecf20Sopenharmony_ci
11478c2ecf20Sopenharmony_ci	return ret;
11488c2ecf20Sopenharmony_ci}
11498c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(iio_update_buffers);
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_civoid iio_disable_all_buffers(struct iio_dev *indio_dev)
11528c2ecf20Sopenharmony_ci{
11538c2ecf20Sopenharmony_ci	iio_disable_buffers(indio_dev);
11548c2ecf20Sopenharmony_ci	iio_buffer_deactivate_all(indio_dev);
11558c2ecf20Sopenharmony_ci}
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_cistatic ssize_t iio_buffer_store_enable(struct device *dev,
11588c2ecf20Sopenharmony_ci				       struct device_attribute *attr,
11598c2ecf20Sopenharmony_ci				       const char *buf,
11608c2ecf20Sopenharmony_ci				       size_t len)
11618c2ecf20Sopenharmony_ci{
11628c2ecf20Sopenharmony_ci	int ret;
11638c2ecf20Sopenharmony_ci	bool requested_state;
11648c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
11658c2ecf20Sopenharmony_ci	struct iio_buffer *buffer = indio_dev->buffer;
11668c2ecf20Sopenharmony_ci	bool inlist;
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_ci	ret = strtobool(buf, &requested_state);
11698c2ecf20Sopenharmony_ci	if (ret < 0)
11708c2ecf20Sopenharmony_ci		return ret;
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_ci	mutex_lock(&indio_dev->mlock);
11738c2ecf20Sopenharmony_ci
11748c2ecf20Sopenharmony_ci	/* Find out if it is in the list */
11758c2ecf20Sopenharmony_ci	inlist = iio_buffer_is_active(buffer);
11768c2ecf20Sopenharmony_ci	/* Already in desired state */
11778c2ecf20Sopenharmony_ci	if (inlist == requested_state)
11788c2ecf20Sopenharmony_ci		goto done;
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ci	if (requested_state)
11818c2ecf20Sopenharmony_ci		ret = __iio_update_buffers(indio_dev, buffer, NULL);
11828c2ecf20Sopenharmony_ci	else
11838c2ecf20Sopenharmony_ci		ret = __iio_update_buffers(indio_dev, NULL, buffer);
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_cidone:
11868c2ecf20Sopenharmony_ci	mutex_unlock(&indio_dev->mlock);
11878c2ecf20Sopenharmony_ci	return (ret < 0) ? ret : len;
11888c2ecf20Sopenharmony_ci}
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_cistatic const char * const iio_scan_elements_group_name = "scan_elements";
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_cistatic ssize_t iio_buffer_show_watermark(struct device *dev,
11938c2ecf20Sopenharmony_ci					 struct device_attribute *attr,
11948c2ecf20Sopenharmony_ci					 char *buf)
11958c2ecf20Sopenharmony_ci{
11968c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
11978c2ecf20Sopenharmony_ci	struct iio_buffer *buffer = indio_dev->buffer;
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_ci	return sprintf(buf, "%u\n", buffer->watermark);
12008c2ecf20Sopenharmony_ci}
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_cistatic ssize_t iio_buffer_store_watermark(struct device *dev,
12038c2ecf20Sopenharmony_ci					  struct device_attribute *attr,
12048c2ecf20Sopenharmony_ci					  const char *buf,
12058c2ecf20Sopenharmony_ci					  size_t len)
12068c2ecf20Sopenharmony_ci{
12078c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
12088c2ecf20Sopenharmony_ci	struct iio_buffer *buffer = indio_dev->buffer;
12098c2ecf20Sopenharmony_ci	unsigned int val;
12108c2ecf20Sopenharmony_ci	int ret;
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci	ret = kstrtouint(buf, 10, &val);
12138c2ecf20Sopenharmony_ci	if (ret)
12148c2ecf20Sopenharmony_ci		return ret;
12158c2ecf20Sopenharmony_ci	if (!val)
12168c2ecf20Sopenharmony_ci		return -EINVAL;
12178c2ecf20Sopenharmony_ci
12188c2ecf20Sopenharmony_ci	mutex_lock(&indio_dev->mlock);
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci	if (val > buffer->length) {
12218c2ecf20Sopenharmony_ci		ret = -EINVAL;
12228c2ecf20Sopenharmony_ci		goto out;
12238c2ecf20Sopenharmony_ci	}
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_ci	if (iio_buffer_is_active(buffer)) {
12268c2ecf20Sopenharmony_ci		ret = -EBUSY;
12278c2ecf20Sopenharmony_ci		goto out;
12288c2ecf20Sopenharmony_ci	}
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	buffer->watermark = val;
12318c2ecf20Sopenharmony_ciout:
12328c2ecf20Sopenharmony_ci	mutex_unlock(&indio_dev->mlock);
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci	return ret ? ret : len;
12358c2ecf20Sopenharmony_ci}
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_cistatic ssize_t iio_dma_show_data_available(struct device *dev,
12388c2ecf20Sopenharmony_ci						struct device_attribute *attr,
12398c2ecf20Sopenharmony_ci						char *buf)
12408c2ecf20Sopenharmony_ci{
12418c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
12428c2ecf20Sopenharmony_ci	struct iio_buffer *buffer = indio_dev->buffer;
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci	return sprintf(buf, "%zu\n", iio_buffer_data_available(buffer));
12458c2ecf20Sopenharmony_ci}
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_cistatic DEVICE_ATTR(length, S_IRUGO | S_IWUSR, iio_buffer_read_length,
12488c2ecf20Sopenharmony_ci		   iio_buffer_write_length);
12498c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_length_ro = __ATTR(length,
12508c2ecf20Sopenharmony_ci	S_IRUGO, iio_buffer_read_length, NULL);
12518c2ecf20Sopenharmony_cistatic DEVICE_ATTR(enable, S_IRUGO | S_IWUSR,
12528c2ecf20Sopenharmony_ci		   iio_buffer_show_enable, iio_buffer_store_enable);
12538c2ecf20Sopenharmony_cistatic DEVICE_ATTR(watermark, S_IRUGO | S_IWUSR,
12548c2ecf20Sopenharmony_ci		   iio_buffer_show_watermark, iio_buffer_store_watermark);
12558c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_watermark_ro = __ATTR(watermark,
12568c2ecf20Sopenharmony_ci	S_IRUGO, iio_buffer_show_watermark, NULL);
12578c2ecf20Sopenharmony_cistatic DEVICE_ATTR(data_available, S_IRUGO,
12588c2ecf20Sopenharmony_ci		iio_dma_show_data_available, NULL);
12598c2ecf20Sopenharmony_ci
12608c2ecf20Sopenharmony_cistatic struct attribute *iio_buffer_attrs[] = {
12618c2ecf20Sopenharmony_ci	&dev_attr_length.attr,
12628c2ecf20Sopenharmony_ci	&dev_attr_enable.attr,
12638c2ecf20Sopenharmony_ci	&dev_attr_watermark.attr,
12648c2ecf20Sopenharmony_ci	&dev_attr_data_available.attr,
12658c2ecf20Sopenharmony_ci};
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_cistatic int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
12688c2ecf20Sopenharmony_ci					     struct iio_dev *indio_dev)
12698c2ecf20Sopenharmony_ci{
12708c2ecf20Sopenharmony_ci	struct iio_dev_attr *p;
12718c2ecf20Sopenharmony_ci	struct attribute **attr;
12728c2ecf20Sopenharmony_ci	int ret, i, attrn, attrcount;
12738c2ecf20Sopenharmony_ci	const struct iio_chan_spec *channels;
12748c2ecf20Sopenharmony_ci
12758c2ecf20Sopenharmony_ci	attrcount = 0;
12768c2ecf20Sopenharmony_ci	if (buffer->attrs) {
12778c2ecf20Sopenharmony_ci		while (buffer->attrs[attrcount] != NULL)
12788c2ecf20Sopenharmony_ci			attrcount++;
12798c2ecf20Sopenharmony_ci	}
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_ci	attr = kcalloc(attrcount + ARRAY_SIZE(iio_buffer_attrs) + 1,
12828c2ecf20Sopenharmony_ci		       sizeof(struct attribute *), GFP_KERNEL);
12838c2ecf20Sopenharmony_ci	if (!attr)
12848c2ecf20Sopenharmony_ci		return -ENOMEM;
12858c2ecf20Sopenharmony_ci
12868c2ecf20Sopenharmony_ci	memcpy(attr, iio_buffer_attrs, sizeof(iio_buffer_attrs));
12878c2ecf20Sopenharmony_ci	if (!buffer->access->set_length)
12888c2ecf20Sopenharmony_ci		attr[0] = &dev_attr_length_ro.attr;
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci	if (buffer->access->flags & INDIO_BUFFER_FLAG_FIXED_WATERMARK)
12918c2ecf20Sopenharmony_ci		attr[2] = &dev_attr_watermark_ro.attr;
12928c2ecf20Sopenharmony_ci
12938c2ecf20Sopenharmony_ci	if (buffer->attrs)
12948c2ecf20Sopenharmony_ci		memcpy(&attr[ARRAY_SIZE(iio_buffer_attrs)], buffer->attrs,
12958c2ecf20Sopenharmony_ci		       sizeof(struct attribute *) * attrcount);
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci	attr[attrcount + ARRAY_SIZE(iio_buffer_attrs)] = NULL;
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_ci	buffer->buffer_group.name = "buffer";
13008c2ecf20Sopenharmony_ci	buffer->buffer_group.attrs = attr;
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci	indio_dev->groups[indio_dev->groupcounter++] = &buffer->buffer_group;
13038c2ecf20Sopenharmony_ci
13048c2ecf20Sopenharmony_ci	attrcount = 0;
13058c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&buffer->scan_el_dev_attr_list);
13068c2ecf20Sopenharmony_ci	channels = indio_dev->channels;
13078c2ecf20Sopenharmony_ci	if (channels) {
13088c2ecf20Sopenharmony_ci		/* new magic */
13098c2ecf20Sopenharmony_ci		for (i = 0; i < indio_dev->num_channels; i++) {
13108c2ecf20Sopenharmony_ci			if (channels[i].scan_index < 0)
13118c2ecf20Sopenharmony_ci				continue;
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci			ret = iio_buffer_add_channel_sysfs(indio_dev, buffer,
13148c2ecf20Sopenharmony_ci							 &channels[i]);
13158c2ecf20Sopenharmony_ci			if (ret < 0)
13168c2ecf20Sopenharmony_ci				goto error_cleanup_dynamic;
13178c2ecf20Sopenharmony_ci			attrcount += ret;
13188c2ecf20Sopenharmony_ci			if (channels[i].type == IIO_TIMESTAMP)
13198c2ecf20Sopenharmony_ci				indio_dev->scan_index_timestamp =
13208c2ecf20Sopenharmony_ci					channels[i].scan_index;
13218c2ecf20Sopenharmony_ci		}
13228c2ecf20Sopenharmony_ci		if (indio_dev->masklength && buffer->scan_mask == NULL) {
13238c2ecf20Sopenharmony_ci			buffer->scan_mask = bitmap_zalloc(indio_dev->masklength,
13248c2ecf20Sopenharmony_ci							  GFP_KERNEL);
13258c2ecf20Sopenharmony_ci			if (buffer->scan_mask == NULL) {
13268c2ecf20Sopenharmony_ci				ret = -ENOMEM;
13278c2ecf20Sopenharmony_ci				goto error_cleanup_dynamic;
13288c2ecf20Sopenharmony_ci			}
13298c2ecf20Sopenharmony_ci		}
13308c2ecf20Sopenharmony_ci	}
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_ci	buffer->scan_el_group.name = iio_scan_elements_group_name;
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_ci	buffer->scan_el_group.attrs = kcalloc(attrcount + 1,
13358c2ecf20Sopenharmony_ci					      sizeof(buffer->scan_el_group.attrs[0]),
13368c2ecf20Sopenharmony_ci					      GFP_KERNEL);
13378c2ecf20Sopenharmony_ci	if (buffer->scan_el_group.attrs == NULL) {
13388c2ecf20Sopenharmony_ci		ret = -ENOMEM;
13398c2ecf20Sopenharmony_ci		goto error_free_scan_mask;
13408c2ecf20Sopenharmony_ci	}
13418c2ecf20Sopenharmony_ci	attrn = 0;
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ci	list_for_each_entry(p, &buffer->scan_el_dev_attr_list, l)
13448c2ecf20Sopenharmony_ci		buffer->scan_el_group.attrs[attrn++] = &p->dev_attr.attr;
13458c2ecf20Sopenharmony_ci	indio_dev->groups[indio_dev->groupcounter++] = &buffer->scan_el_group;
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci	return 0;
13488c2ecf20Sopenharmony_ci
13498c2ecf20Sopenharmony_cierror_free_scan_mask:
13508c2ecf20Sopenharmony_ci	bitmap_free(buffer->scan_mask);
13518c2ecf20Sopenharmony_cierror_cleanup_dynamic:
13528c2ecf20Sopenharmony_ci	iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
13538c2ecf20Sopenharmony_ci	kfree(buffer->buffer_group.attrs);
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci	return ret;
13568c2ecf20Sopenharmony_ci}
13578c2ecf20Sopenharmony_ci
13588c2ecf20Sopenharmony_ciint iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
13598c2ecf20Sopenharmony_ci{
13608c2ecf20Sopenharmony_ci	struct iio_buffer *buffer = indio_dev->buffer;
13618c2ecf20Sopenharmony_ci	const struct iio_chan_spec *channels;
13628c2ecf20Sopenharmony_ci	int i;
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_ci	channels = indio_dev->channels;
13658c2ecf20Sopenharmony_ci	if (channels) {
13668c2ecf20Sopenharmony_ci		int ml = indio_dev->masklength;
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci		for (i = 0; i < indio_dev->num_channels; i++)
13698c2ecf20Sopenharmony_ci			ml = max(ml, channels[i].scan_index + 1);
13708c2ecf20Sopenharmony_ci		indio_dev->masklength = ml;
13718c2ecf20Sopenharmony_ci	}
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ci	if (!buffer)
13748c2ecf20Sopenharmony_ci		return 0;
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	return __iio_buffer_alloc_sysfs_and_mask(buffer, indio_dev);
13778c2ecf20Sopenharmony_ci}
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_cistatic void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer)
13808c2ecf20Sopenharmony_ci{
13818c2ecf20Sopenharmony_ci	bitmap_free(buffer->scan_mask);
13828c2ecf20Sopenharmony_ci	kfree(buffer->buffer_group.attrs);
13838c2ecf20Sopenharmony_ci	kfree(buffer->scan_el_group.attrs);
13848c2ecf20Sopenharmony_ci	iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
13858c2ecf20Sopenharmony_ci}
13868c2ecf20Sopenharmony_ci
13878c2ecf20Sopenharmony_civoid iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev)
13888c2ecf20Sopenharmony_ci{
13898c2ecf20Sopenharmony_ci	struct iio_buffer *buffer = indio_dev->buffer;
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci	if (!buffer)
13928c2ecf20Sopenharmony_ci		return;
13938c2ecf20Sopenharmony_ci
13948c2ecf20Sopenharmony_ci	__iio_buffer_free_sysfs_and_mask(buffer);
13958c2ecf20Sopenharmony_ci}
13968c2ecf20Sopenharmony_ci
13978c2ecf20Sopenharmony_ci/**
13988c2ecf20Sopenharmony_ci * iio_validate_scan_mask_onehot() - Validates that exactly one channel is selected
13998c2ecf20Sopenharmony_ci * @indio_dev: the iio device
14008c2ecf20Sopenharmony_ci * @mask: scan mask to be checked
14018c2ecf20Sopenharmony_ci *
14028c2ecf20Sopenharmony_ci * Return true if exactly one bit is set in the scan mask, false otherwise. It
14038c2ecf20Sopenharmony_ci * can be used for devices where only one channel can be active for sampling at
14048c2ecf20Sopenharmony_ci * a time.
14058c2ecf20Sopenharmony_ci */
14068c2ecf20Sopenharmony_cibool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev,
14078c2ecf20Sopenharmony_ci	const unsigned long *mask)
14088c2ecf20Sopenharmony_ci{
14098c2ecf20Sopenharmony_ci	return bitmap_weight(mask, indio_dev->masklength) == 1;
14108c2ecf20Sopenharmony_ci}
14118c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(iio_validate_scan_mask_onehot);
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_cistatic const void *iio_demux(struct iio_buffer *buffer,
14148c2ecf20Sopenharmony_ci				 const void *datain)
14158c2ecf20Sopenharmony_ci{
14168c2ecf20Sopenharmony_ci	struct iio_demux_table *t;
14178c2ecf20Sopenharmony_ci
14188c2ecf20Sopenharmony_ci	if (list_empty(&buffer->demux_list))
14198c2ecf20Sopenharmony_ci		return datain;
14208c2ecf20Sopenharmony_ci	list_for_each_entry(t, &buffer->demux_list, l)
14218c2ecf20Sopenharmony_ci		memcpy(buffer->demux_bounce + t->to,
14228c2ecf20Sopenharmony_ci		       datain + t->from, t->length);
14238c2ecf20Sopenharmony_ci
14248c2ecf20Sopenharmony_ci	return buffer->demux_bounce;
14258c2ecf20Sopenharmony_ci}
14268c2ecf20Sopenharmony_ci
14278c2ecf20Sopenharmony_cistatic int iio_push_to_buffer(struct iio_buffer *buffer, const void *data)
14288c2ecf20Sopenharmony_ci{
14298c2ecf20Sopenharmony_ci	const void *dataout = iio_demux(buffer, data);
14308c2ecf20Sopenharmony_ci	int ret;
14318c2ecf20Sopenharmony_ci
14328c2ecf20Sopenharmony_ci	ret = buffer->access->store_to(buffer, dataout);
14338c2ecf20Sopenharmony_ci	if (ret)
14348c2ecf20Sopenharmony_ci		return ret;
14358c2ecf20Sopenharmony_ci
14368c2ecf20Sopenharmony_ci	/*
14378c2ecf20Sopenharmony_ci	 * We can't just test for watermark to decide if we wake the poll queue
14388c2ecf20Sopenharmony_ci	 * because read may request less samples than the watermark.
14398c2ecf20Sopenharmony_ci	 */
14408c2ecf20Sopenharmony_ci	wake_up_interruptible_poll(&buffer->pollq, EPOLLIN | EPOLLRDNORM);
14418c2ecf20Sopenharmony_ci	return 0;
14428c2ecf20Sopenharmony_ci}
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_ci/**
14458c2ecf20Sopenharmony_ci * iio_push_to_buffers() - push to a registered buffer.
14468c2ecf20Sopenharmony_ci * @indio_dev:		iio_dev structure for device.
14478c2ecf20Sopenharmony_ci * @data:		Full scan.
14488c2ecf20Sopenharmony_ci */
14498c2ecf20Sopenharmony_ciint iio_push_to_buffers(struct iio_dev *indio_dev, const void *data)
14508c2ecf20Sopenharmony_ci{
14518c2ecf20Sopenharmony_ci	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
14528c2ecf20Sopenharmony_ci	int ret;
14538c2ecf20Sopenharmony_ci	struct iio_buffer *buf;
14548c2ecf20Sopenharmony_ci
14558c2ecf20Sopenharmony_ci	list_for_each_entry(buf, &iio_dev_opaque->buffer_list, buffer_list) {
14568c2ecf20Sopenharmony_ci		ret = iio_push_to_buffer(buf, data);
14578c2ecf20Sopenharmony_ci		if (ret < 0)
14588c2ecf20Sopenharmony_ci			return ret;
14598c2ecf20Sopenharmony_ci	}
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_ci	return 0;
14628c2ecf20Sopenharmony_ci}
14638c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(iio_push_to_buffers);
14648c2ecf20Sopenharmony_ci
14658c2ecf20Sopenharmony_ci/**
14668c2ecf20Sopenharmony_ci * iio_buffer_release() - Free a buffer's resources
14678c2ecf20Sopenharmony_ci * @ref: Pointer to the kref embedded in the iio_buffer struct
14688c2ecf20Sopenharmony_ci *
14698c2ecf20Sopenharmony_ci * This function is called when the last reference to the buffer has been
14708c2ecf20Sopenharmony_ci * dropped. It will typically free all resources allocated by the buffer. Do not
14718c2ecf20Sopenharmony_ci * call this function manually, always use iio_buffer_put() when done using a
14728c2ecf20Sopenharmony_ci * buffer.
14738c2ecf20Sopenharmony_ci */
14748c2ecf20Sopenharmony_cistatic void iio_buffer_release(struct kref *ref)
14758c2ecf20Sopenharmony_ci{
14768c2ecf20Sopenharmony_ci	struct iio_buffer *buffer = container_of(ref, struct iio_buffer, ref);
14778c2ecf20Sopenharmony_ci
14788c2ecf20Sopenharmony_ci	buffer->access->release(buffer);
14798c2ecf20Sopenharmony_ci}
14808c2ecf20Sopenharmony_ci
14818c2ecf20Sopenharmony_ci/**
14828c2ecf20Sopenharmony_ci * iio_buffer_get() - Grab a reference to the buffer
14838c2ecf20Sopenharmony_ci * @buffer: The buffer to grab a reference for, may be NULL
14848c2ecf20Sopenharmony_ci *
14858c2ecf20Sopenharmony_ci * Returns the pointer to the buffer that was passed into the function.
14868c2ecf20Sopenharmony_ci */
14878c2ecf20Sopenharmony_cistruct iio_buffer *iio_buffer_get(struct iio_buffer *buffer)
14888c2ecf20Sopenharmony_ci{
14898c2ecf20Sopenharmony_ci	if (buffer)
14908c2ecf20Sopenharmony_ci		kref_get(&buffer->ref);
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_ci	return buffer;
14938c2ecf20Sopenharmony_ci}
14948c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(iio_buffer_get);
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_ci/**
14978c2ecf20Sopenharmony_ci * iio_buffer_put() - Release the reference to the buffer
14988c2ecf20Sopenharmony_ci * @buffer: The buffer to release the reference for, may be NULL
14998c2ecf20Sopenharmony_ci */
15008c2ecf20Sopenharmony_civoid iio_buffer_put(struct iio_buffer *buffer)
15018c2ecf20Sopenharmony_ci{
15028c2ecf20Sopenharmony_ci	if (buffer)
15038c2ecf20Sopenharmony_ci		kref_put(&buffer->ref, iio_buffer_release);
15048c2ecf20Sopenharmony_ci}
15058c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(iio_buffer_put);
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_ci/**
15088c2ecf20Sopenharmony_ci * iio_device_attach_buffer - Attach a buffer to a IIO device
15098c2ecf20Sopenharmony_ci * @indio_dev: The device the buffer should be attached to
15108c2ecf20Sopenharmony_ci * @buffer: The buffer to attach to the device
15118c2ecf20Sopenharmony_ci *
15128c2ecf20Sopenharmony_ci * This function attaches a buffer to a IIO device. The buffer stays attached to
15138c2ecf20Sopenharmony_ci * the device until the device is freed. The function should only be called at
15148c2ecf20Sopenharmony_ci * most once per device.
15158c2ecf20Sopenharmony_ci */
15168c2ecf20Sopenharmony_civoid iio_device_attach_buffer(struct iio_dev *indio_dev,
15178c2ecf20Sopenharmony_ci			      struct iio_buffer *buffer)
15188c2ecf20Sopenharmony_ci{
15198c2ecf20Sopenharmony_ci	indio_dev->buffer = iio_buffer_get(buffer);
15208c2ecf20Sopenharmony_ci}
15218c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(iio_device_attach_buffer);
1522