xref: /openbmc/linux/drivers/iio/industrialio-buffer.c (revision c72ea20503610a4a7ba26c769357d31602769c01)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2a980e046SJonathan Cameron /* The industrial I/O core
3a980e046SJonathan Cameron  *
4a980e046SJonathan Cameron  * Copyright (c) 2008 Jonathan Cameron
5a980e046SJonathan Cameron  *
6a980e046SJonathan Cameron  * Handling of buffer allocation / resizing.
7a980e046SJonathan Cameron  *
8a980e046SJonathan Cameron  * Things to look at here.
9a980e046SJonathan Cameron  * - Better memory allocation techniques?
10a980e046SJonathan Cameron  * - Alternative access techniques?
11a980e046SJonathan Cameron  */
12f73f7f4dSAlexandru Ardelean #include <linux/anon_inodes.h>
13a980e046SJonathan Cameron #include <linux/kernel.h>
14a980e046SJonathan Cameron #include <linux/export.h>
15a980e046SJonathan Cameron #include <linux/device.h>
16f73f7f4dSAlexandru Ardelean #include <linux/file.h>
17a980e046SJonathan Cameron #include <linux/fs.h>
18a980e046SJonathan Cameron #include <linux/cdev.h>
19a980e046SJonathan Cameron #include <linux/slab.h>
20a980e046SJonathan Cameron #include <linux/poll.h>
21174cd4b1SIngo Molnar #include <linux/sched/signal.h>
22a980e046SJonathan Cameron 
23a980e046SJonathan Cameron #include <linux/iio/iio.h>
246a8c6b26SAlexandru Ardelean #include <linux/iio/iio-opaque.h>
25a980e046SJonathan Cameron #include "iio_core.h"
26f11d59d8SLars-Peter Clausen #include "iio_core_trigger.h"
27a980e046SJonathan Cameron #include <linux/iio/sysfs.h>
28a980e046SJonathan Cameron #include <linux/iio/buffer.h>
2933dd94cbSJonathan Cameron #include <linux/iio/buffer_impl.h>
30a980e046SJonathan Cameron 
31a980e046SJonathan Cameron static const char * const iio_endian_prefix[] = {
32a980e046SJonathan Cameron 	[IIO_BE] = "be",
33a980e046SJonathan Cameron 	[IIO_LE] = "le",
34a980e046SJonathan Cameron };
35a980e046SJonathan Cameron 
36705ee2c9SLars-Peter Clausen static bool iio_buffer_is_active(struct iio_buffer *buf)
3784b36ce5SJonathan Cameron {
38705ee2c9SLars-Peter Clausen 	return !list_empty(&buf->buffer_list);
3984b36ce5SJonathan Cameron }
4084b36ce5SJonathan Cameron 
4137d34556SJosselin Costanzi static size_t iio_buffer_data_available(struct iio_buffer *buf)
42647cc7b9SLars-Peter Clausen {
43647cc7b9SLars-Peter Clausen 	return buf->access->data_available(buf);
44647cc7b9SLars-Peter Clausen }
45647cc7b9SLars-Peter Clausen 
46f4f4673bSOctavian Purdila static int iio_buffer_flush_hwfifo(struct iio_dev *indio_dev,
47f4f4673bSOctavian Purdila 				   struct iio_buffer *buf, size_t required)
4837d34556SJosselin Costanzi {
49f4f4673bSOctavian Purdila 	if (!indio_dev->info->hwfifo_flush_to_buffer)
50f4f4673bSOctavian Purdila 		return -ENODEV;
51f4f4673bSOctavian Purdila 
52f4f4673bSOctavian Purdila 	return indio_dev->info->hwfifo_flush_to_buffer(indio_dev, required);
53f4f4673bSOctavian Purdila }
54f4f4673bSOctavian Purdila 
55f4f4673bSOctavian Purdila static bool iio_buffer_ready(struct iio_dev *indio_dev, struct iio_buffer *buf,
56f4f4673bSOctavian Purdila 			     size_t to_wait, int to_flush)
57f4f4673bSOctavian Purdila {
58f4f4673bSOctavian Purdila 	size_t avail;
59f4f4673bSOctavian Purdila 	int flushed = 0;
60f4f4673bSOctavian Purdila 
6137d34556SJosselin Costanzi 	/* wakeup if the device was unregistered */
6237d34556SJosselin Costanzi 	if (!indio_dev->info)
6337d34556SJosselin Costanzi 		return true;
6437d34556SJosselin Costanzi 
6537d34556SJosselin Costanzi 	/* drain the buffer if it was disabled */
66f4f4673bSOctavian Purdila 	if (!iio_buffer_is_active(buf)) {
6737d34556SJosselin Costanzi 		to_wait = min_t(size_t, to_wait, 1);
68f4f4673bSOctavian Purdila 		to_flush = 0;
69f4f4673bSOctavian Purdila 	}
7037d34556SJosselin Costanzi 
71f4f4673bSOctavian Purdila 	avail = iio_buffer_data_available(buf);
72f4f4673bSOctavian Purdila 
73f4f4673bSOctavian Purdila 	if (avail >= to_wait) {
74f4f4673bSOctavian Purdila 		/* force a flush for non-blocking reads */
75c6f67a1fSOctavian Purdila 		if (!to_wait && avail < to_flush)
76c6f67a1fSOctavian Purdila 			iio_buffer_flush_hwfifo(indio_dev, buf,
77c6f67a1fSOctavian Purdila 						to_flush - avail);
78f4f4673bSOctavian Purdila 		return true;
79f4f4673bSOctavian Purdila 	}
80f4f4673bSOctavian Purdila 
81f4f4673bSOctavian Purdila 	if (to_flush)
82f4f4673bSOctavian Purdila 		flushed = iio_buffer_flush_hwfifo(indio_dev, buf,
83f4f4673bSOctavian Purdila 						  to_wait - avail);
84f4f4673bSOctavian Purdila 	if (flushed <= 0)
85f4f4673bSOctavian Purdila 		return false;
86f4f4673bSOctavian Purdila 
87f4f4673bSOctavian Purdila 	if (avail + flushed >= to_wait)
8837d34556SJosselin Costanzi 		return true;
8937d34556SJosselin Costanzi 
9037d34556SJosselin Costanzi 	return false;
9137d34556SJosselin Costanzi }
9237d34556SJosselin Costanzi 
93a980e046SJonathan Cameron /**
94f73f7f4dSAlexandru Ardelean  * iio_buffer_read() - chrdev read for buffer access
950123635aSCristina Opriceana  * @filp:	File structure pointer for the char device
960123635aSCristina Opriceana  * @buf:	Destination buffer for iio buffer read
970123635aSCristina Opriceana  * @n:		First n bytes to read
980123635aSCristina Opriceana  * @f_ps:	Long offset provided by the user as a seek position
99a980e046SJonathan Cameron  *
100a980e046SJonathan Cameron  * This function relies on all buffer implementations having an
101a980e046SJonathan Cameron  * iio_buffer as their first element.
1020123635aSCristina Opriceana  *
1030123635aSCristina Opriceana  * Return: negative values corresponding to error codes or ret != 0
1040123635aSCristina Opriceana  *	   for ending the reading activity
105a980e046SJonathan Cameron  **/
106f73f7f4dSAlexandru Ardelean static ssize_t iio_buffer_read(struct file *filp, char __user *buf,
107a980e046SJonathan Cameron 			       size_t n, loff_t *f_ps)
108a980e046SJonathan Cameron {
109be24dcb1SAlexandru Ardelean 	struct iio_dev_buffer_pair *ib = filp->private_data;
110be24dcb1SAlexandru Ardelean 	struct iio_buffer *rb = ib->buffer;
111be24dcb1SAlexandru Ardelean 	struct iio_dev *indio_dev = ib->indio_dev;
112fcf68f3cSBrian Norris 	DEFINE_WAIT_FUNC(wait, woken_wake_function);
11337d34556SJosselin Costanzi 	size_t datum_size;
114c6f67a1fSOctavian Purdila 	size_t to_wait;
1155dba4b14SColin Ian King 	int ret = 0;
116a980e046SJonathan Cameron 
117f18e7a06SLars-Peter Clausen 	if (!indio_dev->info)
118f18e7a06SLars-Peter Clausen 		return -ENODEV;
119f18e7a06SLars-Peter Clausen 
120f6d4033dSLars-Peter Clausen 	if (!rb || !rb->access->read)
121a980e046SJonathan Cameron 		return -EINVAL;
122ee551a10SLars-Peter Clausen 
1239eeee3b0SMihail Chindris 	if (rb->direction != IIO_BUFFER_DIRECTION_IN)
1249eeee3b0SMihail Chindris 		return -EPERM;
1259eeee3b0SMihail Chindris 
12637d34556SJosselin Costanzi 	datum_size = rb->bytes_per_datum;
127ee551a10SLars-Peter Clausen 
12837d34556SJosselin Costanzi 	/*
12937d34556SJosselin Costanzi 	 * If datum_size is 0 there will never be anything to read from the
13037d34556SJosselin Costanzi 	 * buffer, so signal end of file now.
13137d34556SJosselin Costanzi 	 */
13237d34556SJosselin Costanzi 	if (!datum_size)
13337d34556SJosselin Costanzi 		return 0;
13437d34556SJosselin Costanzi 
135c6f67a1fSOctavian Purdila 	if (filp->f_flags & O_NONBLOCK)
136c6f67a1fSOctavian Purdila 		to_wait = 0;
137c6f67a1fSOctavian Purdila 	else
138c6f67a1fSOctavian Purdila 		to_wait = min_t(size_t, n / datum_size, rb->watermark);
13937d34556SJosselin Costanzi 
140fcf68f3cSBrian Norris 	add_wait_queue(&rb->pollq, &wait);
14137d34556SJosselin Costanzi 	do {
142fcf68f3cSBrian Norris 		if (!indio_dev->info) {
143fcf68f3cSBrian Norris 			ret = -ENODEV;
144fcf68f3cSBrian Norris 			break;
145fcf68f3cSBrian Norris 		}
14637d34556SJosselin Costanzi 
147fcf68f3cSBrian Norris 		if (!iio_buffer_ready(indio_dev, rb, to_wait, n / datum_size)) {
148fcf68f3cSBrian Norris 			if (signal_pending(current)) {
149fcf68f3cSBrian Norris 				ret = -ERESTARTSYS;
150fcf68f3cSBrian Norris 				break;
151fcf68f3cSBrian Norris 			}
152fcf68f3cSBrian Norris 
153fcf68f3cSBrian Norris 			wait_woken(&wait, TASK_INTERRUPTIBLE,
154fcf68f3cSBrian Norris 				   MAX_SCHEDULE_TIMEOUT);
155fcf68f3cSBrian Norris 			continue;
156fcf68f3cSBrian Norris 		}
157ee551a10SLars-Peter Clausen 
158f6d4033dSLars-Peter Clausen 		ret = rb->access->read(rb, n, buf);
159ee551a10SLars-Peter Clausen 		if (ret == 0 && (filp->f_flags & O_NONBLOCK))
160ee551a10SLars-Peter Clausen 			ret = -EAGAIN;
161ee551a10SLars-Peter Clausen 	} while (ret == 0);
162fcf68f3cSBrian Norris 	remove_wait_queue(&rb->pollq, &wait);
163ee551a10SLars-Peter Clausen 
164ee551a10SLars-Peter Clausen 	return ret;
165a980e046SJonathan Cameron }
166a980e046SJonathan Cameron 
1679eeee3b0SMihail Chindris static size_t iio_buffer_space_available(struct iio_buffer *buf)
1689eeee3b0SMihail Chindris {
1699eeee3b0SMihail Chindris 	if (buf->access->space_available)
1709eeee3b0SMihail Chindris 		return buf->access->space_available(buf);
1719eeee3b0SMihail Chindris 
1729eeee3b0SMihail Chindris 	return SIZE_MAX;
1739eeee3b0SMihail Chindris }
1749eeee3b0SMihail Chindris 
1759eeee3b0SMihail Chindris static ssize_t iio_buffer_write(struct file *filp, const char __user *buf,
1769eeee3b0SMihail Chindris 				size_t n, loff_t *f_ps)
1779eeee3b0SMihail Chindris {
1789eeee3b0SMihail Chindris 	struct iio_dev_buffer_pair *ib = filp->private_data;
1799eeee3b0SMihail Chindris 	struct iio_buffer *rb = ib->buffer;
1809eeee3b0SMihail Chindris 	struct iio_dev *indio_dev = ib->indio_dev;
1819eeee3b0SMihail Chindris 	DEFINE_WAIT_FUNC(wait, woken_wake_function);
182eeb82b54SColin Ian King 	int ret = 0;
1839eeee3b0SMihail Chindris 	size_t written;
1849eeee3b0SMihail Chindris 
1859eeee3b0SMihail Chindris 	if (!indio_dev->info)
1869eeee3b0SMihail Chindris 		return -ENODEV;
1879eeee3b0SMihail Chindris 
1889eeee3b0SMihail Chindris 	if (!rb || !rb->access->write)
1899eeee3b0SMihail Chindris 		return -EINVAL;
1909eeee3b0SMihail Chindris 
1919eeee3b0SMihail Chindris 	if (rb->direction != IIO_BUFFER_DIRECTION_OUT)
1929eeee3b0SMihail Chindris 		return -EPERM;
1939eeee3b0SMihail Chindris 
1949eeee3b0SMihail Chindris 	written = 0;
1959eeee3b0SMihail Chindris 	add_wait_queue(&rb->pollq, &wait);
1969eeee3b0SMihail Chindris 	do {
1979eeee3b0SMihail Chindris 		if (indio_dev->info == NULL)
1989eeee3b0SMihail Chindris 			return -ENODEV;
1999eeee3b0SMihail Chindris 
2009eeee3b0SMihail Chindris 		if (!iio_buffer_space_available(rb)) {
2019eeee3b0SMihail Chindris 			if (signal_pending(current)) {
2029eeee3b0SMihail Chindris 				ret = -ERESTARTSYS;
2039eeee3b0SMihail Chindris 				break;
2049eeee3b0SMihail Chindris 			}
2059eeee3b0SMihail Chindris 
2069eeee3b0SMihail Chindris 			wait_woken(&wait, TASK_INTERRUPTIBLE,
2079eeee3b0SMihail Chindris 					MAX_SCHEDULE_TIMEOUT);
2089eeee3b0SMihail Chindris 			continue;
2099eeee3b0SMihail Chindris 		}
2109eeee3b0SMihail Chindris 
2119eeee3b0SMihail Chindris 		ret = rb->access->write(rb, n - written, buf + written);
2129eeee3b0SMihail Chindris 		if (ret == 0 && (filp->f_flags & O_NONBLOCK))
2139eeee3b0SMihail Chindris 			ret = -EAGAIN;
2149eeee3b0SMihail Chindris 
2159eeee3b0SMihail Chindris 		if (ret > 0) {
2169eeee3b0SMihail Chindris 			written += ret;
2179eeee3b0SMihail Chindris 			if (written != n && !(filp->f_flags & O_NONBLOCK))
2189eeee3b0SMihail Chindris 				continue;
2199eeee3b0SMihail Chindris 		}
2209eeee3b0SMihail Chindris 	} while (ret == 0);
2219eeee3b0SMihail Chindris 	remove_wait_queue(&rb->pollq, &wait);
2229eeee3b0SMihail Chindris 
2239eeee3b0SMihail Chindris 	return ret < 0 ? ret : n;
2249eeee3b0SMihail Chindris }
2259eeee3b0SMihail Chindris 
226a980e046SJonathan Cameron /**
227a980e046SJonathan Cameron  * iio_buffer_poll() - poll the buffer to find out if it has data
2280123635aSCristina Opriceana  * @filp:	File structure pointer for device access
2290123635aSCristina Opriceana  * @wait:	Poll table structure pointer for which the driver adds
2300123635aSCristina Opriceana  *		a wait queue
2310123635aSCristina Opriceana  *
232a9a08845SLinus Torvalds  * Return: (EPOLLIN | EPOLLRDNORM) if data is available for reading
2330123635aSCristina Opriceana  *	   or 0 for other cases
234a980e046SJonathan Cameron  */
235f73f7f4dSAlexandru Ardelean static __poll_t iio_buffer_poll(struct file *filp,
236a980e046SJonathan Cameron 				struct poll_table_struct *wait)
237a980e046SJonathan Cameron {
238be24dcb1SAlexandru Ardelean 	struct iio_dev_buffer_pair *ib = filp->private_data;
239be24dcb1SAlexandru Ardelean 	struct iio_buffer *rb = ib->buffer;
240be24dcb1SAlexandru Ardelean 	struct iio_dev *indio_dev = ib->indio_dev;
241a980e046SJonathan Cameron 
2424cd140bdSStefan Windfeldt-Prytz 	if (!indio_dev->info || rb == NULL)
2431bdc0293SCristina Opriceana 		return 0;
244f18e7a06SLars-Peter Clausen 
245a980e046SJonathan Cameron 	poll_wait(filp, &rb->pollq, wait);
2469eeee3b0SMihail Chindris 
2479eeee3b0SMihail Chindris 	switch (rb->direction) {
2489eeee3b0SMihail Chindris 	case IIO_BUFFER_DIRECTION_IN:
249f4f4673bSOctavian Purdila 		if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0))
250a9a08845SLinus Torvalds 			return EPOLLIN | EPOLLRDNORM;
2519eeee3b0SMihail Chindris 		break;
2529eeee3b0SMihail Chindris 	case IIO_BUFFER_DIRECTION_OUT:
2539eeee3b0SMihail Chindris 		if (iio_buffer_space_available(rb))
2549eeee3b0SMihail Chindris 			return EPOLLOUT | EPOLLWRNORM;
2559eeee3b0SMihail Chindris 		break;
2569eeee3b0SMihail Chindris 	}
2579eeee3b0SMihail Chindris 
258a980e046SJonathan Cameron 	return 0;
259a980e046SJonathan Cameron }
260a980e046SJonathan Cameron 
261f73f7f4dSAlexandru Ardelean ssize_t iio_buffer_read_wrapper(struct file *filp, char __user *buf,
262f73f7f4dSAlexandru Ardelean 				size_t n, loff_t *f_ps)
263f73f7f4dSAlexandru Ardelean {
264f73f7f4dSAlexandru Ardelean 	struct iio_dev_buffer_pair *ib = filp->private_data;
265f73f7f4dSAlexandru Ardelean 	struct iio_buffer *rb = ib->buffer;
266f73f7f4dSAlexandru Ardelean 
267f73f7f4dSAlexandru Ardelean 	/* check if buffer was opened through new API */
268f73f7f4dSAlexandru Ardelean 	if (test_bit(IIO_BUSY_BIT_POS, &rb->flags))
269f73f7f4dSAlexandru Ardelean 		return -EBUSY;
270f73f7f4dSAlexandru Ardelean 
271f73f7f4dSAlexandru Ardelean 	return iio_buffer_read(filp, buf, n, f_ps);
272f73f7f4dSAlexandru Ardelean }
273f73f7f4dSAlexandru Ardelean 
2749eeee3b0SMihail Chindris ssize_t iio_buffer_write_wrapper(struct file *filp, const char __user *buf,
2759eeee3b0SMihail Chindris 				 size_t n, loff_t *f_ps)
2769eeee3b0SMihail Chindris {
2779eeee3b0SMihail Chindris 	struct iio_dev_buffer_pair *ib = filp->private_data;
2789eeee3b0SMihail Chindris 	struct iio_buffer *rb = ib->buffer;
2799eeee3b0SMihail Chindris 
2809eeee3b0SMihail Chindris 	/* check if buffer was opened through new API */
2819eeee3b0SMihail Chindris 	if (test_bit(IIO_BUSY_BIT_POS, &rb->flags))
2829eeee3b0SMihail Chindris 		return -EBUSY;
2839eeee3b0SMihail Chindris 
2849eeee3b0SMihail Chindris 	return iio_buffer_write(filp, buf, n, f_ps);
2859eeee3b0SMihail Chindris }
2869eeee3b0SMihail Chindris 
287f73f7f4dSAlexandru Ardelean __poll_t iio_buffer_poll_wrapper(struct file *filp,
288f73f7f4dSAlexandru Ardelean 				 struct poll_table_struct *wait)
289f73f7f4dSAlexandru Ardelean {
290f73f7f4dSAlexandru Ardelean 	struct iio_dev_buffer_pair *ib = filp->private_data;
291f73f7f4dSAlexandru Ardelean 	struct iio_buffer *rb = ib->buffer;
292f73f7f4dSAlexandru Ardelean 
293f73f7f4dSAlexandru Ardelean 	/* check if buffer was opened through new API */
294f73f7f4dSAlexandru Ardelean 	if (test_bit(IIO_BUSY_BIT_POS, &rb->flags))
295f73f7f4dSAlexandru Ardelean 		return 0;
296f73f7f4dSAlexandru Ardelean 
297f73f7f4dSAlexandru Ardelean 	return iio_buffer_poll(filp, wait);
298f73f7f4dSAlexandru Ardelean }
299f73f7f4dSAlexandru Ardelean 
300d2f0a48fSLars-Peter Clausen /**
301d2f0a48fSLars-Peter Clausen  * iio_buffer_wakeup_poll - Wakes up the buffer waitqueue
302d2f0a48fSLars-Peter Clausen  * @indio_dev: The IIO device
303d2f0a48fSLars-Peter Clausen  *
304d2f0a48fSLars-Peter Clausen  * Wakes up the event waitqueue used for poll(). Should usually
305d2f0a48fSLars-Peter Clausen  * be called when the device is unregistered.
306d2f0a48fSLars-Peter Clausen  */
307d2f0a48fSLars-Peter Clausen void iio_buffer_wakeup_poll(struct iio_dev *indio_dev)
308d2f0a48fSLars-Peter Clausen {
309ee708e6bSAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
310ee708e6bSAlexandru Ardelean 	struct iio_buffer *buffer;
311ee708e6bSAlexandru Ardelean 	unsigned int i;
312ff3f7e04SAlexandru Ardelean 
313ee708e6bSAlexandru Ardelean 	for (i = 0; i < iio_dev_opaque->attached_buffers_cnt; i++) {
314ee708e6bSAlexandru Ardelean 		buffer = iio_dev_opaque->attached_buffers[i];
315ff3f7e04SAlexandru Ardelean 		wake_up(&buffer->pollq);
316d2f0a48fSLars-Peter Clausen 	}
317ee708e6bSAlexandru Ardelean }
318d2f0a48fSLars-Peter Clausen 
3199eeee3b0SMihail Chindris int iio_pop_from_buffer(struct iio_buffer *buffer, void *data)
3209eeee3b0SMihail Chindris {
3219eeee3b0SMihail Chindris 	if (!buffer || !buffer->access || !buffer->access->remove_from)
3229eeee3b0SMihail Chindris 		return -EINVAL;
3239eeee3b0SMihail Chindris 
3249eeee3b0SMihail Chindris 	return buffer->access->remove_from(buffer, data);
3259eeee3b0SMihail Chindris }
3269eeee3b0SMihail Chindris EXPORT_SYMBOL_GPL(iio_pop_from_buffer);
3279eeee3b0SMihail Chindris 
328a980e046SJonathan Cameron void iio_buffer_init(struct iio_buffer *buffer)
329a980e046SJonathan Cameron {
330a980e046SJonathan Cameron 	INIT_LIST_HEAD(&buffer->demux_list);
331705ee2c9SLars-Peter Clausen 	INIT_LIST_HEAD(&buffer->buffer_list);
332a980e046SJonathan Cameron 	init_waitqueue_head(&buffer->pollq);
3339e69c935SLars-Peter Clausen 	kref_init(&buffer->ref);
3344a605357SLars-Peter Clausen 	if (!buffer->watermark)
33537d34556SJosselin Costanzi 		buffer->watermark = 1;
336a980e046SJonathan Cameron }
337a980e046SJonathan Cameron EXPORT_SYMBOL(iio_buffer_init);
338a980e046SJonathan Cameron 
339218bc53dSAlexandru Ardelean void iio_device_detach_buffers(struct iio_dev *indio_dev)
340ee708e6bSAlexandru Ardelean {
341ee708e6bSAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
342ee708e6bSAlexandru Ardelean 	struct iio_buffer *buffer;
343ee708e6bSAlexandru Ardelean 	unsigned int i;
344ee708e6bSAlexandru Ardelean 
345ee708e6bSAlexandru Ardelean 	for (i = 0; i < iio_dev_opaque->attached_buffers_cnt; i++) {
346ee708e6bSAlexandru Ardelean 		buffer = iio_dev_opaque->attached_buffers[i];
347ee708e6bSAlexandru Ardelean 		iio_buffer_put(buffer);
348ee708e6bSAlexandru Ardelean 	}
349218bc53dSAlexandru Ardelean 
350218bc53dSAlexandru Ardelean 	kfree(iio_dev_opaque->attached_buffers);
351ee708e6bSAlexandru Ardelean }
352ee708e6bSAlexandru Ardelean 
353a980e046SJonathan Cameron static ssize_t iio_show_scan_index(struct device *dev,
354a980e046SJonathan Cameron 				   struct device_attribute *attr,
355a980e046SJonathan Cameron 				   char *buf)
356a980e046SJonathan Cameron {
35783ca56b6SLars-Peter Clausen 	return sysfs_emit(buf, "%u\n", to_iio_dev_attr(attr)->c->scan_index);
358a980e046SJonathan Cameron }
359a980e046SJonathan Cameron 
360a980e046SJonathan Cameron static ssize_t iio_show_fixed_type(struct device *dev,
361a980e046SJonathan Cameron 				   struct device_attribute *attr,
362a980e046SJonathan Cameron 				   char *buf)
363a980e046SJonathan Cameron {
364a980e046SJonathan Cameron 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
365a980e046SJonathan Cameron 	u8 type = this_attr->c->scan_type.endianness;
366a980e046SJonathan Cameron 
367a980e046SJonathan Cameron 	if (type == IIO_CPU) {
368a980e046SJonathan Cameron #ifdef __LITTLE_ENDIAN
369a980e046SJonathan Cameron 		type = IIO_LE;
370a980e046SJonathan Cameron #else
371a980e046SJonathan Cameron 		type = IIO_BE;
372a980e046SJonathan Cameron #endif
373a980e046SJonathan Cameron 	}
3740ee8546aSSrinivas Pandruvada 	if (this_attr->c->scan_type.repeat > 1)
37583ca56b6SLars-Peter Clausen 		return sysfs_emit(buf, "%s:%c%d/%dX%d>>%u\n",
3760ee8546aSSrinivas Pandruvada 		       iio_endian_prefix[type],
3770ee8546aSSrinivas Pandruvada 		       this_attr->c->scan_type.sign,
3780ee8546aSSrinivas Pandruvada 		       this_attr->c->scan_type.realbits,
3790ee8546aSSrinivas Pandruvada 		       this_attr->c->scan_type.storagebits,
3800ee8546aSSrinivas Pandruvada 		       this_attr->c->scan_type.repeat,
3810ee8546aSSrinivas Pandruvada 		       this_attr->c->scan_type.shift);
3820ee8546aSSrinivas Pandruvada 	else
38383ca56b6SLars-Peter Clausen 		return sysfs_emit(buf, "%s:%c%d/%d>>%u\n",
384a980e046SJonathan Cameron 		       iio_endian_prefix[type],
385a980e046SJonathan Cameron 		       this_attr->c->scan_type.sign,
386a980e046SJonathan Cameron 		       this_attr->c->scan_type.realbits,
387a980e046SJonathan Cameron 		       this_attr->c->scan_type.storagebits,
388a980e046SJonathan Cameron 		       this_attr->c->scan_type.shift);
389a980e046SJonathan Cameron }
390a980e046SJonathan Cameron 
391a980e046SJonathan Cameron static ssize_t iio_scan_el_show(struct device *dev,
392a980e046SJonathan Cameron 				struct device_attribute *attr,
393a980e046SJonathan Cameron 				char *buf)
394a980e046SJonathan Cameron {
395a980e046SJonathan Cameron 	int ret;
39615097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
397a980e046SJonathan Cameron 
3982076a20fSAlec Berg 	/* Ensure ret is 0 or 1. */
3992076a20fSAlec Berg 	ret = !!test_bit(to_iio_dev_attr(attr)->address,
400ff3f7e04SAlexandru Ardelean 		       buffer->scan_mask);
401a980e046SJonathan Cameron 
40283ca56b6SLars-Peter Clausen 	return sysfs_emit(buf, "%d\n", ret);
403a980e046SJonathan Cameron }
404a980e046SJonathan Cameron 
405217a5cf0SLars-Peter Clausen /* Note NULL used as error indicator as it doesn't make sense. */
406217a5cf0SLars-Peter Clausen static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks,
407217a5cf0SLars-Peter Clausen 					  unsigned int masklength,
4081e1ec286SLars-Peter Clausen 					  const unsigned long *mask,
4091e1ec286SLars-Peter Clausen 					  bool strict)
410217a5cf0SLars-Peter Clausen {
411217a5cf0SLars-Peter Clausen 	if (bitmap_empty(mask, masklength))
412217a5cf0SLars-Peter Clausen 		return NULL;
413217a5cf0SLars-Peter Clausen 	while (*av_masks) {
4141e1ec286SLars-Peter Clausen 		if (strict) {
4151e1ec286SLars-Peter Clausen 			if (bitmap_equal(mask, av_masks, masklength))
4161e1ec286SLars-Peter Clausen 				return av_masks;
4171e1ec286SLars-Peter Clausen 		} else {
418217a5cf0SLars-Peter Clausen 			if (bitmap_subset(mask, av_masks, masklength))
419217a5cf0SLars-Peter Clausen 				return av_masks;
4201e1ec286SLars-Peter Clausen 		}
421217a5cf0SLars-Peter Clausen 		av_masks += BITS_TO_LONGS(masklength);
422217a5cf0SLars-Peter Clausen 	}
423217a5cf0SLars-Peter Clausen 	return NULL;
424217a5cf0SLars-Peter Clausen }
425217a5cf0SLars-Peter Clausen 
426217a5cf0SLars-Peter Clausen static bool iio_validate_scan_mask(struct iio_dev *indio_dev,
427217a5cf0SLars-Peter Clausen 	const unsigned long *mask)
428217a5cf0SLars-Peter Clausen {
429217a5cf0SLars-Peter Clausen 	if (!indio_dev->setup_ops->validate_scan_mask)
430217a5cf0SLars-Peter Clausen 		return true;
431217a5cf0SLars-Peter Clausen 
432217a5cf0SLars-Peter Clausen 	return indio_dev->setup_ops->validate_scan_mask(indio_dev, mask);
433217a5cf0SLars-Peter Clausen }
434217a5cf0SLars-Peter Clausen 
435217a5cf0SLars-Peter Clausen /**
436217a5cf0SLars-Peter Clausen  * iio_scan_mask_set() - set particular bit in the scan mask
437217a5cf0SLars-Peter Clausen  * @indio_dev: the iio device
438217a5cf0SLars-Peter Clausen  * @buffer: the buffer whose scan mask we are interested in
439217a5cf0SLars-Peter Clausen  * @bit: the bit to be set.
440217a5cf0SLars-Peter Clausen  *
441217a5cf0SLars-Peter Clausen  * Note that at this point we have no way of knowing what other
442217a5cf0SLars-Peter Clausen  * buffers might request, hence this code only verifies that the
443217a5cf0SLars-Peter Clausen  * individual buffers request is plausible.
444217a5cf0SLars-Peter Clausen  */
445217a5cf0SLars-Peter Clausen static int iio_scan_mask_set(struct iio_dev *indio_dev,
446217a5cf0SLars-Peter Clausen 		      struct iio_buffer *buffer, int bit)
447217a5cf0SLars-Peter Clausen {
448217a5cf0SLars-Peter Clausen 	const unsigned long *mask;
449217a5cf0SLars-Peter Clausen 	unsigned long *trialmask;
450217a5cf0SLars-Peter Clausen 
451d21fed06SChristophe JAILLET 	if (!indio_dev->masklength) {
452d21fed06SChristophe JAILLET 		WARN(1, "Trying to set scanmask prior to registering buffer\n");
453d21fed06SChristophe JAILLET 		return -EINVAL;
454d21fed06SChristophe JAILLET 	}
455d21fed06SChristophe JAILLET 
45645851650SChristophe JAILLET 	trialmask = bitmap_alloc(indio_dev->masklength, GFP_KERNEL);
45745851650SChristophe JAILLET 	if (!trialmask)
458217a5cf0SLars-Peter Clausen 		return -ENOMEM;
459217a5cf0SLars-Peter Clausen 	bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength);
460217a5cf0SLars-Peter Clausen 	set_bit(bit, trialmask);
461217a5cf0SLars-Peter Clausen 
462217a5cf0SLars-Peter Clausen 	if (!iio_validate_scan_mask(indio_dev, trialmask))
463217a5cf0SLars-Peter Clausen 		goto err_invalid_mask;
464217a5cf0SLars-Peter Clausen 
465217a5cf0SLars-Peter Clausen 	if (indio_dev->available_scan_masks) {
466217a5cf0SLars-Peter Clausen 		mask = iio_scan_mask_match(indio_dev->available_scan_masks,
467217a5cf0SLars-Peter Clausen 					   indio_dev->masklength,
4681e1ec286SLars-Peter Clausen 					   trialmask, false);
469217a5cf0SLars-Peter Clausen 		if (!mask)
470217a5cf0SLars-Peter Clausen 			goto err_invalid_mask;
471217a5cf0SLars-Peter Clausen 	}
472217a5cf0SLars-Peter Clausen 	bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength);
473217a5cf0SLars-Peter Clausen 
4743862828aSAndy Shevchenko 	bitmap_free(trialmask);
475217a5cf0SLars-Peter Clausen 
476217a5cf0SLars-Peter Clausen 	return 0;
477217a5cf0SLars-Peter Clausen 
478217a5cf0SLars-Peter Clausen err_invalid_mask:
4793862828aSAndy Shevchenko 	bitmap_free(trialmask);
480217a5cf0SLars-Peter Clausen 	return -EINVAL;
481217a5cf0SLars-Peter Clausen }
482217a5cf0SLars-Peter Clausen 
483a980e046SJonathan Cameron static int iio_scan_mask_clear(struct iio_buffer *buffer, int bit)
484a980e046SJonathan Cameron {
485a980e046SJonathan Cameron 	clear_bit(bit, buffer->scan_mask);
486a980e046SJonathan Cameron 	return 0;
487a980e046SJonathan Cameron }
488a980e046SJonathan Cameron 
489c2bf8d5fSJonathan Cameron static int iio_scan_mask_query(struct iio_dev *indio_dev,
490c2bf8d5fSJonathan Cameron 			       struct iio_buffer *buffer, int bit)
491c2bf8d5fSJonathan Cameron {
492c2bf8d5fSJonathan Cameron 	if (bit > indio_dev->masklength)
493c2bf8d5fSJonathan Cameron 		return -EINVAL;
494c2bf8d5fSJonathan Cameron 
495c2bf8d5fSJonathan Cameron 	if (!buffer->scan_mask)
496c2bf8d5fSJonathan Cameron 		return 0;
497c2bf8d5fSJonathan Cameron 
498c2bf8d5fSJonathan Cameron 	/* Ensure return value is 0 or 1. */
499c2bf8d5fSJonathan Cameron 	return !!test_bit(bit, buffer->scan_mask);
500c2bf8d5fSJonathan Cameron };
501c2bf8d5fSJonathan Cameron 
502a980e046SJonathan Cameron static ssize_t iio_scan_el_store(struct device *dev,
503a980e046SJonathan Cameron 				 struct device_attribute *attr,
504a980e046SJonathan Cameron 				 const char *buf,
505a980e046SJonathan Cameron 				 size_t len)
506a980e046SJonathan Cameron {
507a980e046SJonathan Cameron 	int ret;
508a980e046SJonathan Cameron 	bool state;
509e53f5ac5SLars-Peter Clausen 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
510a980e046SJonathan Cameron 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
51115097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = this_attr->buffer;
512a980e046SJonathan Cameron 
513a980e046SJonathan Cameron 	ret = strtobool(buf, &state);
514a980e046SJonathan Cameron 	if (ret < 0)
515a980e046SJonathan Cameron 		return ret;
516a980e046SJonathan Cameron 	mutex_lock(&indio_dev->mlock);
517ff3f7e04SAlexandru Ardelean 	if (iio_buffer_is_active(buffer)) {
518a980e046SJonathan Cameron 		ret = -EBUSY;
519a980e046SJonathan Cameron 		goto error_ret;
520a980e046SJonathan Cameron 	}
521a980e046SJonathan Cameron 	ret = iio_scan_mask_query(indio_dev, buffer, this_attr->address);
522a980e046SJonathan Cameron 	if (ret < 0)
523a980e046SJonathan Cameron 		goto error_ret;
524a980e046SJonathan Cameron 	if (!state && ret) {
525a980e046SJonathan Cameron 		ret = iio_scan_mask_clear(buffer, this_attr->address);
526a980e046SJonathan Cameron 		if (ret)
527a980e046SJonathan Cameron 			goto error_ret;
528a980e046SJonathan Cameron 	} else if (state && !ret) {
529a980e046SJonathan Cameron 		ret = iio_scan_mask_set(indio_dev, buffer, this_attr->address);
530a980e046SJonathan Cameron 		if (ret)
531a980e046SJonathan Cameron 			goto error_ret;
532a980e046SJonathan Cameron 	}
533a980e046SJonathan Cameron 
534a980e046SJonathan Cameron error_ret:
535a980e046SJonathan Cameron 	mutex_unlock(&indio_dev->mlock);
536a980e046SJonathan Cameron 
537a980e046SJonathan Cameron 	return ret < 0 ? ret : len;
538a980e046SJonathan Cameron 
539a980e046SJonathan Cameron }
540a980e046SJonathan Cameron 
541a980e046SJonathan Cameron static ssize_t iio_scan_el_ts_show(struct device *dev,
542a980e046SJonathan Cameron 				   struct device_attribute *attr,
543a980e046SJonathan Cameron 				   char *buf)
544a980e046SJonathan Cameron {
54515097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
546ff3f7e04SAlexandru Ardelean 
54783ca56b6SLars-Peter Clausen 	return sysfs_emit(buf, "%d\n", buffer->scan_timestamp);
548a980e046SJonathan Cameron }
549a980e046SJonathan Cameron 
550a980e046SJonathan Cameron static ssize_t iio_scan_el_ts_store(struct device *dev,
551a980e046SJonathan Cameron 				    struct device_attribute *attr,
552a980e046SJonathan Cameron 				    const char *buf,
553a980e046SJonathan Cameron 				    size_t len)
554a980e046SJonathan Cameron {
555a980e046SJonathan Cameron 	int ret;
556e53f5ac5SLars-Peter Clausen 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
55715097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
558a980e046SJonathan Cameron 	bool state;
559a980e046SJonathan Cameron 
560a980e046SJonathan Cameron 	ret = strtobool(buf, &state);
561a980e046SJonathan Cameron 	if (ret < 0)
562a980e046SJonathan Cameron 		return ret;
563a980e046SJonathan Cameron 
564a980e046SJonathan Cameron 	mutex_lock(&indio_dev->mlock);
565ff3f7e04SAlexandru Ardelean 	if (iio_buffer_is_active(buffer)) {
566a980e046SJonathan Cameron 		ret = -EBUSY;
567a980e046SJonathan Cameron 		goto error_ret;
568a980e046SJonathan Cameron 	}
569ff3f7e04SAlexandru Ardelean 	buffer->scan_timestamp = state;
570a980e046SJonathan Cameron error_ret:
571a980e046SJonathan Cameron 	mutex_unlock(&indio_dev->mlock);
572a980e046SJonathan Cameron 
573a980e046SJonathan Cameron 	return ret ? ret : len;
574a980e046SJonathan Cameron }
575a980e046SJonathan Cameron 
576a980e046SJonathan Cameron static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
577ff3f7e04SAlexandru Ardelean 					struct iio_buffer *buffer,
578a980e046SJonathan Cameron 					const struct iio_chan_spec *chan)
579a980e046SJonathan Cameron {
580a980e046SJonathan Cameron 	int ret, attrcount = 0;
581a980e046SJonathan Cameron 
582a980e046SJonathan Cameron 	ret = __iio_add_chan_devattr("index",
583a980e046SJonathan Cameron 				     chan,
584a980e046SJonathan Cameron 				     &iio_show_scan_index,
585a980e046SJonathan Cameron 				     NULL,
586a980e046SJonathan Cameron 				     0,
5873704432fSJonathan Cameron 				     IIO_SEPARATE,
588a980e046SJonathan Cameron 				     &indio_dev->dev,
5893e3d11b2SAlexandru Ardelean 				     buffer,
59015097c7aSAlexandru Ardelean 				     &buffer->buffer_attr_list);
591a980e046SJonathan Cameron 	if (ret)
59292825ff9SHartmut Knaack 		return ret;
593a980e046SJonathan Cameron 	attrcount++;
594a980e046SJonathan Cameron 	ret = __iio_add_chan_devattr("type",
595a980e046SJonathan Cameron 				     chan,
596a980e046SJonathan Cameron 				     &iio_show_fixed_type,
597a980e046SJonathan Cameron 				     NULL,
598a980e046SJonathan Cameron 				     0,
599a980e046SJonathan Cameron 				     0,
600a980e046SJonathan Cameron 				     &indio_dev->dev,
6013e3d11b2SAlexandru Ardelean 				     buffer,
60215097c7aSAlexandru Ardelean 				     &buffer->buffer_attr_list);
603a980e046SJonathan Cameron 	if (ret)
60492825ff9SHartmut Knaack 		return ret;
605a980e046SJonathan Cameron 	attrcount++;
606a980e046SJonathan Cameron 	if (chan->type != IIO_TIMESTAMP)
607a980e046SJonathan Cameron 		ret = __iio_add_chan_devattr("en",
608a980e046SJonathan Cameron 					     chan,
609a980e046SJonathan Cameron 					     &iio_scan_el_show,
610a980e046SJonathan Cameron 					     &iio_scan_el_store,
611a980e046SJonathan Cameron 					     chan->scan_index,
612a980e046SJonathan Cameron 					     0,
613a980e046SJonathan Cameron 					     &indio_dev->dev,
6143e3d11b2SAlexandru Ardelean 					     buffer,
61515097c7aSAlexandru Ardelean 					     &buffer->buffer_attr_list);
616a980e046SJonathan Cameron 	else
617a980e046SJonathan Cameron 		ret = __iio_add_chan_devattr("en",
618a980e046SJonathan Cameron 					     chan,
619a980e046SJonathan Cameron 					     &iio_scan_el_ts_show,
620a980e046SJonathan Cameron 					     &iio_scan_el_ts_store,
621a980e046SJonathan Cameron 					     chan->scan_index,
622a980e046SJonathan Cameron 					     0,
623a980e046SJonathan Cameron 					     &indio_dev->dev,
6243e3d11b2SAlexandru Ardelean 					     buffer,
62515097c7aSAlexandru Ardelean 					     &buffer->buffer_attr_list);
6269572588cSPeter Meerwald 	if (ret)
62792825ff9SHartmut Knaack 		return ret;
628a980e046SJonathan Cameron 	attrcount++;
629a980e046SJonathan Cameron 	ret = attrcount;
630a980e046SJonathan Cameron 	return ret;
631a980e046SJonathan Cameron }
632a980e046SJonathan Cameron 
63308e7e0adSLars-Peter Clausen static ssize_t iio_buffer_read_length(struct device *dev,
634a980e046SJonathan Cameron 				      struct device_attribute *attr,
635a980e046SJonathan Cameron 				      char *buf)
636a980e046SJonathan Cameron {
63715097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
638a980e046SJonathan Cameron 
63983ca56b6SLars-Peter Clausen 	return sysfs_emit(buf, "%d\n", buffer->length);
640a980e046SJonathan Cameron }
641a980e046SJonathan Cameron 
64208e7e0adSLars-Peter Clausen static ssize_t iio_buffer_write_length(struct device *dev,
643a980e046SJonathan Cameron 				       struct device_attribute *attr,
64408e7e0adSLars-Peter Clausen 				       const char *buf, size_t len)
645a980e046SJonathan Cameron {
646e53f5ac5SLars-Peter Clausen 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
64715097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
648948ad205SLars-Peter Clausen 	unsigned int val;
649948ad205SLars-Peter Clausen 	int ret;
650a980e046SJonathan Cameron 
651948ad205SLars-Peter Clausen 	ret = kstrtouint(buf, 10, &val);
652a980e046SJonathan Cameron 	if (ret)
653a980e046SJonathan Cameron 		return ret;
654a980e046SJonathan Cameron 
65537495660SLars-Peter Clausen 	if (val == buffer->length)
656a980e046SJonathan Cameron 		return len;
657a980e046SJonathan Cameron 
658a980e046SJonathan Cameron 	mutex_lock(&indio_dev->mlock);
659ff3f7e04SAlexandru Ardelean 	if (iio_buffer_is_active(buffer)) {
660a980e046SJonathan Cameron 		ret = -EBUSY;
661a980e046SJonathan Cameron 	} else {
662a980e046SJonathan Cameron 		buffer->access->set_length(buffer, val);
663a980e046SJonathan Cameron 		ret = 0;
664a980e046SJonathan Cameron 	}
66537d34556SJosselin Costanzi 	if (ret)
66637d34556SJosselin Costanzi 		goto out;
66737d34556SJosselin Costanzi 	if (buffer->length && buffer->length < buffer->watermark)
66837d34556SJosselin Costanzi 		buffer->watermark = buffer->length;
66937d34556SJosselin Costanzi out:
670a980e046SJonathan Cameron 	mutex_unlock(&indio_dev->mlock);
671a980e046SJonathan Cameron 
672a980e046SJonathan Cameron 	return ret ? ret : len;
673a980e046SJonathan Cameron }
674a980e046SJonathan Cameron 
67508e7e0adSLars-Peter Clausen static ssize_t iio_buffer_show_enable(struct device *dev,
676a980e046SJonathan Cameron 				      struct device_attribute *attr,
677a980e046SJonathan Cameron 				      char *buf)
678a980e046SJonathan Cameron {
67915097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
680ff3f7e04SAlexandru Ardelean 
68183ca56b6SLars-Peter Clausen 	return sysfs_emit(buf, "%d\n", iio_buffer_is_active(buffer));
682a980e046SJonathan Cameron }
683a980e046SJonathan Cameron 
684182b4905SLars-Peter Clausen static unsigned int iio_storage_bytes_for_si(struct iio_dev *indio_dev,
685182b4905SLars-Peter Clausen 					     unsigned int scan_index)
686182b4905SLars-Peter Clausen {
687182b4905SLars-Peter Clausen 	const struct iio_chan_spec *ch;
688182b4905SLars-Peter Clausen 	unsigned int bytes;
689182b4905SLars-Peter Clausen 
690182b4905SLars-Peter Clausen 	ch = iio_find_channel_from_si(indio_dev, scan_index);
691182b4905SLars-Peter Clausen 	bytes = ch->scan_type.storagebits / 8;
692182b4905SLars-Peter Clausen 	if (ch->scan_type.repeat > 1)
693182b4905SLars-Peter Clausen 		bytes *= ch->scan_type.repeat;
694182b4905SLars-Peter Clausen 	return bytes;
695182b4905SLars-Peter Clausen }
696182b4905SLars-Peter Clausen 
697182b4905SLars-Peter Clausen static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev)
698182b4905SLars-Peter Clausen {
69962f4f36cSJonathan Cameron 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
70062f4f36cSJonathan Cameron 
701182b4905SLars-Peter Clausen 	return iio_storage_bytes_for_si(indio_dev,
70262f4f36cSJonathan Cameron 					iio_dev_opaque->scan_index_timestamp);
703182b4905SLars-Peter Clausen }
704182b4905SLars-Peter Clausen 
705183f4173SPeter Meerwald static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
706183f4173SPeter Meerwald 				const unsigned long *mask, bool timestamp)
707a980e046SJonathan Cameron {
708a980e046SJonathan Cameron 	unsigned bytes = 0;
709883f6165SLars Möllendorf 	int length, i, largest = 0;
710a980e046SJonathan Cameron 
711a980e046SJonathan Cameron 	/* How much space will the demuxed element take? */
712a980e046SJonathan Cameron 	for_each_set_bit(i, mask,
713a980e046SJonathan Cameron 			 indio_dev->masklength) {
714182b4905SLars-Peter Clausen 		length = iio_storage_bytes_for_si(indio_dev, i);
715a980e046SJonathan Cameron 		bytes = ALIGN(bytes, length);
716a980e046SJonathan Cameron 		bytes += length;
717883f6165SLars Möllendorf 		largest = max(largest, length);
718a980e046SJonathan Cameron 	}
719182b4905SLars-Peter Clausen 
720a980e046SJonathan Cameron 	if (timestamp) {
721182b4905SLars-Peter Clausen 		length = iio_storage_bytes_for_timestamp(indio_dev);
722a980e046SJonathan Cameron 		bytes = ALIGN(bytes, length);
723a980e046SJonathan Cameron 		bytes += length;
724883f6165SLars Möllendorf 		largest = max(largest, length);
725a980e046SJonathan Cameron 	}
726883f6165SLars Möllendorf 
727883f6165SLars Möllendorf 	bytes = ALIGN(bytes, largest);
728a980e046SJonathan Cameron 	return bytes;
729a980e046SJonathan Cameron }
730a980e046SJonathan Cameron 
7319e69c935SLars-Peter Clausen static void iio_buffer_activate(struct iio_dev *indio_dev,
7329e69c935SLars-Peter Clausen 	struct iio_buffer *buffer)
7339e69c935SLars-Peter Clausen {
7346a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
7356a8c6b26SAlexandru Ardelean 
7369e69c935SLars-Peter Clausen 	iio_buffer_get(buffer);
7376a8c6b26SAlexandru Ardelean 	list_add(&buffer->buffer_list, &iio_dev_opaque->buffer_list);
7389e69c935SLars-Peter Clausen }
7399e69c935SLars-Peter Clausen 
7409e69c935SLars-Peter Clausen static void iio_buffer_deactivate(struct iio_buffer *buffer)
7419e69c935SLars-Peter Clausen {
7429e69c935SLars-Peter Clausen 	list_del_init(&buffer->buffer_list);
74337d34556SJosselin Costanzi 	wake_up_interruptible(&buffer->pollq);
7449e69c935SLars-Peter Clausen 	iio_buffer_put(buffer);
7459e69c935SLars-Peter Clausen }
7469e69c935SLars-Peter Clausen 
7471250186aSLars-Peter Clausen static void iio_buffer_deactivate_all(struct iio_dev *indio_dev)
7481250186aSLars-Peter Clausen {
7496a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
7501250186aSLars-Peter Clausen 	struct iio_buffer *buffer, *_buffer;
7511250186aSLars-Peter Clausen 
7521250186aSLars-Peter Clausen 	list_for_each_entry_safe(buffer, _buffer,
7536a8c6b26SAlexandru Ardelean 			&iio_dev_opaque->buffer_list, buffer_list)
7541250186aSLars-Peter Clausen 		iio_buffer_deactivate(buffer);
7551250186aSLars-Peter Clausen }
7561250186aSLars-Peter Clausen 
757e18a2ad4SLars-Peter Clausen static int iio_buffer_enable(struct iio_buffer *buffer,
758e18a2ad4SLars-Peter Clausen 	struct iio_dev *indio_dev)
759e18a2ad4SLars-Peter Clausen {
760e18a2ad4SLars-Peter Clausen 	if (!buffer->access->enable)
761e18a2ad4SLars-Peter Clausen 		return 0;
762e18a2ad4SLars-Peter Clausen 	return buffer->access->enable(buffer, indio_dev);
763e18a2ad4SLars-Peter Clausen }
764e18a2ad4SLars-Peter Clausen 
765e18a2ad4SLars-Peter Clausen static int iio_buffer_disable(struct iio_buffer *buffer,
766e18a2ad4SLars-Peter Clausen 	struct iio_dev *indio_dev)
767e18a2ad4SLars-Peter Clausen {
768e18a2ad4SLars-Peter Clausen 	if (!buffer->access->disable)
769e18a2ad4SLars-Peter Clausen 		return 0;
770e18a2ad4SLars-Peter Clausen 	return buffer->access->disable(buffer, indio_dev);
771e18a2ad4SLars-Peter Clausen }
772e18a2ad4SLars-Peter Clausen 
7738e050996SLars-Peter Clausen static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev,
7748e050996SLars-Peter Clausen 	struct iio_buffer *buffer)
7758e050996SLars-Peter Clausen {
7768e050996SLars-Peter Clausen 	unsigned int bytes;
7778e050996SLars-Peter Clausen 
7788e050996SLars-Peter Clausen 	if (!buffer->access->set_bytes_per_datum)
7798e050996SLars-Peter Clausen 		return;
7808e050996SLars-Peter Clausen 
7818e050996SLars-Peter Clausen 	bytes = iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
7828e050996SLars-Peter Clausen 		buffer->scan_timestamp);
7838e050996SLars-Peter Clausen 
7848e050996SLars-Peter Clausen 	buffer->access->set_bytes_per_datum(buffer, bytes);
7858e050996SLars-Peter Clausen }
7868e050996SLars-Peter Clausen 
787fcc1b2f5SLars-Peter Clausen static int iio_buffer_request_update(struct iio_dev *indio_dev,
788fcc1b2f5SLars-Peter Clausen 	struct iio_buffer *buffer)
789fcc1b2f5SLars-Peter Clausen {
790fcc1b2f5SLars-Peter Clausen 	int ret;
791fcc1b2f5SLars-Peter Clausen 
792fcc1b2f5SLars-Peter Clausen 	iio_buffer_update_bytes_per_datum(indio_dev, buffer);
793fcc1b2f5SLars-Peter Clausen 	if (buffer->access->request_update) {
794fcc1b2f5SLars-Peter Clausen 		ret = buffer->access->request_update(buffer);
795fcc1b2f5SLars-Peter Clausen 		if (ret) {
796fcc1b2f5SLars-Peter Clausen 			dev_dbg(&indio_dev->dev,
797fcc1b2f5SLars-Peter Clausen 			       "Buffer not started: buffer parameter update failed (%d)\n",
798fcc1b2f5SLars-Peter Clausen 				ret);
799fcc1b2f5SLars-Peter Clausen 			return ret;
800fcc1b2f5SLars-Peter Clausen 		}
801fcc1b2f5SLars-Peter Clausen 	}
802fcc1b2f5SLars-Peter Clausen 
803fcc1b2f5SLars-Peter Clausen 	return 0;
804fcc1b2f5SLars-Peter Clausen }
805fcc1b2f5SLars-Peter Clausen 
806248be5aaSLars-Peter Clausen static void iio_free_scan_mask(struct iio_dev *indio_dev,
807248be5aaSLars-Peter Clausen 	const unsigned long *mask)
808248be5aaSLars-Peter Clausen {
809248be5aaSLars-Peter Clausen 	/* If the mask is dynamically allocated free it, otherwise do nothing */
810248be5aaSLars-Peter Clausen 	if (!indio_dev->available_scan_masks)
8113862828aSAndy Shevchenko 		bitmap_free(mask);
812248be5aaSLars-Peter Clausen }
813248be5aaSLars-Peter Clausen 
8146e509c4dSLars-Peter Clausen struct iio_device_config {
8156e509c4dSLars-Peter Clausen 	unsigned int mode;
816f0566c0cSLars-Peter Clausen 	unsigned int watermark;
8176e509c4dSLars-Peter Clausen 	const unsigned long *scan_mask;
8186e509c4dSLars-Peter Clausen 	unsigned int scan_bytes;
8196e509c4dSLars-Peter Clausen 	bool scan_timestamp;
8206e509c4dSLars-Peter Clausen };
8216e509c4dSLars-Peter Clausen 
8226e509c4dSLars-Peter Clausen static int iio_verify_update(struct iio_dev *indio_dev,
8236e509c4dSLars-Peter Clausen 	struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer,
8246e509c4dSLars-Peter Clausen 	struct iio_device_config *config)
8256e509c4dSLars-Peter Clausen {
8266a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
8276e509c4dSLars-Peter Clausen 	unsigned long *compound_mask;
8286e509c4dSLars-Peter Clausen 	const unsigned long *scan_mask;
8291e1ec286SLars-Peter Clausen 	bool strict_scanmask = false;
8306e509c4dSLars-Peter Clausen 	struct iio_buffer *buffer;
8316e509c4dSLars-Peter Clausen 	bool scan_timestamp;
832225d59adSLars-Peter Clausen 	unsigned int modes;
8336e509c4dSLars-Peter Clausen 
834b7329249SLars-Peter Clausen 	if (insert_buffer &&
835b7329249SLars-Peter Clausen 	    bitmap_empty(insert_buffer->scan_mask, indio_dev->masklength)) {
836b7329249SLars-Peter Clausen 		dev_dbg(&indio_dev->dev,
837b7329249SLars-Peter Clausen 			"At least one scan element must be enabled first\n");
838b7329249SLars-Peter Clausen 		return -EINVAL;
839b7329249SLars-Peter Clausen 	}
840b7329249SLars-Peter Clausen 
8416e509c4dSLars-Peter Clausen 	memset(config, 0, sizeof(*config));
8421bef2c1dSIrina Tirdea 	config->watermark = ~0;
8436e509c4dSLars-Peter Clausen 
8446e509c4dSLars-Peter Clausen 	/*
8456e509c4dSLars-Peter Clausen 	 * If there is just one buffer and we are removing it there is nothing
8466e509c4dSLars-Peter Clausen 	 * to verify.
8476e509c4dSLars-Peter Clausen 	 */
8486e509c4dSLars-Peter Clausen 	if (remove_buffer && !insert_buffer &&
8496a8c6b26SAlexandru Ardelean 		list_is_singular(&iio_dev_opaque->buffer_list))
8506e509c4dSLars-Peter Clausen 			return 0;
8516e509c4dSLars-Peter Clausen 
852225d59adSLars-Peter Clausen 	modes = indio_dev->modes;
853225d59adSLars-Peter Clausen 
8546a8c6b26SAlexandru Ardelean 	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
855225d59adSLars-Peter Clausen 		if (buffer == remove_buffer)
856225d59adSLars-Peter Clausen 			continue;
857225d59adSLars-Peter Clausen 		modes &= buffer->access->modes;
858f0566c0cSLars-Peter Clausen 		config->watermark = min(config->watermark, buffer->watermark);
859225d59adSLars-Peter Clausen 	}
860225d59adSLars-Peter Clausen 
861f0566c0cSLars-Peter Clausen 	if (insert_buffer) {
862225d59adSLars-Peter Clausen 		modes &= insert_buffer->access->modes;
863f0566c0cSLars-Peter Clausen 		config->watermark = min(config->watermark,
864f0566c0cSLars-Peter Clausen 			insert_buffer->watermark);
865f0566c0cSLars-Peter Clausen 	}
866225d59adSLars-Peter Clausen 
8676e509c4dSLars-Peter Clausen 	/* Definitely possible for devices to support both of these. */
868225d59adSLars-Peter Clausen 	if ((modes & INDIO_BUFFER_TRIGGERED) && indio_dev->trig) {
8696e509c4dSLars-Peter Clausen 		config->mode = INDIO_BUFFER_TRIGGERED;
870225d59adSLars-Peter Clausen 	} else if (modes & INDIO_BUFFER_HARDWARE) {
8711e1ec286SLars-Peter Clausen 		/*
8721e1ec286SLars-Peter Clausen 		 * Keep things simple for now and only allow a single buffer to
8731e1ec286SLars-Peter Clausen 		 * be connected in hardware mode.
8741e1ec286SLars-Peter Clausen 		 */
8756a8c6b26SAlexandru Ardelean 		if (insert_buffer && !list_empty(&iio_dev_opaque->buffer_list))
8761e1ec286SLars-Peter Clausen 			return -EINVAL;
8776e509c4dSLars-Peter Clausen 		config->mode = INDIO_BUFFER_HARDWARE;
8781e1ec286SLars-Peter Clausen 		strict_scanmask = true;
879225d59adSLars-Peter Clausen 	} else if (modes & INDIO_BUFFER_SOFTWARE) {
8806e509c4dSLars-Peter Clausen 		config->mode = INDIO_BUFFER_SOFTWARE;
8816e509c4dSLars-Peter Clausen 	} else {
8826e509c4dSLars-Peter Clausen 		/* Can only occur on first buffer */
8836e509c4dSLars-Peter Clausen 		if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
8846e509c4dSLars-Peter Clausen 			dev_dbg(&indio_dev->dev, "Buffer not started: no trigger\n");
8856e509c4dSLars-Peter Clausen 		return -EINVAL;
8866e509c4dSLars-Peter Clausen 	}
8876e509c4dSLars-Peter Clausen 
8886e509c4dSLars-Peter Clausen 	/* What scan mask do we actually have? */
8893862828aSAndy Shevchenko 	compound_mask = bitmap_zalloc(indio_dev->masklength, GFP_KERNEL);
8906e509c4dSLars-Peter Clausen 	if (compound_mask == NULL)
8916e509c4dSLars-Peter Clausen 		return -ENOMEM;
8926e509c4dSLars-Peter Clausen 
8936e509c4dSLars-Peter Clausen 	scan_timestamp = false;
8946e509c4dSLars-Peter Clausen 
8956a8c6b26SAlexandru Ardelean 	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
8966e509c4dSLars-Peter Clausen 		if (buffer == remove_buffer)
8976e509c4dSLars-Peter Clausen 			continue;
8986e509c4dSLars-Peter Clausen 		bitmap_or(compound_mask, compound_mask, buffer->scan_mask,
8996e509c4dSLars-Peter Clausen 			  indio_dev->masklength);
9006e509c4dSLars-Peter Clausen 		scan_timestamp |= buffer->scan_timestamp;
9016e509c4dSLars-Peter Clausen 	}
9026e509c4dSLars-Peter Clausen 
9036e509c4dSLars-Peter Clausen 	if (insert_buffer) {
9046e509c4dSLars-Peter Clausen 		bitmap_or(compound_mask, compound_mask,
9056e509c4dSLars-Peter Clausen 			  insert_buffer->scan_mask, indio_dev->masklength);
9066e509c4dSLars-Peter Clausen 		scan_timestamp |= insert_buffer->scan_timestamp;
9076e509c4dSLars-Peter Clausen 	}
9086e509c4dSLars-Peter Clausen 
9096e509c4dSLars-Peter Clausen 	if (indio_dev->available_scan_masks) {
9106e509c4dSLars-Peter Clausen 		scan_mask = iio_scan_mask_match(indio_dev->available_scan_masks,
9116e509c4dSLars-Peter Clausen 				    indio_dev->masklength,
9121e1ec286SLars-Peter Clausen 				    compound_mask,
9131e1ec286SLars-Peter Clausen 				    strict_scanmask);
9143862828aSAndy Shevchenko 		bitmap_free(compound_mask);
9156e509c4dSLars-Peter Clausen 		if (scan_mask == NULL)
9166e509c4dSLars-Peter Clausen 			return -EINVAL;
9176e509c4dSLars-Peter Clausen 	} else {
9186e509c4dSLars-Peter Clausen 	    scan_mask = compound_mask;
9196e509c4dSLars-Peter Clausen 	}
9206e509c4dSLars-Peter Clausen 
9216e509c4dSLars-Peter Clausen 	config->scan_bytes = iio_compute_scan_bytes(indio_dev,
9226e509c4dSLars-Peter Clausen 				    scan_mask, scan_timestamp);
9236e509c4dSLars-Peter Clausen 	config->scan_mask = scan_mask;
9246e509c4dSLars-Peter Clausen 	config->scan_timestamp = scan_timestamp;
9256e509c4dSLars-Peter Clausen 
9266e509c4dSLars-Peter Clausen 	return 0;
9276e509c4dSLars-Peter Clausen }
9286e509c4dSLars-Peter Clausen 
92978c9981fSJonathan Cameron /**
93078c9981fSJonathan Cameron  * struct iio_demux_table - table describing demux memcpy ops
93178c9981fSJonathan Cameron  * @from:	index to copy from
93278c9981fSJonathan Cameron  * @to:		index to copy to
93378c9981fSJonathan Cameron  * @length:	how many bytes to copy
93478c9981fSJonathan Cameron  * @l:		list head used for management
93578c9981fSJonathan Cameron  */
93678c9981fSJonathan Cameron struct iio_demux_table {
93778c9981fSJonathan Cameron 	unsigned from;
93878c9981fSJonathan Cameron 	unsigned to;
93978c9981fSJonathan Cameron 	unsigned length;
94078c9981fSJonathan Cameron 	struct list_head l;
94178c9981fSJonathan Cameron };
94278c9981fSJonathan Cameron 
94378c9981fSJonathan Cameron static void iio_buffer_demux_free(struct iio_buffer *buffer)
94478c9981fSJonathan Cameron {
94578c9981fSJonathan Cameron 	struct iio_demux_table *p, *q;
94678c9981fSJonathan Cameron 	list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
94778c9981fSJonathan Cameron 		list_del(&p->l);
94878c9981fSJonathan Cameron 		kfree(p);
94978c9981fSJonathan Cameron 	}
95078c9981fSJonathan Cameron }
95178c9981fSJonathan Cameron 
95278c9981fSJonathan Cameron static int iio_buffer_add_demux(struct iio_buffer *buffer,
95378c9981fSJonathan Cameron 	struct iio_demux_table **p, unsigned int in_loc, unsigned int out_loc,
95478c9981fSJonathan Cameron 	unsigned int length)
95578c9981fSJonathan Cameron {
95678c9981fSJonathan Cameron 
95778c9981fSJonathan Cameron 	if (*p && (*p)->from + (*p)->length == in_loc &&
95878c9981fSJonathan Cameron 		(*p)->to + (*p)->length == out_loc) {
95978c9981fSJonathan Cameron 		(*p)->length += length;
96078c9981fSJonathan Cameron 	} else {
96178c9981fSJonathan Cameron 		*p = kmalloc(sizeof(**p), GFP_KERNEL);
96278c9981fSJonathan Cameron 		if (*p == NULL)
96378c9981fSJonathan Cameron 			return -ENOMEM;
96478c9981fSJonathan Cameron 		(*p)->from = in_loc;
96578c9981fSJonathan Cameron 		(*p)->to = out_loc;
96678c9981fSJonathan Cameron 		(*p)->length = length;
96778c9981fSJonathan Cameron 		list_add_tail(&(*p)->l, &buffer->demux_list);
96878c9981fSJonathan Cameron 	}
96978c9981fSJonathan Cameron 
97078c9981fSJonathan Cameron 	return 0;
97178c9981fSJonathan Cameron }
97278c9981fSJonathan Cameron 
97378c9981fSJonathan Cameron static int iio_buffer_update_demux(struct iio_dev *indio_dev,
97478c9981fSJonathan Cameron 				   struct iio_buffer *buffer)
97578c9981fSJonathan Cameron {
97678c9981fSJonathan Cameron 	int ret, in_ind = -1, out_ind, length;
97778c9981fSJonathan Cameron 	unsigned in_loc = 0, out_loc = 0;
97878c9981fSJonathan Cameron 	struct iio_demux_table *p = NULL;
97978c9981fSJonathan Cameron 
98078c9981fSJonathan Cameron 	/* Clear out any old demux */
98178c9981fSJonathan Cameron 	iio_buffer_demux_free(buffer);
98278c9981fSJonathan Cameron 	kfree(buffer->demux_bounce);
98378c9981fSJonathan Cameron 	buffer->demux_bounce = NULL;
98478c9981fSJonathan Cameron 
98578c9981fSJonathan Cameron 	/* First work out which scan mode we will actually have */
98678c9981fSJonathan Cameron 	if (bitmap_equal(indio_dev->active_scan_mask,
98778c9981fSJonathan Cameron 			 buffer->scan_mask,
98878c9981fSJonathan Cameron 			 indio_dev->masklength))
98978c9981fSJonathan Cameron 		return 0;
99078c9981fSJonathan Cameron 
99178c9981fSJonathan Cameron 	/* Now we have the two masks, work from least sig and build up sizes */
99278c9981fSJonathan Cameron 	for_each_set_bit(out_ind,
99378c9981fSJonathan Cameron 			 buffer->scan_mask,
99478c9981fSJonathan Cameron 			 indio_dev->masklength) {
99578c9981fSJonathan Cameron 		in_ind = find_next_bit(indio_dev->active_scan_mask,
99678c9981fSJonathan Cameron 				       indio_dev->masklength,
99778c9981fSJonathan Cameron 				       in_ind + 1);
99878c9981fSJonathan Cameron 		while (in_ind != out_ind) {
99978c9981fSJonathan Cameron 			length = iio_storage_bytes_for_si(indio_dev, in_ind);
100078c9981fSJonathan Cameron 			/* Make sure we are aligned */
100178c9981fSJonathan Cameron 			in_loc = roundup(in_loc, length) + length;
100219ef7b70SNuno Sá 			in_ind = find_next_bit(indio_dev->active_scan_mask,
100319ef7b70SNuno Sá 					       indio_dev->masklength,
100419ef7b70SNuno Sá 					       in_ind + 1);
100578c9981fSJonathan Cameron 		}
100678c9981fSJonathan Cameron 		length = iio_storage_bytes_for_si(indio_dev, in_ind);
100778c9981fSJonathan Cameron 		out_loc = roundup(out_loc, length);
100878c9981fSJonathan Cameron 		in_loc = roundup(in_loc, length);
100978c9981fSJonathan Cameron 		ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length);
101078c9981fSJonathan Cameron 		if (ret)
101178c9981fSJonathan Cameron 			goto error_clear_mux_table;
101278c9981fSJonathan Cameron 		out_loc += length;
101378c9981fSJonathan Cameron 		in_loc += length;
101478c9981fSJonathan Cameron 	}
101578c9981fSJonathan Cameron 	/* Relies on scan_timestamp being last */
101678c9981fSJonathan Cameron 	if (buffer->scan_timestamp) {
101778c9981fSJonathan Cameron 		length = iio_storage_bytes_for_timestamp(indio_dev);
101878c9981fSJonathan Cameron 		out_loc = roundup(out_loc, length);
101978c9981fSJonathan Cameron 		in_loc = roundup(in_loc, length);
102078c9981fSJonathan Cameron 		ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length);
102178c9981fSJonathan Cameron 		if (ret)
102278c9981fSJonathan Cameron 			goto error_clear_mux_table;
102378c9981fSJonathan Cameron 		out_loc += length;
102478c9981fSJonathan Cameron 	}
102578c9981fSJonathan Cameron 	buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL);
102678c9981fSJonathan Cameron 	if (buffer->demux_bounce == NULL) {
102778c9981fSJonathan Cameron 		ret = -ENOMEM;
102878c9981fSJonathan Cameron 		goto error_clear_mux_table;
102978c9981fSJonathan Cameron 	}
103078c9981fSJonathan Cameron 	return 0;
103178c9981fSJonathan Cameron 
103278c9981fSJonathan Cameron error_clear_mux_table:
103378c9981fSJonathan Cameron 	iio_buffer_demux_free(buffer);
103478c9981fSJonathan Cameron 
103578c9981fSJonathan Cameron 	return ret;
103678c9981fSJonathan Cameron }
103778c9981fSJonathan Cameron 
103878c9981fSJonathan Cameron static int iio_update_demux(struct iio_dev *indio_dev)
103978c9981fSJonathan Cameron {
10406a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
104178c9981fSJonathan Cameron 	struct iio_buffer *buffer;
104278c9981fSJonathan Cameron 	int ret;
104378c9981fSJonathan Cameron 
10446a8c6b26SAlexandru Ardelean 	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
104578c9981fSJonathan Cameron 		ret = iio_buffer_update_demux(indio_dev, buffer);
104678c9981fSJonathan Cameron 		if (ret < 0)
104778c9981fSJonathan Cameron 			goto error_clear_mux_table;
104878c9981fSJonathan Cameron 	}
104978c9981fSJonathan Cameron 	return 0;
105078c9981fSJonathan Cameron 
105178c9981fSJonathan Cameron error_clear_mux_table:
10526a8c6b26SAlexandru Ardelean 	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list)
105378c9981fSJonathan Cameron 		iio_buffer_demux_free(buffer);
105478c9981fSJonathan Cameron 
105578c9981fSJonathan Cameron 	return ret;
105678c9981fSJonathan Cameron }
105778c9981fSJonathan Cameron 
1058623d74e3SLars-Peter Clausen static int iio_enable_buffers(struct iio_dev *indio_dev,
1059623d74e3SLars-Peter Clausen 	struct iio_device_config *config)
1060623d74e3SLars-Peter Clausen {
10616a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1062e18a2ad4SLars-Peter Clausen 	struct iio_buffer *buffer;
1063623d74e3SLars-Peter Clausen 	int ret;
1064623d74e3SLars-Peter Clausen 
1065623d74e3SLars-Peter Clausen 	indio_dev->active_scan_mask = config->scan_mask;
1066623d74e3SLars-Peter Clausen 	indio_dev->scan_timestamp = config->scan_timestamp;
1067623d74e3SLars-Peter Clausen 	indio_dev->scan_bytes = config->scan_bytes;
10685cb1a548SLars-Peter Clausen 	indio_dev->currentmode = config->mode;
1069623d74e3SLars-Peter Clausen 
1070623d74e3SLars-Peter Clausen 	iio_update_demux(indio_dev);
1071623d74e3SLars-Peter Clausen 
1072623d74e3SLars-Peter Clausen 	/* Wind up again */
1073623d74e3SLars-Peter Clausen 	if (indio_dev->setup_ops->preenable) {
1074623d74e3SLars-Peter Clausen 		ret = indio_dev->setup_ops->preenable(indio_dev);
1075623d74e3SLars-Peter Clausen 		if (ret) {
1076623d74e3SLars-Peter Clausen 			dev_dbg(&indio_dev->dev,
1077623d74e3SLars-Peter Clausen 			       "Buffer not started: buffer preenable failed (%d)\n", ret);
1078623d74e3SLars-Peter Clausen 			goto err_undo_config;
1079623d74e3SLars-Peter Clausen 		}
1080623d74e3SLars-Peter Clausen 	}
1081623d74e3SLars-Peter Clausen 
1082623d74e3SLars-Peter Clausen 	if (indio_dev->info->update_scan_mode) {
1083623d74e3SLars-Peter Clausen 		ret = indio_dev->info
1084623d74e3SLars-Peter Clausen 			->update_scan_mode(indio_dev,
1085623d74e3SLars-Peter Clausen 					   indio_dev->active_scan_mask);
1086623d74e3SLars-Peter Clausen 		if (ret < 0) {
1087623d74e3SLars-Peter Clausen 			dev_dbg(&indio_dev->dev,
1088623d74e3SLars-Peter Clausen 				"Buffer not started: update scan mode failed (%d)\n",
1089623d74e3SLars-Peter Clausen 				ret);
1090623d74e3SLars-Peter Clausen 			goto err_run_postdisable;
1091623d74e3SLars-Peter Clausen 		}
1092623d74e3SLars-Peter Clausen 	}
1093623d74e3SLars-Peter Clausen 
1094f0566c0cSLars-Peter Clausen 	if (indio_dev->info->hwfifo_set_watermark)
1095f0566c0cSLars-Peter Clausen 		indio_dev->info->hwfifo_set_watermark(indio_dev,
1096f0566c0cSLars-Peter Clausen 			config->watermark);
1097f0566c0cSLars-Peter Clausen 
10986a8c6b26SAlexandru Ardelean 	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
1099e18a2ad4SLars-Peter Clausen 		ret = iio_buffer_enable(buffer, indio_dev);
1100e18a2ad4SLars-Peter Clausen 		if (ret)
1101e18a2ad4SLars-Peter Clausen 			goto err_disable_buffers;
1102e18a2ad4SLars-Peter Clausen 	}
1103e18a2ad4SLars-Peter Clausen 
1104f11d59d8SLars-Peter Clausen 	if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
1105f11d59d8SLars-Peter Clausen 		ret = iio_trigger_attach_poll_func(indio_dev->trig,
1106f11d59d8SLars-Peter Clausen 						   indio_dev->pollfunc);
1107f11d59d8SLars-Peter Clausen 		if (ret)
1108f11d59d8SLars-Peter Clausen 			goto err_disable_buffers;
1109f11d59d8SLars-Peter Clausen 	}
1110f11d59d8SLars-Peter Clausen 
111162a30a29SAlexandru Ardelean 	if (indio_dev->setup_ops->postenable) {
111262a30a29SAlexandru Ardelean 		ret = indio_dev->setup_ops->postenable(indio_dev);
111362a30a29SAlexandru Ardelean 		if (ret) {
111462a30a29SAlexandru Ardelean 			dev_dbg(&indio_dev->dev,
111562a30a29SAlexandru Ardelean 			       "Buffer not started: postenable failed (%d)\n", ret);
111662a30a29SAlexandru Ardelean 			goto err_detach_pollfunc;
111762a30a29SAlexandru Ardelean 		}
111862a30a29SAlexandru Ardelean 	}
111962a30a29SAlexandru Ardelean 
1120623d74e3SLars-Peter Clausen 	return 0;
1121623d74e3SLars-Peter Clausen 
112262a30a29SAlexandru Ardelean err_detach_pollfunc:
112362a30a29SAlexandru Ardelean 	if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
112462a30a29SAlexandru Ardelean 		iio_trigger_detach_poll_func(indio_dev->trig,
112562a30a29SAlexandru Ardelean 					     indio_dev->pollfunc);
112662a30a29SAlexandru Ardelean 	}
1127e18a2ad4SLars-Peter Clausen err_disable_buffers:
11286a8c6b26SAlexandru Ardelean 	list_for_each_entry_continue_reverse(buffer, &iio_dev_opaque->buffer_list,
1129e18a2ad4SLars-Peter Clausen 					     buffer_list)
1130e18a2ad4SLars-Peter Clausen 		iio_buffer_disable(buffer, indio_dev);
1131623d74e3SLars-Peter Clausen err_run_postdisable:
1132623d74e3SLars-Peter Clausen 	if (indio_dev->setup_ops->postdisable)
1133623d74e3SLars-Peter Clausen 		indio_dev->setup_ops->postdisable(indio_dev);
1134623d74e3SLars-Peter Clausen err_undo_config:
11355cb1a548SLars-Peter Clausen 	indio_dev->currentmode = INDIO_DIRECT_MODE;
1136623d74e3SLars-Peter Clausen 	indio_dev->active_scan_mask = NULL;
1137623d74e3SLars-Peter Clausen 
1138623d74e3SLars-Peter Clausen 	return ret;
1139623d74e3SLars-Peter Clausen }
1140623d74e3SLars-Peter Clausen 
1141623d74e3SLars-Peter Clausen static int iio_disable_buffers(struct iio_dev *indio_dev)
1142623d74e3SLars-Peter Clausen {
11436a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1144e18a2ad4SLars-Peter Clausen 	struct iio_buffer *buffer;
11451250186aSLars-Peter Clausen 	int ret = 0;
11461250186aSLars-Peter Clausen 	int ret2;
1147623d74e3SLars-Peter Clausen 
1148623d74e3SLars-Peter Clausen 	/* Wind down existing buffers - iff there are any */
11496a8c6b26SAlexandru Ardelean 	if (list_empty(&iio_dev_opaque->buffer_list))
1150623d74e3SLars-Peter Clausen 		return 0;
1151623d74e3SLars-Peter Clausen 
11521250186aSLars-Peter Clausen 	/*
11531250186aSLars-Peter Clausen 	 * If things go wrong at some step in disable we still need to continue
11541250186aSLars-Peter Clausen 	 * to perform the other steps, otherwise we leave the device in a
11551250186aSLars-Peter Clausen 	 * inconsistent state. We return the error code for the first error we
11561250186aSLars-Peter Clausen 	 * encountered.
11571250186aSLars-Peter Clausen 	 */
11581250186aSLars-Peter Clausen 
1159623d74e3SLars-Peter Clausen 	if (indio_dev->setup_ops->predisable) {
11601250186aSLars-Peter Clausen 		ret2 = indio_dev->setup_ops->predisable(indio_dev);
11611250186aSLars-Peter Clausen 		if (ret2 && !ret)
11621250186aSLars-Peter Clausen 			ret = ret2;
1163623d74e3SLars-Peter Clausen 	}
1164623d74e3SLars-Peter Clausen 
116562a30a29SAlexandru Ardelean 	if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
116662a30a29SAlexandru Ardelean 		iio_trigger_detach_poll_func(indio_dev->trig,
116762a30a29SAlexandru Ardelean 					     indio_dev->pollfunc);
116862a30a29SAlexandru Ardelean 	}
116962a30a29SAlexandru Ardelean 
11706a8c6b26SAlexandru Ardelean 	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
1171e18a2ad4SLars-Peter Clausen 		ret2 = iio_buffer_disable(buffer, indio_dev);
1172e18a2ad4SLars-Peter Clausen 		if (ret2 && !ret)
1173e18a2ad4SLars-Peter Clausen 			ret = ret2;
1174e18a2ad4SLars-Peter Clausen 	}
1175e18a2ad4SLars-Peter Clausen 
1176623d74e3SLars-Peter Clausen 	if (indio_dev->setup_ops->postdisable) {
11771250186aSLars-Peter Clausen 		ret2 = indio_dev->setup_ops->postdisable(indio_dev);
11781250186aSLars-Peter Clausen 		if (ret2 && !ret)
11791250186aSLars-Peter Clausen 			ret = ret2;
1180623d74e3SLars-Peter Clausen 	}
1181623d74e3SLars-Peter Clausen 
11821250186aSLars-Peter Clausen 	iio_free_scan_mask(indio_dev, indio_dev->active_scan_mask);
11831250186aSLars-Peter Clausen 	indio_dev->active_scan_mask = NULL;
11845cb1a548SLars-Peter Clausen 	indio_dev->currentmode = INDIO_DIRECT_MODE;
11851250186aSLars-Peter Clausen 
11861250186aSLars-Peter Clausen 	return ret;
1187623d74e3SLars-Peter Clausen }
1188623d74e3SLars-Peter Clausen 
1189a9519456SLars-Peter Clausen static int __iio_update_buffers(struct iio_dev *indio_dev,
119084b36ce5SJonathan Cameron 		       struct iio_buffer *insert_buffer,
119184b36ce5SJonathan Cameron 		       struct iio_buffer *remove_buffer)
1192a980e046SJonathan Cameron {
11936a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
11946e509c4dSLars-Peter Clausen 	struct iio_device_config new_config;
11951250186aSLars-Peter Clausen 	int ret;
11966e509c4dSLars-Peter Clausen 
11976e509c4dSLars-Peter Clausen 	ret = iio_verify_update(indio_dev, insert_buffer, remove_buffer,
11986e509c4dSLars-Peter Clausen 		&new_config);
11996e509c4dSLars-Peter Clausen 	if (ret)
12006e509c4dSLars-Peter Clausen 		return ret;
1201a980e046SJonathan Cameron 
1202fcc1b2f5SLars-Peter Clausen 	if (insert_buffer) {
1203fcc1b2f5SLars-Peter Clausen 		ret = iio_buffer_request_update(indio_dev, insert_buffer);
1204fcc1b2f5SLars-Peter Clausen 		if (ret)
12056e509c4dSLars-Peter Clausen 			goto err_free_config;
1206fcc1b2f5SLars-Peter Clausen 	}
1207fcc1b2f5SLars-Peter Clausen 
1208623d74e3SLars-Peter Clausen 	ret = iio_disable_buffers(indio_dev);
12091250186aSLars-Peter Clausen 	if (ret)
12101250186aSLars-Peter Clausen 		goto err_deactivate_all;
1211623d74e3SLars-Peter Clausen 
121284b36ce5SJonathan Cameron 	if (remove_buffer)
12139e69c935SLars-Peter Clausen 		iio_buffer_deactivate(remove_buffer);
121484b36ce5SJonathan Cameron 	if (insert_buffer)
12159e69c935SLars-Peter Clausen 		iio_buffer_activate(indio_dev, insert_buffer);
121684b36ce5SJonathan Cameron 
121784b36ce5SJonathan Cameron 	/* If no buffers in list, we are done */
12186a8c6b26SAlexandru Ardelean 	if (list_empty(&iio_dev_opaque->buffer_list))
121984b36ce5SJonathan Cameron 		return 0;
1220a980e046SJonathan Cameron 
1221623d74e3SLars-Peter Clausen 	ret = iio_enable_buffers(indio_dev, &new_config);
12221250186aSLars-Peter Clausen 	if (ret)
12231250186aSLars-Peter Clausen 		goto err_deactivate_all;
1224623d74e3SLars-Peter Clausen 
1225623d74e3SLars-Peter Clausen 	return 0;
12266e509c4dSLars-Peter Clausen 
12271250186aSLars-Peter Clausen err_deactivate_all:
12281250186aSLars-Peter Clausen 	/*
12291250186aSLars-Peter Clausen 	 * We've already verified that the config is valid earlier. If things go
12301250186aSLars-Peter Clausen 	 * wrong in either enable or disable the most likely reason is an IO
12311250186aSLars-Peter Clausen 	 * error from the device. In this case there is no good recovery
12321250186aSLars-Peter Clausen 	 * strategy. Just make sure to disable everything and leave the device
12331250186aSLars-Peter Clausen 	 * in a sane state.  With a bit of luck the device might come back to
12341250186aSLars-Peter Clausen 	 * life again later and userspace can try again.
12351250186aSLars-Peter Clausen 	 */
12361250186aSLars-Peter Clausen 	iio_buffer_deactivate_all(indio_dev);
12371250186aSLars-Peter Clausen 
12386e509c4dSLars-Peter Clausen err_free_config:
12396e509c4dSLars-Peter Clausen 	iio_free_scan_mask(indio_dev, new_config.scan_mask);
12406e509c4dSLars-Peter Clausen 	return ret;
124184b36ce5SJonathan Cameron }
1242a9519456SLars-Peter Clausen 
1243a9519456SLars-Peter Clausen int iio_update_buffers(struct iio_dev *indio_dev,
1244a9519456SLars-Peter Clausen 		       struct iio_buffer *insert_buffer,
1245a9519456SLars-Peter Clausen 		       struct iio_buffer *remove_buffer)
1246a9519456SLars-Peter Clausen {
1247b804e2b7SJonathan Cameron 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1248a9519456SLars-Peter Clausen 	int ret;
1249a9519456SLars-Peter Clausen 
12503909fab5SLars-Peter Clausen 	if (insert_buffer == remove_buffer)
12513909fab5SLars-Peter Clausen 		return 0;
12523909fab5SLars-Peter Clausen 
12539eeee3b0SMihail Chindris 	if (insert_buffer &&
12549eeee3b0SMihail Chindris 	    (insert_buffer->direction == IIO_BUFFER_DIRECTION_OUT))
12559eeee3b0SMihail Chindris 		return -EINVAL;
12569eeee3b0SMihail Chindris 
1257b804e2b7SJonathan Cameron 	mutex_lock(&iio_dev_opaque->info_exist_lock);
1258a9519456SLars-Peter Clausen 	mutex_lock(&indio_dev->mlock);
1259a9519456SLars-Peter Clausen 
12603909fab5SLars-Peter Clausen 	if (insert_buffer && iio_buffer_is_active(insert_buffer))
12613909fab5SLars-Peter Clausen 		insert_buffer = NULL;
12623909fab5SLars-Peter Clausen 
12633909fab5SLars-Peter Clausen 	if (remove_buffer && !iio_buffer_is_active(remove_buffer))
12643909fab5SLars-Peter Clausen 		remove_buffer = NULL;
12653909fab5SLars-Peter Clausen 
12663909fab5SLars-Peter Clausen 	if (!insert_buffer && !remove_buffer) {
12673909fab5SLars-Peter Clausen 		ret = 0;
12683909fab5SLars-Peter Clausen 		goto out_unlock;
12693909fab5SLars-Peter Clausen 	}
12703909fab5SLars-Peter Clausen 
1271a9519456SLars-Peter Clausen 	if (indio_dev->info == NULL) {
1272a9519456SLars-Peter Clausen 		ret = -ENODEV;
1273a9519456SLars-Peter Clausen 		goto out_unlock;
1274a9519456SLars-Peter Clausen 	}
1275a9519456SLars-Peter Clausen 
1276a9519456SLars-Peter Clausen 	ret = __iio_update_buffers(indio_dev, insert_buffer, remove_buffer);
1277a9519456SLars-Peter Clausen 
1278a9519456SLars-Peter Clausen out_unlock:
1279a9519456SLars-Peter Clausen 	mutex_unlock(&indio_dev->mlock);
1280b804e2b7SJonathan Cameron 	mutex_unlock(&iio_dev_opaque->info_exist_lock);
1281a9519456SLars-Peter Clausen 
1282a9519456SLars-Peter Clausen 	return ret;
1283a9519456SLars-Peter Clausen }
128484b36ce5SJonathan Cameron EXPORT_SYMBOL_GPL(iio_update_buffers);
128584b36ce5SJonathan Cameron 
1286623d74e3SLars-Peter Clausen void iio_disable_all_buffers(struct iio_dev *indio_dev)
1287623d74e3SLars-Peter Clausen {
1288623d74e3SLars-Peter Clausen 	iio_disable_buffers(indio_dev);
12891250186aSLars-Peter Clausen 	iio_buffer_deactivate_all(indio_dev);
1290623d74e3SLars-Peter Clausen }
1291623d74e3SLars-Peter Clausen 
129208e7e0adSLars-Peter Clausen static ssize_t iio_buffer_store_enable(struct device *dev,
129384b36ce5SJonathan Cameron 				       struct device_attribute *attr,
129484b36ce5SJonathan Cameron 				       const char *buf,
129584b36ce5SJonathan Cameron 				       size_t len)
129684b36ce5SJonathan Cameron {
129784b36ce5SJonathan Cameron 	int ret;
129884b36ce5SJonathan Cameron 	bool requested_state;
129984b36ce5SJonathan Cameron 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
130015097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
130184b36ce5SJonathan Cameron 	bool inlist;
130284b36ce5SJonathan Cameron 
130384b36ce5SJonathan Cameron 	ret = strtobool(buf, &requested_state);
130484b36ce5SJonathan Cameron 	if (ret < 0)
130584b36ce5SJonathan Cameron 		return ret;
130684b36ce5SJonathan Cameron 
130784b36ce5SJonathan Cameron 	mutex_lock(&indio_dev->mlock);
130884b36ce5SJonathan Cameron 
130984b36ce5SJonathan Cameron 	/* Find out if it is in the list */
1310ff3f7e04SAlexandru Ardelean 	inlist = iio_buffer_is_active(buffer);
131184b36ce5SJonathan Cameron 	/* Already in desired state */
131284b36ce5SJonathan Cameron 	if (inlist == requested_state)
131384b36ce5SJonathan Cameron 		goto done;
131484b36ce5SJonathan Cameron 
131584b36ce5SJonathan Cameron 	if (requested_state)
1316ff3f7e04SAlexandru Ardelean 		ret = __iio_update_buffers(indio_dev, buffer, NULL);
131784b36ce5SJonathan Cameron 	else
1318ff3f7e04SAlexandru Ardelean 		ret = __iio_update_buffers(indio_dev, NULL, buffer);
131984b36ce5SJonathan Cameron 
132084b36ce5SJonathan Cameron done:
132184b36ce5SJonathan Cameron 	mutex_unlock(&indio_dev->mlock);
132284b36ce5SJonathan Cameron 	return (ret < 0) ? ret : len;
132384b36ce5SJonathan Cameron }
132484b36ce5SJonathan Cameron 
132537d34556SJosselin Costanzi static ssize_t iio_buffer_show_watermark(struct device *dev,
132637d34556SJosselin Costanzi 					 struct device_attribute *attr,
132737d34556SJosselin Costanzi 					 char *buf)
132837d34556SJosselin Costanzi {
132915097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
133037d34556SJosselin Costanzi 
133183ca56b6SLars-Peter Clausen 	return sysfs_emit(buf, "%u\n", buffer->watermark);
133237d34556SJosselin Costanzi }
133337d34556SJosselin Costanzi 
133437d34556SJosselin Costanzi static ssize_t iio_buffer_store_watermark(struct device *dev,
133537d34556SJosselin Costanzi 					  struct device_attribute *attr,
133637d34556SJosselin Costanzi 					  const char *buf,
133737d34556SJosselin Costanzi 					  size_t len)
133837d34556SJosselin Costanzi {
133937d34556SJosselin Costanzi 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
134015097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
134137d34556SJosselin Costanzi 	unsigned int val;
134237d34556SJosselin Costanzi 	int ret;
134337d34556SJosselin Costanzi 
134437d34556SJosselin Costanzi 	ret = kstrtouint(buf, 10, &val);
134537d34556SJosselin Costanzi 	if (ret)
134637d34556SJosselin Costanzi 		return ret;
134737d34556SJosselin Costanzi 	if (!val)
134837d34556SJosselin Costanzi 		return -EINVAL;
134937d34556SJosselin Costanzi 
135037d34556SJosselin Costanzi 	mutex_lock(&indio_dev->mlock);
135137d34556SJosselin Costanzi 
135237d34556SJosselin Costanzi 	if (val > buffer->length) {
135337d34556SJosselin Costanzi 		ret = -EINVAL;
135437d34556SJosselin Costanzi 		goto out;
135537d34556SJosselin Costanzi 	}
135637d34556SJosselin Costanzi 
1357ff3f7e04SAlexandru Ardelean 	if (iio_buffer_is_active(buffer)) {
135837d34556SJosselin Costanzi 		ret = -EBUSY;
135937d34556SJosselin Costanzi 		goto out;
136037d34556SJosselin Costanzi 	}
136137d34556SJosselin Costanzi 
136237d34556SJosselin Costanzi 	buffer->watermark = val;
136337d34556SJosselin Costanzi out:
136437d34556SJosselin Costanzi 	mutex_unlock(&indio_dev->mlock);
136537d34556SJosselin Costanzi 
136637d34556SJosselin Costanzi 	return ret ? ret : len;
136737d34556SJosselin Costanzi }
136837d34556SJosselin Costanzi 
1369350f6c75SMatt Fornero static ssize_t iio_dma_show_data_available(struct device *dev,
1370350f6c75SMatt Fornero 						struct device_attribute *attr,
1371350f6c75SMatt Fornero 						char *buf)
1372350f6c75SMatt Fornero {
137315097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
1374350f6c75SMatt Fornero 
137583ca56b6SLars-Peter Clausen 	return sysfs_emit(buf, "%zu\n", iio_buffer_data_available(buffer));
1376350f6c75SMatt Fornero }
1377350f6c75SMatt Fornero 
13789eeee3b0SMihail Chindris static ssize_t direction_show(struct device *dev,
13799eeee3b0SMihail Chindris 			      struct device_attribute *attr,
13809eeee3b0SMihail Chindris 			      char *buf)
13819eeee3b0SMihail Chindris {
13829eeee3b0SMihail Chindris 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
13839eeee3b0SMihail Chindris 
13849eeee3b0SMihail Chindris 	switch (buffer->direction) {
13859eeee3b0SMihail Chindris 	case IIO_BUFFER_DIRECTION_IN:
13869eeee3b0SMihail Chindris 		return sprintf(buf, "in\n");
13879eeee3b0SMihail Chindris 	case IIO_BUFFER_DIRECTION_OUT:
13889eeee3b0SMihail Chindris 		return sprintf(buf, "out\n");
13899eeee3b0SMihail Chindris 	default:
13909eeee3b0SMihail Chindris 		return -EINVAL;
13919eeee3b0SMihail Chindris 	}
13929eeee3b0SMihail Chindris }
13939eeee3b0SMihail Chindris 
139408e7e0adSLars-Peter Clausen static DEVICE_ATTR(length, S_IRUGO | S_IWUSR, iio_buffer_read_length,
139508e7e0adSLars-Peter Clausen 		   iio_buffer_write_length);
13968d92db28SLars-Peter Clausen static struct device_attribute dev_attr_length_ro = __ATTR(length,
13978d92db28SLars-Peter Clausen 	S_IRUGO, iio_buffer_read_length, NULL);
139808e7e0adSLars-Peter Clausen static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR,
139908e7e0adSLars-Peter Clausen 		   iio_buffer_show_enable, iio_buffer_store_enable);
140037d34556SJosselin Costanzi static DEVICE_ATTR(watermark, S_IRUGO | S_IWUSR,
140137d34556SJosselin Costanzi 		   iio_buffer_show_watermark, iio_buffer_store_watermark);
1402b440655bSLars-Peter Clausen static struct device_attribute dev_attr_watermark_ro = __ATTR(watermark,
1403b440655bSLars-Peter Clausen 	S_IRUGO, iio_buffer_show_watermark, NULL);
1404350f6c75SMatt Fornero static DEVICE_ATTR(data_available, S_IRUGO,
1405350f6c75SMatt Fornero 		iio_dma_show_data_available, NULL);
14069eeee3b0SMihail Chindris static DEVICE_ATTR_RO(direction);
140708e7e0adSLars-Peter Clausen 
14089eeee3b0SMihail Chindris /*
14099eeee3b0SMihail Chindris  * When adding new attributes here, put the at the end, at least until
14109eeee3b0SMihail Chindris  * the code that handles the length/length_ro & watermark/watermark_ro
14119eeee3b0SMihail Chindris  * assignments gets cleaned up. Otherwise these can create some weird
14129eeee3b0SMihail Chindris  * duplicate attributes errors under some setups.
14139eeee3b0SMihail Chindris  */
14146da9b382SOctavian Purdila static struct attribute *iio_buffer_attrs[] = {
14156da9b382SOctavian Purdila 	&dev_attr_length.attr,
14166da9b382SOctavian Purdila 	&dev_attr_enable.attr,
141737d34556SJosselin Costanzi 	&dev_attr_watermark.attr,
1418350f6c75SMatt Fornero 	&dev_attr_data_available.attr,
14199eeee3b0SMihail Chindris 	&dev_attr_direction.attr,
14206da9b382SOctavian Purdila };
14216da9b382SOctavian Purdila 
142215097c7aSAlexandru Ardelean #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
142315097c7aSAlexandru Ardelean 
142415097c7aSAlexandru Ardelean static struct attribute *iio_buffer_wrap_attr(struct iio_buffer *buffer,
142515097c7aSAlexandru Ardelean 					      struct attribute *attr)
142615097c7aSAlexandru Ardelean {
142715097c7aSAlexandru Ardelean 	struct device_attribute *dattr = to_dev_attr(attr);
142815097c7aSAlexandru Ardelean 	struct iio_dev_attr *iio_attr;
142915097c7aSAlexandru Ardelean 
143015097c7aSAlexandru Ardelean 	iio_attr = kzalloc(sizeof(*iio_attr), GFP_KERNEL);
143115097c7aSAlexandru Ardelean 	if (!iio_attr)
143215097c7aSAlexandru Ardelean 		return NULL;
143315097c7aSAlexandru Ardelean 
143415097c7aSAlexandru Ardelean 	iio_attr->buffer = buffer;
143515097c7aSAlexandru Ardelean 	memcpy(&iio_attr->dev_attr, dattr, sizeof(iio_attr->dev_attr));
143615097c7aSAlexandru Ardelean 	iio_attr->dev_attr.attr.name = kstrdup_const(attr->name, GFP_KERNEL);
14372c0ad3f0SYang Yingliang 	if (!iio_attr->dev_attr.attr.name) {
14382c0ad3f0SYang Yingliang 		kfree(iio_attr);
14392c0ad3f0SYang Yingliang 		return NULL;
14402c0ad3f0SYang Yingliang 	}
14412c0ad3f0SYang Yingliang 
1442ca3e7d52SAlexandru Ardelean 	sysfs_attr_init(&iio_attr->dev_attr.attr);
144315097c7aSAlexandru Ardelean 
144415097c7aSAlexandru Ardelean 	list_add(&iio_attr->l, &buffer->buffer_attr_list);
144515097c7aSAlexandru Ardelean 
144615097c7aSAlexandru Ardelean 	return &iio_attr->dev_attr.attr;
144715097c7aSAlexandru Ardelean }
144815097c7aSAlexandru Ardelean 
1449d9a62574SAlexandru Ardelean static int iio_buffer_register_legacy_sysfs_groups(struct iio_dev *indio_dev,
1450d9a62574SAlexandru Ardelean 						   struct attribute **buffer_attrs,
1451d9a62574SAlexandru Ardelean 						   int buffer_attrcount,
1452d9a62574SAlexandru Ardelean 						   int scan_el_attrcount)
1453d9a62574SAlexandru Ardelean {
1454d9a62574SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1455d9a62574SAlexandru Ardelean 	struct attribute_group *group;
1456d9a62574SAlexandru Ardelean 	struct attribute **attrs;
1457d9a62574SAlexandru Ardelean 	int ret;
1458d9a62574SAlexandru Ardelean 
1459d9a62574SAlexandru Ardelean 	attrs = kcalloc(buffer_attrcount + 1, sizeof(*attrs), GFP_KERNEL);
1460d9a62574SAlexandru Ardelean 	if (!attrs)
1461d9a62574SAlexandru Ardelean 		return -ENOMEM;
1462d9a62574SAlexandru Ardelean 
1463d9a62574SAlexandru Ardelean 	memcpy(attrs, buffer_attrs, buffer_attrcount * sizeof(*attrs));
1464d9a62574SAlexandru Ardelean 
1465d9a62574SAlexandru Ardelean 	group = &iio_dev_opaque->legacy_buffer_group;
1466d9a62574SAlexandru Ardelean 	group->attrs = attrs;
1467d9a62574SAlexandru Ardelean 	group->name = "buffer";
1468d9a62574SAlexandru Ardelean 
1469d9a62574SAlexandru Ardelean 	ret = iio_device_register_sysfs_group(indio_dev, group);
1470d9a62574SAlexandru Ardelean 	if (ret)
1471d9a62574SAlexandru Ardelean 		goto error_free_buffer_attrs;
1472d9a62574SAlexandru Ardelean 
1473d9a62574SAlexandru Ardelean 	attrs = kcalloc(scan_el_attrcount + 1, sizeof(*attrs), GFP_KERNEL);
1474d9a62574SAlexandru Ardelean 	if (!attrs) {
1475d9a62574SAlexandru Ardelean 		ret = -ENOMEM;
1476d9a62574SAlexandru Ardelean 		goto error_free_buffer_attrs;
1477d9a62574SAlexandru Ardelean 	}
1478d9a62574SAlexandru Ardelean 
1479d9a62574SAlexandru Ardelean 	memcpy(attrs, &buffer_attrs[buffer_attrcount],
1480d9a62574SAlexandru Ardelean 	       scan_el_attrcount * sizeof(*attrs));
1481d9a62574SAlexandru Ardelean 
1482d9a62574SAlexandru Ardelean 	group = &iio_dev_opaque->legacy_scan_el_group;
1483d9a62574SAlexandru Ardelean 	group->attrs = attrs;
1484d9a62574SAlexandru Ardelean 	group->name = "scan_elements";
1485d9a62574SAlexandru Ardelean 
1486d9a62574SAlexandru Ardelean 	ret = iio_device_register_sysfs_group(indio_dev, group);
1487d9a62574SAlexandru Ardelean 	if (ret)
1488d9a62574SAlexandru Ardelean 		goto error_free_scan_el_attrs;
1489d9a62574SAlexandru Ardelean 
1490d9a62574SAlexandru Ardelean 	return 0;
1491d9a62574SAlexandru Ardelean 
1492d9a62574SAlexandru Ardelean error_free_scan_el_attrs:
1493d9a62574SAlexandru Ardelean 	kfree(iio_dev_opaque->legacy_scan_el_group.attrs);
1494604faf9aSYang Yingliang error_free_buffer_attrs:
1495604faf9aSYang Yingliang 	kfree(iio_dev_opaque->legacy_buffer_group.attrs);
1496d9a62574SAlexandru Ardelean 
1497d9a62574SAlexandru Ardelean 	return ret;
1498d9a62574SAlexandru Ardelean }
1499d9a62574SAlexandru Ardelean 
1500d9a62574SAlexandru Ardelean static void iio_buffer_unregister_legacy_sysfs_groups(struct iio_dev *indio_dev)
1501d9a62574SAlexandru Ardelean {
1502d9a62574SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1503d9a62574SAlexandru Ardelean 
1504d9a62574SAlexandru Ardelean 	kfree(iio_dev_opaque->legacy_buffer_group.attrs);
1505d9a62574SAlexandru Ardelean 	kfree(iio_dev_opaque->legacy_scan_el_group.attrs);
1506d9a62574SAlexandru Ardelean }
1507d9a62574SAlexandru Ardelean 
1508f73f7f4dSAlexandru Ardelean static int iio_buffer_chrdev_release(struct inode *inode, struct file *filep)
1509f73f7f4dSAlexandru Ardelean {
1510f73f7f4dSAlexandru Ardelean 	struct iio_dev_buffer_pair *ib = filep->private_data;
1511f73f7f4dSAlexandru Ardelean 	struct iio_dev *indio_dev = ib->indio_dev;
1512f73f7f4dSAlexandru Ardelean 	struct iio_buffer *buffer = ib->buffer;
1513f73f7f4dSAlexandru Ardelean 
1514f73f7f4dSAlexandru Ardelean 	wake_up(&buffer->pollq);
1515f73f7f4dSAlexandru Ardelean 
1516f73f7f4dSAlexandru Ardelean 	kfree(ib);
1517f73f7f4dSAlexandru Ardelean 	clear_bit(IIO_BUSY_BIT_POS, &buffer->flags);
1518f73f7f4dSAlexandru Ardelean 	iio_device_put(indio_dev);
1519f73f7f4dSAlexandru Ardelean 
1520f73f7f4dSAlexandru Ardelean 	return 0;
1521f73f7f4dSAlexandru Ardelean }
1522f73f7f4dSAlexandru Ardelean 
1523f73f7f4dSAlexandru Ardelean static const struct file_operations iio_buffer_chrdev_fileops = {
1524f73f7f4dSAlexandru Ardelean 	.owner = THIS_MODULE,
1525f73f7f4dSAlexandru Ardelean 	.llseek = noop_llseek,
1526f73f7f4dSAlexandru Ardelean 	.read = iio_buffer_read,
15279eeee3b0SMihail Chindris 	.write = iio_buffer_write,
1528f73f7f4dSAlexandru Ardelean 	.poll = iio_buffer_poll,
1529f73f7f4dSAlexandru Ardelean 	.release = iio_buffer_chrdev_release,
1530f73f7f4dSAlexandru Ardelean };
1531f73f7f4dSAlexandru Ardelean 
1532f73f7f4dSAlexandru Ardelean static long iio_device_buffer_getfd(struct iio_dev *indio_dev, unsigned long arg)
1533f73f7f4dSAlexandru Ardelean {
1534f73f7f4dSAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1535f73f7f4dSAlexandru Ardelean 	int __user *ival = (int __user *)arg;
1536f73f7f4dSAlexandru Ardelean 	struct iio_dev_buffer_pair *ib;
1537f73f7f4dSAlexandru Ardelean 	struct iio_buffer *buffer;
1538f73f7f4dSAlexandru Ardelean 	int fd, idx, ret;
1539f73f7f4dSAlexandru Ardelean 
1540f73f7f4dSAlexandru Ardelean 	if (copy_from_user(&idx, ival, sizeof(idx)))
1541f73f7f4dSAlexandru Ardelean 		return -EFAULT;
1542f73f7f4dSAlexandru Ardelean 
1543f73f7f4dSAlexandru Ardelean 	if (idx >= iio_dev_opaque->attached_buffers_cnt)
1544f73f7f4dSAlexandru Ardelean 		return -ENODEV;
1545f73f7f4dSAlexandru Ardelean 
1546f73f7f4dSAlexandru Ardelean 	iio_device_get(indio_dev);
1547f73f7f4dSAlexandru Ardelean 
1548f73f7f4dSAlexandru Ardelean 	buffer = iio_dev_opaque->attached_buffers[idx];
1549f73f7f4dSAlexandru Ardelean 
1550f73f7f4dSAlexandru Ardelean 	if (test_and_set_bit(IIO_BUSY_BIT_POS, &buffer->flags)) {
1551f73f7f4dSAlexandru Ardelean 		ret = -EBUSY;
1552f73f7f4dSAlexandru Ardelean 		goto error_iio_dev_put;
1553f73f7f4dSAlexandru Ardelean 	}
1554f73f7f4dSAlexandru Ardelean 
1555f73f7f4dSAlexandru Ardelean 	ib = kzalloc(sizeof(*ib), GFP_KERNEL);
1556f73f7f4dSAlexandru Ardelean 	if (!ib) {
1557f73f7f4dSAlexandru Ardelean 		ret = -ENOMEM;
1558f73f7f4dSAlexandru Ardelean 		goto error_clear_busy_bit;
1559f73f7f4dSAlexandru Ardelean 	}
1560f73f7f4dSAlexandru Ardelean 
1561f73f7f4dSAlexandru Ardelean 	ib->indio_dev = indio_dev;
1562f73f7f4dSAlexandru Ardelean 	ib->buffer = buffer;
1563f73f7f4dSAlexandru Ardelean 
1564f73f7f4dSAlexandru Ardelean 	fd = anon_inode_getfd("iio:buffer", &iio_buffer_chrdev_fileops,
1565f73f7f4dSAlexandru Ardelean 			      ib, O_RDWR | O_CLOEXEC);
1566f73f7f4dSAlexandru Ardelean 	if (fd < 0) {
1567f73f7f4dSAlexandru Ardelean 		ret = fd;
1568f73f7f4dSAlexandru Ardelean 		goto error_free_ib;
1569f73f7f4dSAlexandru Ardelean 	}
1570f73f7f4dSAlexandru Ardelean 
1571f73f7f4dSAlexandru Ardelean 	if (copy_to_user(ival, &fd, sizeof(fd))) {
1572*c72ea205SMathias Krause 		/*
1573*c72ea205SMathias Krause 		 * "Leak" the fd, as there's not much we can do about this
1574*c72ea205SMathias Krause 		 * anyway. 'fd' might have been closed already, as
1575*c72ea205SMathias Krause 		 * anon_inode_getfd() called fd_install() on it, which made
1576*c72ea205SMathias Krause 		 * it reachable by userland.
1577*c72ea205SMathias Krause 		 *
1578*c72ea205SMathias Krause 		 * Instead of allowing a malicious user to play tricks with
1579*c72ea205SMathias Krause 		 * us, rely on the process exit path to do any necessary
1580*c72ea205SMathias Krause 		 * cleanup, as in releasing the file, if still needed.
1581*c72ea205SMathias Krause 		 */
1582*c72ea205SMathias Krause 		return -EFAULT;
1583f73f7f4dSAlexandru Ardelean 	}
1584f73f7f4dSAlexandru Ardelean 
15854c822244SAlexandru Ardelean 	return 0;
1586f73f7f4dSAlexandru Ardelean 
1587f73f7f4dSAlexandru Ardelean error_free_ib:
1588f73f7f4dSAlexandru Ardelean 	kfree(ib);
1589f73f7f4dSAlexandru Ardelean error_clear_busy_bit:
1590f73f7f4dSAlexandru Ardelean 	clear_bit(IIO_BUSY_BIT_POS, &buffer->flags);
1591f73f7f4dSAlexandru Ardelean error_iio_dev_put:
1592f73f7f4dSAlexandru Ardelean 	iio_device_put(indio_dev);
1593f73f7f4dSAlexandru Ardelean 	return ret;
1594f73f7f4dSAlexandru Ardelean }
1595f73f7f4dSAlexandru Ardelean 
1596f73f7f4dSAlexandru Ardelean static long iio_device_buffer_ioctl(struct iio_dev *indio_dev, struct file *filp,
1597f73f7f4dSAlexandru Ardelean 				    unsigned int cmd, unsigned long arg)
1598f73f7f4dSAlexandru Ardelean {
1599f73f7f4dSAlexandru Ardelean 	switch (cmd) {
1600f73f7f4dSAlexandru Ardelean 	case IIO_BUFFER_GET_FD_IOCTL:
1601f73f7f4dSAlexandru Ardelean 		return iio_device_buffer_getfd(indio_dev, arg);
1602f73f7f4dSAlexandru Ardelean 	default:
1603f73f7f4dSAlexandru Ardelean 		return IIO_IOCTL_UNHANDLED;
1604f73f7f4dSAlexandru Ardelean 	}
1605f73f7f4dSAlexandru Ardelean }
1606f73f7f4dSAlexandru Ardelean 
1607e16e0a77SAlexandru Ardelean static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
1608d9a62574SAlexandru Ardelean 					     struct iio_dev *indio_dev,
1609d9a62574SAlexandru Ardelean 					     int index)
1610d967cb6bSLars-Peter Clausen {
161162f4f36cSJonathan Cameron 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1612d967cb6bSLars-Peter Clausen 	struct iio_dev_attr *p;
1613d967cb6bSLars-Peter Clausen 	struct attribute **attr;
1614e2b4d7acSAlexandru Ardelean 	int ret, i, attrn, scan_el_attrcount, buffer_attrcount;
1615d967cb6bSLars-Peter Clausen 	const struct iio_chan_spec *channels;
1616d967cb6bSLars-Peter Clausen 
1617e2b4d7acSAlexandru Ardelean 	buffer_attrcount = 0;
161808e7e0adSLars-Peter Clausen 	if (buffer->attrs) {
1619e2b4d7acSAlexandru Ardelean 		while (buffer->attrs[buffer_attrcount] != NULL)
1620e2b4d7acSAlexandru Ardelean 			buffer_attrcount++;
162108e7e0adSLars-Peter Clausen 	}
162208e7e0adSLars-Peter Clausen 
1623e2b4d7acSAlexandru Ardelean 	scan_el_attrcount = 0;
162415097c7aSAlexandru Ardelean 	INIT_LIST_HEAD(&buffer->buffer_attr_list);
1625d967cb6bSLars-Peter Clausen 	channels = indio_dev->channels;
1626d967cb6bSLars-Peter Clausen 	if (channels) {
1627d967cb6bSLars-Peter Clausen 		/* new magic */
1628d967cb6bSLars-Peter Clausen 		for (i = 0; i < indio_dev->num_channels; i++) {
1629d967cb6bSLars-Peter Clausen 			if (channels[i].scan_index < 0)
1630d967cb6bSLars-Peter Clausen 				continue;
1631d967cb6bSLars-Peter Clausen 
1632ff3f7e04SAlexandru Ardelean 			ret = iio_buffer_add_channel_sysfs(indio_dev, buffer,
1633d967cb6bSLars-Peter Clausen 							 &channels[i]);
1634d967cb6bSLars-Peter Clausen 			if (ret < 0)
1635d967cb6bSLars-Peter Clausen 				goto error_cleanup_dynamic;
1636e2b4d7acSAlexandru Ardelean 			scan_el_attrcount += ret;
1637d967cb6bSLars-Peter Clausen 			if (channels[i].type == IIO_TIMESTAMP)
163862f4f36cSJonathan Cameron 				iio_dev_opaque->scan_index_timestamp =
1639d967cb6bSLars-Peter Clausen 					channels[i].scan_index;
1640d967cb6bSLars-Peter Clausen 		}
1641d967cb6bSLars-Peter Clausen 		if (indio_dev->masklength && buffer->scan_mask == NULL) {
16423862828aSAndy Shevchenko 			buffer->scan_mask = bitmap_zalloc(indio_dev->masklength,
1643d967cb6bSLars-Peter Clausen 							  GFP_KERNEL);
1644d967cb6bSLars-Peter Clausen 			if (buffer->scan_mask == NULL) {
1645d967cb6bSLars-Peter Clausen 				ret = -ENOMEM;
1646d967cb6bSLars-Peter Clausen 				goto error_cleanup_dynamic;
1647d967cb6bSLars-Peter Clausen 			}
1648d967cb6bSLars-Peter Clausen 		}
1649d967cb6bSLars-Peter Clausen 	}
1650d967cb6bSLars-Peter Clausen 
1651d9a62574SAlexandru Ardelean 	attrn = buffer_attrcount + scan_el_attrcount + ARRAY_SIZE(iio_buffer_attrs);
1652d9a62574SAlexandru Ardelean 	attr = kcalloc(attrn + 1, sizeof(* attr), GFP_KERNEL);
1653e2b4d7acSAlexandru Ardelean 	if (!attr) {
1654e2b4d7acSAlexandru Ardelean 		ret = -ENOMEM;
1655e2b4d7acSAlexandru Ardelean 		goto error_free_scan_mask;
1656e2b4d7acSAlexandru Ardelean 	}
1657e2b4d7acSAlexandru Ardelean 
1658e2b4d7acSAlexandru Ardelean 	memcpy(attr, iio_buffer_attrs, sizeof(iio_buffer_attrs));
1659e2b4d7acSAlexandru Ardelean 	if (!buffer->access->set_length)
1660e2b4d7acSAlexandru Ardelean 		attr[0] = &dev_attr_length_ro.attr;
1661e2b4d7acSAlexandru Ardelean 
1662e2b4d7acSAlexandru Ardelean 	if (buffer->access->flags & INDIO_BUFFER_FLAG_FIXED_WATERMARK)
1663e2b4d7acSAlexandru Ardelean 		attr[2] = &dev_attr_watermark_ro.attr;
1664e2b4d7acSAlexandru Ardelean 
1665e2b4d7acSAlexandru Ardelean 	if (buffer->attrs)
1666e2b4d7acSAlexandru Ardelean 		memcpy(&attr[ARRAY_SIZE(iio_buffer_attrs)], buffer->attrs,
1667e2b4d7acSAlexandru Ardelean 		       sizeof(struct attribute *) * buffer_attrcount);
1668e2b4d7acSAlexandru Ardelean 
1669e2b4d7acSAlexandru Ardelean 	buffer_attrcount += ARRAY_SIZE(iio_buffer_attrs);
16709a2ff800SYang Yingliang 	buffer->buffer_group.attrs = attr;
1671e2b4d7acSAlexandru Ardelean 
167215097c7aSAlexandru Ardelean 	for (i = 0; i < buffer_attrcount; i++) {
167315097c7aSAlexandru Ardelean 		struct attribute *wrapped;
1674d9a62574SAlexandru Ardelean 
167515097c7aSAlexandru Ardelean 		wrapped = iio_buffer_wrap_attr(buffer, attr[i]);
167615097c7aSAlexandru Ardelean 		if (!wrapped) {
167715097c7aSAlexandru Ardelean 			ret = -ENOMEM;
16789a2ff800SYang Yingliang 			goto error_free_buffer_attrs;
167915097c7aSAlexandru Ardelean 		}
168015097c7aSAlexandru Ardelean 		attr[i] = wrapped;
168115097c7aSAlexandru Ardelean 	}
168215097c7aSAlexandru Ardelean 
168315097c7aSAlexandru Ardelean 	attrn = 0;
168415097c7aSAlexandru Ardelean 	list_for_each_entry(p, &buffer->buffer_attr_list, l)
1685d9a62574SAlexandru Ardelean 		attr[attrn++] = &p->dev_attr.attr;
1686d9a62574SAlexandru Ardelean 
1687d9a62574SAlexandru Ardelean 	buffer->buffer_group.name = kasprintf(GFP_KERNEL, "buffer%d", index);
1688d9a62574SAlexandru Ardelean 	if (!buffer->buffer_group.name) {
1689d9a62574SAlexandru Ardelean 		ret = -ENOMEM;
1690d9a62574SAlexandru Ardelean 		goto error_free_buffer_attrs;
1691d9a62574SAlexandru Ardelean 	}
1692d9a62574SAlexandru Ardelean 
1693e2b4d7acSAlexandru Ardelean 	ret = iio_device_register_sysfs_group(indio_dev, &buffer->buffer_group);
1694e2b4d7acSAlexandru Ardelean 	if (ret)
1695d9a62574SAlexandru Ardelean 		goto error_free_buffer_attr_group_name;
1696e2b4d7acSAlexandru Ardelean 
1697d9a62574SAlexandru Ardelean 	/* we only need to register the legacy groups for the first buffer */
1698d9a62574SAlexandru Ardelean 	if (index > 0)
1699d9a62574SAlexandru Ardelean 		return 0;
1700d967cb6bSLars-Peter Clausen 
1701d9a62574SAlexandru Ardelean 	ret = iio_buffer_register_legacy_sysfs_groups(indio_dev, attr,
1702d9a62574SAlexandru Ardelean 						      buffer_attrcount,
1703d9a62574SAlexandru Ardelean 						      scan_el_attrcount);
170432f17172SAlexandru Ardelean 	if (ret)
1705d9a62574SAlexandru Ardelean 		goto error_free_buffer_attr_group_name;
1706d967cb6bSLars-Peter Clausen 
1707d967cb6bSLars-Peter Clausen 	return 0;
1708d967cb6bSLars-Peter Clausen 
1709d9a62574SAlexandru Ardelean error_free_buffer_attr_group_name:
1710d9a62574SAlexandru Ardelean 	kfree(buffer->buffer_group.name);
1711e2b4d7acSAlexandru Ardelean error_free_buffer_attrs:
1712e2b4d7acSAlexandru Ardelean 	kfree(buffer->buffer_group.attrs);
1713d967cb6bSLars-Peter Clausen error_free_scan_mask:
17143862828aSAndy Shevchenko 	bitmap_free(buffer->scan_mask);
1715d967cb6bSLars-Peter Clausen error_cleanup_dynamic:
171615097c7aSAlexandru Ardelean 	iio_free_chan_devattr_list(&buffer->buffer_attr_list);
1717d967cb6bSLars-Peter Clausen 
1718d967cb6bSLars-Peter Clausen 	return ret;
1719d967cb6bSLars-Peter Clausen }
1720d967cb6bSLars-Peter Clausen 
1721486a2508SYang Yingliang static void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer,
1722486a2508SYang Yingliang 					     struct iio_dev *indio_dev,
1723486a2508SYang Yingliang 					     int index)
17240224af85SAlexandru Ardelean {
1725486a2508SYang Yingliang 	if (index == 0)
1726486a2508SYang Yingliang 		iio_buffer_unregister_legacy_sysfs_groups(indio_dev);
17270224af85SAlexandru Ardelean 	bitmap_free(buffer->scan_mask);
17280224af85SAlexandru Ardelean 	kfree(buffer->buffer_group.name);
17290224af85SAlexandru Ardelean 	kfree(buffer->buffer_group.attrs);
17300224af85SAlexandru Ardelean 	iio_free_chan_devattr_list(&buffer->buffer_attr_list);
17310224af85SAlexandru Ardelean }
17320224af85SAlexandru Ardelean 
1733ee708e6bSAlexandru Ardelean int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
1734e16e0a77SAlexandru Ardelean {
1735ee708e6bSAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1736e16e0a77SAlexandru Ardelean 	const struct iio_chan_spec *channels;
1737ee708e6bSAlexandru Ardelean 	struct iio_buffer *buffer;
1738e5cc9840SAndy Shevchenko 	int ret, i, idx;
1739f73f7f4dSAlexandru Ardelean 	size_t sz;
1740e16e0a77SAlexandru Ardelean 
1741e16e0a77SAlexandru Ardelean 	channels = indio_dev->channels;
1742e16e0a77SAlexandru Ardelean 	if (channels) {
1743e16e0a77SAlexandru Ardelean 		int ml = indio_dev->masklength;
1744e16e0a77SAlexandru Ardelean 
1745e16e0a77SAlexandru Ardelean 		for (i = 0; i < indio_dev->num_channels; i++)
1746e16e0a77SAlexandru Ardelean 			ml = max(ml, channels[i].scan_index + 1);
1747e16e0a77SAlexandru Ardelean 		indio_dev->masklength = ml;
1748e16e0a77SAlexandru Ardelean 	}
1749e16e0a77SAlexandru Ardelean 
1750ee708e6bSAlexandru Ardelean 	if (!iio_dev_opaque->attached_buffers_cnt)
1751e16e0a77SAlexandru Ardelean 		return 0;
1752e16e0a77SAlexandru Ardelean 
1753e5cc9840SAndy Shevchenko 	for (idx = 0; idx < iio_dev_opaque->attached_buffers_cnt; idx++) {
1754e5cc9840SAndy Shevchenko 		buffer = iio_dev_opaque->attached_buffers[idx];
1755e5cc9840SAndy Shevchenko 		ret = __iio_buffer_alloc_sysfs_and_mask(buffer, indio_dev, idx);
1756e5cc9840SAndy Shevchenko 		if (ret)
1757ee708e6bSAlexandru Ardelean 			goto error_unwind_sysfs_and_mask;
1758ee708e6bSAlexandru Ardelean 	}
1759f73f7f4dSAlexandru Ardelean 
1760f73f7f4dSAlexandru Ardelean 	sz = sizeof(*(iio_dev_opaque->buffer_ioctl_handler));
1761f73f7f4dSAlexandru Ardelean 	iio_dev_opaque->buffer_ioctl_handler = kzalloc(sz, GFP_KERNEL);
1762f73f7f4dSAlexandru Ardelean 	if (!iio_dev_opaque->buffer_ioctl_handler) {
1763f73f7f4dSAlexandru Ardelean 		ret = -ENOMEM;
1764f73f7f4dSAlexandru Ardelean 		goto error_unwind_sysfs_and_mask;
1765f73f7f4dSAlexandru Ardelean 	}
1766f73f7f4dSAlexandru Ardelean 
1767f73f7f4dSAlexandru Ardelean 	iio_dev_opaque->buffer_ioctl_handler->ioctl = iio_device_buffer_ioctl;
1768f73f7f4dSAlexandru Ardelean 	iio_device_ioctl_handler_register(indio_dev,
1769f73f7f4dSAlexandru Ardelean 					  iio_dev_opaque->buffer_ioctl_handler);
1770e16e0a77SAlexandru Ardelean 
1771ee708e6bSAlexandru Ardelean 	return 0;
1772ff3f7e04SAlexandru Ardelean 
1773ee708e6bSAlexandru Ardelean error_unwind_sysfs_and_mask:
1774e5cc9840SAndy Shevchenko 	while (idx--) {
1775e5cc9840SAndy Shevchenko 		buffer = iio_dev_opaque->attached_buffers[idx];
1776e5cc9840SAndy Shevchenko 		__iio_buffer_free_sysfs_and_mask(buffer, indio_dev, idx);
1777ee708e6bSAlexandru Ardelean 	}
1778ee708e6bSAlexandru Ardelean 	return ret;
1779ee708e6bSAlexandru Ardelean }
1780ee708e6bSAlexandru Ardelean 
1781ee708e6bSAlexandru Ardelean void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev)
1782ee708e6bSAlexandru Ardelean {
1783ee708e6bSAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1784ee708e6bSAlexandru Ardelean 	struct iio_buffer *buffer;
1785ee708e6bSAlexandru Ardelean 	int i;
1786ee708e6bSAlexandru Ardelean 
1787ee708e6bSAlexandru Ardelean 	if (!iio_dev_opaque->attached_buffers_cnt)
1788d967cb6bSLars-Peter Clausen 		return;
1789d967cb6bSLars-Peter Clausen 
1790f73f7f4dSAlexandru Ardelean 	iio_device_ioctl_handler_unregister(iio_dev_opaque->buffer_ioctl_handler);
1791f73f7f4dSAlexandru Ardelean 	kfree(iio_dev_opaque->buffer_ioctl_handler);
1792f73f7f4dSAlexandru Ardelean 
1793ee708e6bSAlexandru Ardelean 	for (i = iio_dev_opaque->attached_buffers_cnt - 1; i >= 0; i--) {
1794ee708e6bSAlexandru Ardelean 		buffer = iio_dev_opaque->attached_buffers[i];
1795486a2508SYang Yingliang 		__iio_buffer_free_sysfs_and_mask(buffer, indio_dev, i);
1796d967cb6bSLars-Peter Clausen 	}
1797ee708e6bSAlexandru Ardelean }
1798ee708e6bSAlexandru Ardelean 
1799a980e046SJonathan Cameron /**
180081636632SLars-Peter Clausen  * iio_validate_scan_mask_onehot() - Validates that exactly one channel is selected
180181636632SLars-Peter Clausen  * @indio_dev: the iio device
180281636632SLars-Peter Clausen  * @mask: scan mask to be checked
180381636632SLars-Peter Clausen  *
180481636632SLars-Peter Clausen  * Return true if exactly one bit is set in the scan mask, false otherwise. It
180581636632SLars-Peter Clausen  * can be used for devices where only one channel can be active for sampling at
180681636632SLars-Peter Clausen  * a time.
180781636632SLars-Peter Clausen  */
180881636632SLars-Peter Clausen bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev,
180981636632SLars-Peter Clausen 	const unsigned long *mask)
181081636632SLars-Peter Clausen {
181181636632SLars-Peter Clausen 	return bitmap_weight(mask, indio_dev->masklength) == 1;
181281636632SLars-Peter Clausen }
181381636632SLars-Peter Clausen EXPORT_SYMBOL_GPL(iio_validate_scan_mask_onehot);
181481636632SLars-Peter Clausen 
18155d65d920SLars-Peter Clausen static const void *iio_demux(struct iio_buffer *buffer,
18165d65d920SLars-Peter Clausen 				 const void *datain)
1817a980e046SJonathan Cameron {
1818a980e046SJonathan Cameron 	struct iio_demux_table *t;
1819a980e046SJonathan Cameron 
1820a980e046SJonathan Cameron 	if (list_empty(&buffer->demux_list))
1821a980e046SJonathan Cameron 		return datain;
1822a980e046SJonathan Cameron 	list_for_each_entry(t, &buffer->demux_list, l)
1823a980e046SJonathan Cameron 		memcpy(buffer->demux_bounce + t->to,
1824a980e046SJonathan Cameron 		       datain + t->from, t->length);
1825a980e046SJonathan Cameron 
1826a980e046SJonathan Cameron 	return buffer->demux_bounce;
1827a980e046SJonathan Cameron }
1828a980e046SJonathan Cameron 
18295d65d920SLars-Peter Clausen static int iio_push_to_buffer(struct iio_buffer *buffer, const void *data)
1830a980e046SJonathan Cameron {
18315d65d920SLars-Peter Clausen 	const void *dataout = iio_demux(buffer, data);
183237d34556SJosselin Costanzi 	int ret;
1833a980e046SJonathan Cameron 
183437d34556SJosselin Costanzi 	ret = buffer->access->store_to(buffer, dataout);
183537d34556SJosselin Costanzi 	if (ret)
183637d34556SJosselin Costanzi 		return ret;
183737d34556SJosselin Costanzi 
183837d34556SJosselin Costanzi 	/*
183937d34556SJosselin Costanzi 	 * We can't just test for watermark to decide if we wake the poll queue
184037d34556SJosselin Costanzi 	 * because read may request less samples than the watermark.
184137d34556SJosselin Costanzi 	 */
1842a9a08845SLinus Torvalds 	wake_up_interruptible_poll(&buffer->pollq, EPOLLIN | EPOLLRDNORM);
184337d34556SJosselin Costanzi 	return 0;
1844a980e046SJonathan Cameron }
1845a980e046SJonathan Cameron 
1846315a19ecSJonathan Cameron /**
1847315a19ecSJonathan Cameron  * iio_push_to_buffers() - push to a registered buffer.
1848315a19ecSJonathan Cameron  * @indio_dev:		iio_dev structure for device.
1849315a19ecSJonathan Cameron  * @data:		Full scan.
1850315a19ecSJonathan Cameron  */
18515d65d920SLars-Peter Clausen int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data)
185284b36ce5SJonathan Cameron {
18536a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
185484b36ce5SJonathan Cameron 	int ret;
185584b36ce5SJonathan Cameron 	struct iio_buffer *buf;
185684b36ce5SJonathan Cameron 
18576a8c6b26SAlexandru Ardelean 	list_for_each_entry(buf, &iio_dev_opaque->buffer_list, buffer_list) {
185884b36ce5SJonathan Cameron 		ret = iio_push_to_buffer(buf, data);
185984b36ce5SJonathan Cameron 		if (ret < 0)
186084b36ce5SJonathan Cameron 			return ret;
186184b36ce5SJonathan Cameron 	}
186284b36ce5SJonathan Cameron 
186384b36ce5SJonathan Cameron 	return 0;
186484b36ce5SJonathan Cameron }
186584b36ce5SJonathan Cameron EXPORT_SYMBOL_GPL(iio_push_to_buffers);
186684b36ce5SJonathan Cameron 
18679e69c935SLars-Peter Clausen /**
186895ec3fdfSJonathan Cameron  * iio_push_to_buffers_with_ts_unaligned() - push to registered buffer,
186995ec3fdfSJonathan Cameron  *    no alignment or space requirements.
187095ec3fdfSJonathan Cameron  * @indio_dev:		iio_dev structure for device.
187195ec3fdfSJonathan Cameron  * @data:		channel data excluding the timestamp.
187295ec3fdfSJonathan Cameron  * @data_sz:		size of data.
187395ec3fdfSJonathan Cameron  * @timestamp:		timestamp for the sample data.
187495ec3fdfSJonathan Cameron  *
187595ec3fdfSJonathan Cameron  * This special variant of iio_push_to_buffers_with_timestamp() does
187695ec3fdfSJonathan Cameron  * not require space for the timestamp, or 8 byte alignment of data.
187795ec3fdfSJonathan Cameron  * It does however require an allocation on first call and additional
187895ec3fdfSJonathan Cameron  * copies on all calls, so should be avoided if possible.
187995ec3fdfSJonathan Cameron  */
188095ec3fdfSJonathan Cameron int iio_push_to_buffers_with_ts_unaligned(struct iio_dev *indio_dev,
188195ec3fdfSJonathan Cameron 					  const void *data,
188295ec3fdfSJonathan Cameron 					  size_t data_sz,
188395ec3fdfSJonathan Cameron 					  int64_t timestamp)
188495ec3fdfSJonathan Cameron {
188595ec3fdfSJonathan Cameron 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
188695ec3fdfSJonathan Cameron 
188795ec3fdfSJonathan Cameron 	/*
188895ec3fdfSJonathan Cameron 	 * Conservative estimate - we can always safely copy the minimum
188995ec3fdfSJonathan Cameron 	 * of either the data provided or the length of the destination buffer.
189095ec3fdfSJonathan Cameron 	 * This relaxed limit allows the calling drivers to be lax about
189195ec3fdfSJonathan Cameron 	 * tracking the size of the data they are pushing, at the cost of
189295ec3fdfSJonathan Cameron 	 * unnecessary copying of padding.
189395ec3fdfSJonathan Cameron 	 */
189495ec3fdfSJonathan Cameron 	data_sz = min_t(size_t, indio_dev->scan_bytes, data_sz);
189595ec3fdfSJonathan Cameron 	if (iio_dev_opaque->bounce_buffer_size !=  indio_dev->scan_bytes) {
189695ec3fdfSJonathan Cameron 		void *bb;
189795ec3fdfSJonathan Cameron 
189895ec3fdfSJonathan Cameron 		bb = devm_krealloc(&indio_dev->dev,
189995ec3fdfSJonathan Cameron 				   iio_dev_opaque->bounce_buffer,
190095ec3fdfSJonathan Cameron 				   indio_dev->scan_bytes, GFP_KERNEL);
190195ec3fdfSJonathan Cameron 		if (!bb)
190295ec3fdfSJonathan Cameron 			return -ENOMEM;
190395ec3fdfSJonathan Cameron 		iio_dev_opaque->bounce_buffer = bb;
190495ec3fdfSJonathan Cameron 		iio_dev_opaque->bounce_buffer_size = indio_dev->scan_bytes;
190595ec3fdfSJonathan Cameron 	}
190695ec3fdfSJonathan Cameron 	memcpy(iio_dev_opaque->bounce_buffer, data, data_sz);
190795ec3fdfSJonathan Cameron 	return iio_push_to_buffers_with_timestamp(indio_dev,
190895ec3fdfSJonathan Cameron 						  iio_dev_opaque->bounce_buffer,
190995ec3fdfSJonathan Cameron 						  timestamp);
191095ec3fdfSJonathan Cameron }
191195ec3fdfSJonathan Cameron EXPORT_SYMBOL_GPL(iio_push_to_buffers_with_ts_unaligned);
191295ec3fdfSJonathan Cameron 
191395ec3fdfSJonathan Cameron /**
19149e69c935SLars-Peter Clausen  * iio_buffer_release() - Free a buffer's resources
19159e69c935SLars-Peter Clausen  * @ref: Pointer to the kref embedded in the iio_buffer struct
19169e69c935SLars-Peter Clausen  *
19179e69c935SLars-Peter Clausen  * This function is called when the last reference to the buffer has been
19189e69c935SLars-Peter Clausen  * dropped. It will typically free all resources allocated by the buffer. Do not
19199e69c935SLars-Peter Clausen  * call this function manually, always use iio_buffer_put() when done using a
19209e69c935SLars-Peter Clausen  * buffer.
19219e69c935SLars-Peter Clausen  */
19229e69c935SLars-Peter Clausen static void iio_buffer_release(struct kref *ref)
19239e69c935SLars-Peter Clausen {
19249e69c935SLars-Peter Clausen 	struct iio_buffer *buffer = container_of(ref, struct iio_buffer, ref);
19259e69c935SLars-Peter Clausen 
19269e69c935SLars-Peter Clausen 	buffer->access->release(buffer);
19279e69c935SLars-Peter Clausen }
19289e69c935SLars-Peter Clausen 
19299e69c935SLars-Peter Clausen /**
19309e69c935SLars-Peter Clausen  * iio_buffer_get() - Grab a reference to the buffer
19319e69c935SLars-Peter Clausen  * @buffer: The buffer to grab a reference for, may be NULL
19329e69c935SLars-Peter Clausen  *
19339e69c935SLars-Peter Clausen  * Returns the pointer to the buffer that was passed into the function.
19349e69c935SLars-Peter Clausen  */
19359e69c935SLars-Peter Clausen struct iio_buffer *iio_buffer_get(struct iio_buffer *buffer)
19369e69c935SLars-Peter Clausen {
19379e69c935SLars-Peter Clausen 	if (buffer)
19389e69c935SLars-Peter Clausen 		kref_get(&buffer->ref);
19399e69c935SLars-Peter Clausen 
19409e69c935SLars-Peter Clausen 	return buffer;
19419e69c935SLars-Peter Clausen }
19429e69c935SLars-Peter Clausen EXPORT_SYMBOL_GPL(iio_buffer_get);
19439e69c935SLars-Peter Clausen 
19449e69c935SLars-Peter Clausen /**
19459e69c935SLars-Peter Clausen  * iio_buffer_put() - Release the reference to the buffer
19469e69c935SLars-Peter Clausen  * @buffer: The buffer to release the reference for, may be NULL
19479e69c935SLars-Peter Clausen  */
19489e69c935SLars-Peter Clausen void iio_buffer_put(struct iio_buffer *buffer)
19499e69c935SLars-Peter Clausen {
19509e69c935SLars-Peter Clausen 	if (buffer)
19519e69c935SLars-Peter Clausen 		kref_put(&buffer->ref, iio_buffer_release);
19529e69c935SLars-Peter Clausen }
19539e69c935SLars-Peter Clausen EXPORT_SYMBOL_GPL(iio_buffer_put);
19542b827ad5SJonathan Cameron 
19552b827ad5SJonathan Cameron /**
19562b827ad5SJonathan Cameron  * iio_device_attach_buffer - Attach a buffer to a IIO device
19572b827ad5SJonathan Cameron  * @indio_dev: The device the buffer should be attached to
19582b827ad5SJonathan Cameron  * @buffer: The buffer to attach to the device
19592b827ad5SJonathan Cameron  *
1960ee708e6bSAlexandru Ardelean  * Return 0 if successful, negative if error.
1961ee708e6bSAlexandru Ardelean  *
19622b827ad5SJonathan Cameron  * This function attaches a buffer to a IIO device. The buffer stays attached to
1963ee708e6bSAlexandru Ardelean  * the device until the device is freed. For legacy reasons, the first attached
1964ee708e6bSAlexandru Ardelean  * buffer will also be assigned to 'indio_dev->buffer'.
1965218bc53dSAlexandru Ardelean  * The array allocated here, will be free'd via the iio_device_detach_buffers()
1966218bc53dSAlexandru Ardelean  * call which is handled by the iio_device_free().
19672b827ad5SJonathan Cameron  */
1968ee708e6bSAlexandru Ardelean int iio_device_attach_buffer(struct iio_dev *indio_dev,
19692b827ad5SJonathan Cameron 			     struct iio_buffer *buffer)
19702b827ad5SJonathan Cameron {
1971ee708e6bSAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1972ee708e6bSAlexandru Ardelean 	struct iio_buffer **new, **old = iio_dev_opaque->attached_buffers;
1973ee708e6bSAlexandru Ardelean 	unsigned int cnt = iio_dev_opaque->attached_buffers_cnt;
1974ee708e6bSAlexandru Ardelean 
1975ee708e6bSAlexandru Ardelean 	cnt++;
1976ee708e6bSAlexandru Ardelean 
1977ee708e6bSAlexandru Ardelean 	new = krealloc(old, sizeof(*new) * cnt, GFP_KERNEL);
1978ee708e6bSAlexandru Ardelean 	if (!new)
1979ee708e6bSAlexandru Ardelean 		return -ENOMEM;
1980ee708e6bSAlexandru Ardelean 	iio_dev_opaque->attached_buffers = new;
1981ee708e6bSAlexandru Ardelean 
1982ee708e6bSAlexandru Ardelean 	buffer = iio_buffer_get(buffer);
1983ee708e6bSAlexandru Ardelean 
1984ee708e6bSAlexandru Ardelean 	/* first buffer is legacy; attach it to the IIO device directly */
1985ee708e6bSAlexandru Ardelean 	if (!indio_dev->buffer)
1986ee708e6bSAlexandru Ardelean 		indio_dev->buffer = buffer;
1987ee708e6bSAlexandru Ardelean 
1988ee708e6bSAlexandru Ardelean 	iio_dev_opaque->attached_buffers[cnt - 1] = buffer;
1989ee708e6bSAlexandru Ardelean 	iio_dev_opaque->attached_buffers_cnt = cnt;
1990ee708e6bSAlexandru Ardelean 
1991ee708e6bSAlexandru Ardelean 	return 0;
19922b827ad5SJonathan Cameron }
19932b827ad5SJonathan Cameron EXPORT_SYMBOL_GPL(iio_device_attach_buffer);
1994