xref: /openbmc/linux/drivers/iio/industrialio-buffer.c (revision 16afe125b53f88b855d2713c8ba253d905dcf3cc)
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);
510*16afe125SNuno Sá 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
511a980e046SJonathan Cameron 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
51215097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = this_attr->buffer;
513a980e046SJonathan Cameron 
51474f582ecSLars-Peter Clausen 	ret = kstrtobool(buf, &state);
515a980e046SJonathan Cameron 	if (ret < 0)
516a980e046SJonathan Cameron 		return ret;
517*16afe125SNuno Sá 	mutex_lock(&iio_dev_opaque->mlock);
518ff3f7e04SAlexandru Ardelean 	if (iio_buffer_is_active(buffer)) {
519a980e046SJonathan Cameron 		ret = -EBUSY;
520a980e046SJonathan Cameron 		goto error_ret;
521a980e046SJonathan Cameron 	}
522a980e046SJonathan Cameron 	ret = iio_scan_mask_query(indio_dev, buffer, this_attr->address);
523a980e046SJonathan Cameron 	if (ret < 0)
524a980e046SJonathan Cameron 		goto error_ret;
525a980e046SJonathan Cameron 	if (!state && ret) {
526a980e046SJonathan Cameron 		ret = iio_scan_mask_clear(buffer, this_attr->address);
527a980e046SJonathan Cameron 		if (ret)
528a980e046SJonathan Cameron 			goto error_ret;
529a980e046SJonathan Cameron 	} else if (state && !ret) {
530a980e046SJonathan Cameron 		ret = iio_scan_mask_set(indio_dev, buffer, this_attr->address);
531a980e046SJonathan Cameron 		if (ret)
532a980e046SJonathan Cameron 			goto error_ret;
533a980e046SJonathan Cameron 	}
534a980e046SJonathan Cameron 
535a980e046SJonathan Cameron error_ret:
536*16afe125SNuno Sá 	mutex_unlock(&iio_dev_opaque->mlock);
537a980e046SJonathan Cameron 
538a980e046SJonathan Cameron 	return ret < 0 ? ret : len;
539a980e046SJonathan Cameron 
540a980e046SJonathan Cameron }
541a980e046SJonathan Cameron 
542a980e046SJonathan Cameron static ssize_t iio_scan_el_ts_show(struct device *dev,
543a980e046SJonathan Cameron 				   struct device_attribute *attr,
544a980e046SJonathan Cameron 				   char *buf)
545a980e046SJonathan Cameron {
54615097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
547ff3f7e04SAlexandru Ardelean 
54883ca56b6SLars-Peter Clausen 	return sysfs_emit(buf, "%d\n", buffer->scan_timestamp);
549a980e046SJonathan Cameron }
550a980e046SJonathan Cameron 
551a980e046SJonathan Cameron static ssize_t iio_scan_el_ts_store(struct device *dev,
552a980e046SJonathan Cameron 				    struct device_attribute *attr,
553a980e046SJonathan Cameron 				    const char *buf,
554a980e046SJonathan Cameron 				    size_t len)
555a980e046SJonathan Cameron {
556a980e046SJonathan Cameron 	int ret;
557e53f5ac5SLars-Peter Clausen 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
558*16afe125SNuno Sá 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
55915097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
560a980e046SJonathan Cameron 	bool state;
561a980e046SJonathan Cameron 
56274f582ecSLars-Peter Clausen 	ret = kstrtobool(buf, &state);
563a980e046SJonathan Cameron 	if (ret < 0)
564a980e046SJonathan Cameron 		return ret;
565a980e046SJonathan Cameron 
566*16afe125SNuno Sá 	mutex_lock(&iio_dev_opaque->mlock);
567ff3f7e04SAlexandru Ardelean 	if (iio_buffer_is_active(buffer)) {
568a980e046SJonathan Cameron 		ret = -EBUSY;
569a980e046SJonathan Cameron 		goto error_ret;
570a980e046SJonathan Cameron 	}
571ff3f7e04SAlexandru Ardelean 	buffer->scan_timestamp = state;
572a980e046SJonathan Cameron error_ret:
573*16afe125SNuno Sá 	mutex_unlock(&iio_dev_opaque->mlock);
574a980e046SJonathan Cameron 
575a980e046SJonathan Cameron 	return ret ? ret : len;
576a980e046SJonathan Cameron }
577a980e046SJonathan Cameron 
578a980e046SJonathan Cameron static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
579ff3f7e04SAlexandru Ardelean 					struct iio_buffer *buffer,
580a980e046SJonathan Cameron 					const struct iio_chan_spec *chan)
581a980e046SJonathan Cameron {
582a980e046SJonathan Cameron 	int ret, attrcount = 0;
583a980e046SJonathan Cameron 
584a980e046SJonathan Cameron 	ret = __iio_add_chan_devattr("index",
585a980e046SJonathan Cameron 				     chan,
586a980e046SJonathan Cameron 				     &iio_show_scan_index,
587a980e046SJonathan Cameron 				     NULL,
588a980e046SJonathan Cameron 				     0,
5893704432fSJonathan Cameron 				     IIO_SEPARATE,
590a980e046SJonathan Cameron 				     &indio_dev->dev,
5913e3d11b2SAlexandru Ardelean 				     buffer,
59215097c7aSAlexandru Ardelean 				     &buffer->buffer_attr_list);
593a980e046SJonathan Cameron 	if (ret)
59492825ff9SHartmut Knaack 		return ret;
595a980e046SJonathan Cameron 	attrcount++;
596a980e046SJonathan Cameron 	ret = __iio_add_chan_devattr("type",
597a980e046SJonathan Cameron 				     chan,
598a980e046SJonathan Cameron 				     &iio_show_fixed_type,
599a980e046SJonathan Cameron 				     NULL,
600a980e046SJonathan Cameron 				     0,
601a980e046SJonathan Cameron 				     0,
602a980e046SJonathan Cameron 				     &indio_dev->dev,
6033e3d11b2SAlexandru Ardelean 				     buffer,
60415097c7aSAlexandru Ardelean 				     &buffer->buffer_attr_list);
605a980e046SJonathan Cameron 	if (ret)
60692825ff9SHartmut Knaack 		return ret;
607a980e046SJonathan Cameron 	attrcount++;
608a980e046SJonathan Cameron 	if (chan->type != IIO_TIMESTAMP)
609a980e046SJonathan Cameron 		ret = __iio_add_chan_devattr("en",
610a980e046SJonathan Cameron 					     chan,
611a980e046SJonathan Cameron 					     &iio_scan_el_show,
612a980e046SJonathan Cameron 					     &iio_scan_el_store,
613a980e046SJonathan Cameron 					     chan->scan_index,
614a980e046SJonathan Cameron 					     0,
615a980e046SJonathan Cameron 					     &indio_dev->dev,
6163e3d11b2SAlexandru Ardelean 					     buffer,
61715097c7aSAlexandru Ardelean 					     &buffer->buffer_attr_list);
618a980e046SJonathan Cameron 	else
619a980e046SJonathan Cameron 		ret = __iio_add_chan_devattr("en",
620a980e046SJonathan Cameron 					     chan,
621a980e046SJonathan Cameron 					     &iio_scan_el_ts_show,
622a980e046SJonathan Cameron 					     &iio_scan_el_ts_store,
623a980e046SJonathan Cameron 					     chan->scan_index,
624a980e046SJonathan Cameron 					     0,
625a980e046SJonathan Cameron 					     &indio_dev->dev,
6263e3d11b2SAlexandru Ardelean 					     buffer,
62715097c7aSAlexandru Ardelean 					     &buffer->buffer_attr_list);
6289572588cSPeter Meerwald 	if (ret)
62992825ff9SHartmut Knaack 		return ret;
630a980e046SJonathan Cameron 	attrcount++;
631a980e046SJonathan Cameron 	ret = attrcount;
632a980e046SJonathan Cameron 	return ret;
633a980e046SJonathan Cameron }
634a980e046SJonathan Cameron 
6359cf0b618SJoe Simmons-Talbott static ssize_t length_show(struct device *dev, struct device_attribute *attr,
636a980e046SJonathan Cameron 			   char *buf)
637a980e046SJonathan Cameron {
63815097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
639a980e046SJonathan Cameron 
64083ca56b6SLars-Peter Clausen 	return sysfs_emit(buf, "%d\n", buffer->length);
641a980e046SJonathan Cameron }
642a980e046SJonathan Cameron 
6439cf0b618SJoe Simmons-Talbott static ssize_t length_store(struct device *dev, 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);
647*16afe125SNuno Sá 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
64815097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
649948ad205SLars-Peter Clausen 	unsigned int val;
650948ad205SLars-Peter Clausen 	int ret;
651a980e046SJonathan Cameron 
652948ad205SLars-Peter Clausen 	ret = kstrtouint(buf, 10, &val);
653a980e046SJonathan Cameron 	if (ret)
654a980e046SJonathan Cameron 		return ret;
655a980e046SJonathan Cameron 
65637495660SLars-Peter Clausen 	if (val == buffer->length)
657a980e046SJonathan Cameron 		return len;
658a980e046SJonathan Cameron 
659*16afe125SNuno Sá 	mutex_lock(&iio_dev_opaque->mlock);
660ff3f7e04SAlexandru Ardelean 	if (iio_buffer_is_active(buffer)) {
661a980e046SJonathan Cameron 		ret = -EBUSY;
662a980e046SJonathan Cameron 	} else {
663a980e046SJonathan Cameron 		buffer->access->set_length(buffer, val);
664a980e046SJonathan Cameron 		ret = 0;
665a980e046SJonathan Cameron 	}
66637d34556SJosselin Costanzi 	if (ret)
66737d34556SJosselin Costanzi 		goto out;
66837d34556SJosselin Costanzi 	if (buffer->length && buffer->length < buffer->watermark)
66937d34556SJosselin Costanzi 		buffer->watermark = buffer->length;
67037d34556SJosselin Costanzi out:
671*16afe125SNuno Sá 	mutex_unlock(&iio_dev_opaque->mlock);
672a980e046SJonathan Cameron 
673a980e046SJonathan Cameron 	return ret ? ret : len;
674a980e046SJonathan Cameron }
675a980e046SJonathan Cameron 
6769cf0b618SJoe Simmons-Talbott static ssize_t enable_show(struct device *dev, 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 {
708abeba59fSJoe Simmons-Talbott 	unsigned int 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 {
937abeba59fSJoe Simmons-Talbott 	unsigned int from;
938abeba59fSJoe Simmons-Talbott 	unsigned int to;
939abeba59fSJoe Simmons-Talbott 	unsigned int 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;
9469d9ec8d0SJoe Simmons-Talbott 
94778c9981fSJonathan Cameron 	list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
94878c9981fSJonathan Cameron 		list_del(&p->l);
94978c9981fSJonathan Cameron 		kfree(p);
95078c9981fSJonathan Cameron 	}
95178c9981fSJonathan Cameron }
95278c9981fSJonathan Cameron 
95378c9981fSJonathan Cameron static int iio_buffer_add_demux(struct iio_buffer *buffer,
95478c9981fSJonathan Cameron 	struct iio_demux_table **p, unsigned int in_loc, unsigned int out_loc,
95578c9981fSJonathan Cameron 	unsigned int length)
95678c9981fSJonathan Cameron {
95778c9981fSJonathan Cameron 
95878c9981fSJonathan Cameron 	if (*p && (*p)->from + (*p)->length == in_loc &&
95978c9981fSJonathan Cameron 		(*p)->to + (*p)->length == out_loc) {
96078c9981fSJonathan Cameron 		(*p)->length += length;
96178c9981fSJonathan Cameron 	} else {
96278c9981fSJonathan Cameron 		*p = kmalloc(sizeof(**p), GFP_KERNEL);
96378c9981fSJonathan Cameron 		if (*p == NULL)
96478c9981fSJonathan Cameron 			return -ENOMEM;
96578c9981fSJonathan Cameron 		(*p)->from = in_loc;
96678c9981fSJonathan Cameron 		(*p)->to = out_loc;
96778c9981fSJonathan Cameron 		(*p)->length = length;
96878c9981fSJonathan Cameron 		list_add_tail(&(*p)->l, &buffer->demux_list);
96978c9981fSJonathan Cameron 	}
97078c9981fSJonathan Cameron 
97178c9981fSJonathan Cameron 	return 0;
97278c9981fSJonathan Cameron }
97378c9981fSJonathan Cameron 
97478c9981fSJonathan Cameron static int iio_buffer_update_demux(struct iio_dev *indio_dev,
97578c9981fSJonathan Cameron 				   struct iio_buffer *buffer)
97678c9981fSJonathan Cameron {
97778c9981fSJonathan Cameron 	int ret, in_ind = -1, out_ind, length;
978abeba59fSJoe Simmons-Talbott 	unsigned int in_loc = 0, out_loc = 0;
97978c9981fSJonathan Cameron 	struct iio_demux_table *p = NULL;
98078c9981fSJonathan Cameron 
98178c9981fSJonathan Cameron 	/* Clear out any old demux */
98278c9981fSJonathan Cameron 	iio_buffer_demux_free(buffer);
98378c9981fSJonathan Cameron 	kfree(buffer->demux_bounce);
98478c9981fSJonathan Cameron 	buffer->demux_bounce = NULL;
98578c9981fSJonathan Cameron 
98678c9981fSJonathan Cameron 	/* First work out which scan mode we will actually have */
98778c9981fSJonathan Cameron 	if (bitmap_equal(indio_dev->active_scan_mask,
98878c9981fSJonathan Cameron 			 buffer->scan_mask,
98978c9981fSJonathan Cameron 			 indio_dev->masklength))
99078c9981fSJonathan Cameron 		return 0;
99178c9981fSJonathan Cameron 
99278c9981fSJonathan Cameron 	/* Now we have the two masks, work from least sig and build up sizes */
99378c9981fSJonathan Cameron 	for_each_set_bit(out_ind,
99478c9981fSJonathan Cameron 			 buffer->scan_mask,
99578c9981fSJonathan Cameron 			 indio_dev->masklength) {
99678c9981fSJonathan Cameron 		in_ind = find_next_bit(indio_dev->active_scan_mask,
99778c9981fSJonathan Cameron 				       indio_dev->masklength,
99878c9981fSJonathan Cameron 				       in_ind + 1);
99978c9981fSJonathan Cameron 		while (in_ind != out_ind) {
100078c9981fSJonathan Cameron 			length = iio_storage_bytes_for_si(indio_dev, in_ind);
100178c9981fSJonathan Cameron 			/* Make sure we are aligned */
100278c9981fSJonathan Cameron 			in_loc = roundup(in_loc, length) + length;
100319ef7b70SNuno Sá 			in_ind = find_next_bit(indio_dev->active_scan_mask,
100419ef7b70SNuno Sá 					       indio_dev->masklength,
100519ef7b70SNuno Sá 					       in_ind + 1);
100678c9981fSJonathan Cameron 		}
100778c9981fSJonathan Cameron 		length = iio_storage_bytes_for_si(indio_dev, in_ind);
100878c9981fSJonathan Cameron 		out_loc = roundup(out_loc, length);
100978c9981fSJonathan Cameron 		in_loc = roundup(in_loc, length);
101078c9981fSJonathan Cameron 		ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length);
101178c9981fSJonathan Cameron 		if (ret)
101278c9981fSJonathan Cameron 			goto error_clear_mux_table;
101378c9981fSJonathan Cameron 		out_loc += length;
101478c9981fSJonathan Cameron 		in_loc += length;
101578c9981fSJonathan Cameron 	}
101678c9981fSJonathan Cameron 	/* Relies on scan_timestamp being last */
101778c9981fSJonathan Cameron 	if (buffer->scan_timestamp) {
101878c9981fSJonathan Cameron 		length = iio_storage_bytes_for_timestamp(indio_dev);
101978c9981fSJonathan Cameron 		out_loc = roundup(out_loc, length);
102078c9981fSJonathan Cameron 		in_loc = roundup(in_loc, length);
102178c9981fSJonathan Cameron 		ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length);
102278c9981fSJonathan Cameron 		if (ret)
102378c9981fSJonathan Cameron 			goto error_clear_mux_table;
102478c9981fSJonathan Cameron 		out_loc += length;
102578c9981fSJonathan Cameron 	}
102678c9981fSJonathan Cameron 	buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL);
102778c9981fSJonathan Cameron 	if (buffer->demux_bounce == NULL) {
102878c9981fSJonathan Cameron 		ret = -ENOMEM;
102978c9981fSJonathan Cameron 		goto error_clear_mux_table;
103078c9981fSJonathan Cameron 	}
103178c9981fSJonathan Cameron 	return 0;
103278c9981fSJonathan Cameron 
103378c9981fSJonathan Cameron error_clear_mux_table:
103478c9981fSJonathan Cameron 	iio_buffer_demux_free(buffer);
103578c9981fSJonathan Cameron 
103678c9981fSJonathan Cameron 	return ret;
103778c9981fSJonathan Cameron }
103878c9981fSJonathan Cameron 
103978c9981fSJonathan Cameron static int iio_update_demux(struct iio_dev *indio_dev)
104078c9981fSJonathan Cameron {
10416a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
104278c9981fSJonathan Cameron 	struct iio_buffer *buffer;
104378c9981fSJonathan Cameron 	int ret;
104478c9981fSJonathan Cameron 
10456a8c6b26SAlexandru Ardelean 	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
104678c9981fSJonathan Cameron 		ret = iio_buffer_update_demux(indio_dev, buffer);
104778c9981fSJonathan Cameron 		if (ret < 0)
104878c9981fSJonathan Cameron 			goto error_clear_mux_table;
104978c9981fSJonathan Cameron 	}
105078c9981fSJonathan Cameron 	return 0;
105178c9981fSJonathan Cameron 
105278c9981fSJonathan Cameron error_clear_mux_table:
10536a8c6b26SAlexandru Ardelean 	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list)
105478c9981fSJonathan Cameron 		iio_buffer_demux_free(buffer);
105578c9981fSJonathan Cameron 
105678c9981fSJonathan Cameron 	return ret;
105778c9981fSJonathan Cameron }
105878c9981fSJonathan Cameron 
1059623d74e3SLars-Peter Clausen static int iio_enable_buffers(struct iio_dev *indio_dev,
1060623d74e3SLars-Peter Clausen 	struct iio_device_config *config)
1061623d74e3SLars-Peter Clausen {
10626a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1063c22e60c3SJakob Koschel 	struct iio_buffer *buffer, *tmp = NULL;
1064623d74e3SLars-Peter Clausen 	int ret;
1065623d74e3SLars-Peter Clausen 
1066623d74e3SLars-Peter Clausen 	indio_dev->active_scan_mask = config->scan_mask;
1067623d74e3SLars-Peter Clausen 	indio_dev->scan_timestamp = config->scan_timestamp;
1068623d74e3SLars-Peter Clausen 	indio_dev->scan_bytes = config->scan_bytes;
106951570c9dSMiquel Raynal 	iio_dev_opaque->currentmode = config->mode;
1070623d74e3SLars-Peter Clausen 
1071623d74e3SLars-Peter Clausen 	iio_update_demux(indio_dev);
1072623d74e3SLars-Peter Clausen 
1073623d74e3SLars-Peter Clausen 	/* Wind up again */
1074623d74e3SLars-Peter Clausen 	if (indio_dev->setup_ops->preenable) {
1075623d74e3SLars-Peter Clausen 		ret = indio_dev->setup_ops->preenable(indio_dev);
1076623d74e3SLars-Peter Clausen 		if (ret) {
1077623d74e3SLars-Peter Clausen 			dev_dbg(&indio_dev->dev,
1078623d74e3SLars-Peter Clausen 			       "Buffer not started: buffer preenable failed (%d)\n", ret);
1079623d74e3SLars-Peter Clausen 			goto err_undo_config;
1080623d74e3SLars-Peter Clausen 		}
1081623d74e3SLars-Peter Clausen 	}
1082623d74e3SLars-Peter Clausen 
1083623d74e3SLars-Peter Clausen 	if (indio_dev->info->update_scan_mode) {
1084623d74e3SLars-Peter Clausen 		ret = indio_dev->info
1085623d74e3SLars-Peter Clausen 			->update_scan_mode(indio_dev,
1086623d74e3SLars-Peter Clausen 					   indio_dev->active_scan_mask);
1087623d74e3SLars-Peter Clausen 		if (ret < 0) {
1088623d74e3SLars-Peter Clausen 			dev_dbg(&indio_dev->dev,
1089623d74e3SLars-Peter Clausen 				"Buffer not started: update scan mode failed (%d)\n",
1090623d74e3SLars-Peter Clausen 				ret);
1091623d74e3SLars-Peter Clausen 			goto err_run_postdisable;
1092623d74e3SLars-Peter Clausen 		}
1093623d74e3SLars-Peter Clausen 	}
1094623d74e3SLars-Peter Clausen 
1095f0566c0cSLars-Peter Clausen 	if (indio_dev->info->hwfifo_set_watermark)
1096f0566c0cSLars-Peter Clausen 		indio_dev->info->hwfifo_set_watermark(indio_dev,
1097f0566c0cSLars-Peter Clausen 			config->watermark);
1098f0566c0cSLars-Peter Clausen 
10996a8c6b26SAlexandru Ardelean 	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
1100e18a2ad4SLars-Peter Clausen 		ret = iio_buffer_enable(buffer, indio_dev);
1101c22e60c3SJakob Koschel 		if (ret) {
1102c22e60c3SJakob Koschel 			tmp = buffer;
1103e18a2ad4SLars-Peter Clausen 			goto err_disable_buffers;
1104e18a2ad4SLars-Peter Clausen 		}
1105c22e60c3SJakob Koschel 	}
1106e18a2ad4SLars-Peter Clausen 
110751570c9dSMiquel Raynal 	if (iio_dev_opaque->currentmode == INDIO_BUFFER_TRIGGERED) {
1108f11d59d8SLars-Peter Clausen 		ret = iio_trigger_attach_poll_func(indio_dev->trig,
1109f11d59d8SLars-Peter Clausen 						   indio_dev->pollfunc);
1110f11d59d8SLars-Peter Clausen 		if (ret)
1111f11d59d8SLars-Peter Clausen 			goto err_disable_buffers;
1112f11d59d8SLars-Peter Clausen 	}
1113f11d59d8SLars-Peter Clausen 
111462a30a29SAlexandru Ardelean 	if (indio_dev->setup_ops->postenable) {
111562a30a29SAlexandru Ardelean 		ret = indio_dev->setup_ops->postenable(indio_dev);
111662a30a29SAlexandru Ardelean 		if (ret) {
111762a30a29SAlexandru Ardelean 			dev_dbg(&indio_dev->dev,
111862a30a29SAlexandru Ardelean 			       "Buffer not started: postenable failed (%d)\n", ret);
111962a30a29SAlexandru Ardelean 			goto err_detach_pollfunc;
112062a30a29SAlexandru Ardelean 		}
112162a30a29SAlexandru Ardelean 	}
112262a30a29SAlexandru Ardelean 
1123623d74e3SLars-Peter Clausen 	return 0;
1124623d74e3SLars-Peter Clausen 
112562a30a29SAlexandru Ardelean err_detach_pollfunc:
112651570c9dSMiquel Raynal 	if (iio_dev_opaque->currentmode == INDIO_BUFFER_TRIGGERED) {
112762a30a29SAlexandru Ardelean 		iio_trigger_detach_poll_func(indio_dev->trig,
112862a30a29SAlexandru Ardelean 					     indio_dev->pollfunc);
112962a30a29SAlexandru Ardelean 	}
1130e18a2ad4SLars-Peter Clausen err_disable_buffers:
1131c22e60c3SJakob Koschel 	buffer = list_prepare_entry(tmp, &iio_dev_opaque->buffer_list, buffer_list);
11326a8c6b26SAlexandru Ardelean 	list_for_each_entry_continue_reverse(buffer, &iio_dev_opaque->buffer_list,
1133e18a2ad4SLars-Peter Clausen 					     buffer_list)
1134e18a2ad4SLars-Peter Clausen 		iio_buffer_disable(buffer, indio_dev);
1135623d74e3SLars-Peter Clausen err_run_postdisable:
1136623d74e3SLars-Peter Clausen 	if (indio_dev->setup_ops->postdisable)
1137623d74e3SLars-Peter Clausen 		indio_dev->setup_ops->postdisable(indio_dev);
1138623d74e3SLars-Peter Clausen err_undo_config:
113951570c9dSMiquel Raynal 	iio_dev_opaque->currentmode = INDIO_DIRECT_MODE;
1140623d74e3SLars-Peter Clausen 	indio_dev->active_scan_mask = NULL;
1141623d74e3SLars-Peter Clausen 
1142623d74e3SLars-Peter Clausen 	return ret;
1143623d74e3SLars-Peter Clausen }
1144623d74e3SLars-Peter Clausen 
1145623d74e3SLars-Peter Clausen static int iio_disable_buffers(struct iio_dev *indio_dev)
1146623d74e3SLars-Peter Clausen {
11476a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1148e18a2ad4SLars-Peter Clausen 	struct iio_buffer *buffer;
11491250186aSLars-Peter Clausen 	int ret = 0;
11501250186aSLars-Peter Clausen 	int ret2;
1151623d74e3SLars-Peter Clausen 
1152623d74e3SLars-Peter Clausen 	/* Wind down existing buffers - iff there are any */
11536a8c6b26SAlexandru Ardelean 	if (list_empty(&iio_dev_opaque->buffer_list))
1154623d74e3SLars-Peter Clausen 		return 0;
1155623d74e3SLars-Peter Clausen 
11561250186aSLars-Peter Clausen 	/*
11571250186aSLars-Peter Clausen 	 * If things go wrong at some step in disable we still need to continue
11581250186aSLars-Peter Clausen 	 * to perform the other steps, otherwise we leave the device in a
11591250186aSLars-Peter Clausen 	 * inconsistent state. We return the error code for the first error we
11601250186aSLars-Peter Clausen 	 * encountered.
11611250186aSLars-Peter Clausen 	 */
11621250186aSLars-Peter Clausen 
1163623d74e3SLars-Peter Clausen 	if (indio_dev->setup_ops->predisable) {
11641250186aSLars-Peter Clausen 		ret2 = indio_dev->setup_ops->predisable(indio_dev);
11651250186aSLars-Peter Clausen 		if (ret2 && !ret)
11661250186aSLars-Peter Clausen 			ret = ret2;
1167623d74e3SLars-Peter Clausen 	}
1168623d74e3SLars-Peter Clausen 
116951570c9dSMiquel Raynal 	if (iio_dev_opaque->currentmode == INDIO_BUFFER_TRIGGERED) {
117062a30a29SAlexandru Ardelean 		iio_trigger_detach_poll_func(indio_dev->trig,
117162a30a29SAlexandru Ardelean 					     indio_dev->pollfunc);
117262a30a29SAlexandru Ardelean 	}
117362a30a29SAlexandru Ardelean 
11746a8c6b26SAlexandru Ardelean 	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
1175e18a2ad4SLars-Peter Clausen 		ret2 = iio_buffer_disable(buffer, indio_dev);
1176e18a2ad4SLars-Peter Clausen 		if (ret2 && !ret)
1177e18a2ad4SLars-Peter Clausen 			ret = ret2;
1178e18a2ad4SLars-Peter Clausen 	}
1179e18a2ad4SLars-Peter Clausen 
1180623d74e3SLars-Peter Clausen 	if (indio_dev->setup_ops->postdisable) {
11811250186aSLars-Peter Clausen 		ret2 = indio_dev->setup_ops->postdisable(indio_dev);
11821250186aSLars-Peter Clausen 		if (ret2 && !ret)
11831250186aSLars-Peter Clausen 			ret = ret2;
1184623d74e3SLars-Peter Clausen 	}
1185623d74e3SLars-Peter Clausen 
11861250186aSLars-Peter Clausen 	iio_free_scan_mask(indio_dev, indio_dev->active_scan_mask);
11871250186aSLars-Peter Clausen 	indio_dev->active_scan_mask = NULL;
118851570c9dSMiquel Raynal 	iio_dev_opaque->currentmode = INDIO_DIRECT_MODE;
11891250186aSLars-Peter Clausen 
11901250186aSLars-Peter Clausen 	return ret;
1191623d74e3SLars-Peter Clausen }
1192623d74e3SLars-Peter Clausen 
1193a9519456SLars-Peter Clausen static int __iio_update_buffers(struct iio_dev *indio_dev,
119484b36ce5SJonathan Cameron 		       struct iio_buffer *insert_buffer,
119584b36ce5SJonathan Cameron 		       struct iio_buffer *remove_buffer)
1196a980e046SJonathan Cameron {
11976a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
11986e509c4dSLars-Peter Clausen 	struct iio_device_config new_config;
11991250186aSLars-Peter Clausen 	int ret;
12006e509c4dSLars-Peter Clausen 
12016e509c4dSLars-Peter Clausen 	ret = iio_verify_update(indio_dev, insert_buffer, remove_buffer,
12026e509c4dSLars-Peter Clausen 		&new_config);
12036e509c4dSLars-Peter Clausen 	if (ret)
12046e509c4dSLars-Peter Clausen 		return ret;
1205a980e046SJonathan Cameron 
1206fcc1b2f5SLars-Peter Clausen 	if (insert_buffer) {
1207fcc1b2f5SLars-Peter Clausen 		ret = iio_buffer_request_update(indio_dev, insert_buffer);
1208fcc1b2f5SLars-Peter Clausen 		if (ret)
12096e509c4dSLars-Peter Clausen 			goto err_free_config;
1210fcc1b2f5SLars-Peter Clausen 	}
1211fcc1b2f5SLars-Peter Clausen 
1212623d74e3SLars-Peter Clausen 	ret = iio_disable_buffers(indio_dev);
12131250186aSLars-Peter Clausen 	if (ret)
12141250186aSLars-Peter Clausen 		goto err_deactivate_all;
1215623d74e3SLars-Peter Clausen 
121684b36ce5SJonathan Cameron 	if (remove_buffer)
12179e69c935SLars-Peter Clausen 		iio_buffer_deactivate(remove_buffer);
121884b36ce5SJonathan Cameron 	if (insert_buffer)
12199e69c935SLars-Peter Clausen 		iio_buffer_activate(indio_dev, insert_buffer);
122084b36ce5SJonathan Cameron 
122184b36ce5SJonathan Cameron 	/* If no buffers in list, we are done */
12226a8c6b26SAlexandru Ardelean 	if (list_empty(&iio_dev_opaque->buffer_list))
122384b36ce5SJonathan Cameron 		return 0;
1224a980e046SJonathan Cameron 
1225623d74e3SLars-Peter Clausen 	ret = iio_enable_buffers(indio_dev, &new_config);
12261250186aSLars-Peter Clausen 	if (ret)
12271250186aSLars-Peter Clausen 		goto err_deactivate_all;
1228623d74e3SLars-Peter Clausen 
1229623d74e3SLars-Peter Clausen 	return 0;
12306e509c4dSLars-Peter Clausen 
12311250186aSLars-Peter Clausen err_deactivate_all:
12321250186aSLars-Peter Clausen 	/*
12331250186aSLars-Peter Clausen 	 * We've already verified that the config is valid earlier. If things go
12341250186aSLars-Peter Clausen 	 * wrong in either enable or disable the most likely reason is an IO
12351250186aSLars-Peter Clausen 	 * error from the device. In this case there is no good recovery
12361250186aSLars-Peter Clausen 	 * strategy. Just make sure to disable everything and leave the device
12371250186aSLars-Peter Clausen 	 * in a sane state.  With a bit of luck the device might come back to
12381250186aSLars-Peter Clausen 	 * life again later and userspace can try again.
12391250186aSLars-Peter Clausen 	 */
12401250186aSLars-Peter Clausen 	iio_buffer_deactivate_all(indio_dev);
12411250186aSLars-Peter Clausen 
12426e509c4dSLars-Peter Clausen err_free_config:
12436e509c4dSLars-Peter Clausen 	iio_free_scan_mask(indio_dev, new_config.scan_mask);
12446e509c4dSLars-Peter Clausen 	return ret;
124584b36ce5SJonathan Cameron }
1246a9519456SLars-Peter Clausen 
1247a9519456SLars-Peter Clausen int iio_update_buffers(struct iio_dev *indio_dev,
1248a9519456SLars-Peter Clausen 		       struct iio_buffer *insert_buffer,
1249a9519456SLars-Peter Clausen 		       struct iio_buffer *remove_buffer)
1250a9519456SLars-Peter Clausen {
1251b804e2b7SJonathan Cameron 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1252a9519456SLars-Peter Clausen 	int ret;
1253a9519456SLars-Peter Clausen 
12543909fab5SLars-Peter Clausen 	if (insert_buffer == remove_buffer)
12553909fab5SLars-Peter Clausen 		return 0;
12563909fab5SLars-Peter Clausen 
12579eeee3b0SMihail Chindris 	if (insert_buffer &&
12589eeee3b0SMihail Chindris 	    (insert_buffer->direction == IIO_BUFFER_DIRECTION_OUT))
12599eeee3b0SMihail Chindris 		return -EINVAL;
12609eeee3b0SMihail Chindris 
1261b804e2b7SJonathan Cameron 	mutex_lock(&iio_dev_opaque->info_exist_lock);
1262*16afe125SNuno Sá 	mutex_lock(&iio_dev_opaque->mlock);
1263a9519456SLars-Peter Clausen 
12643909fab5SLars-Peter Clausen 	if (insert_buffer && iio_buffer_is_active(insert_buffer))
12653909fab5SLars-Peter Clausen 		insert_buffer = NULL;
12663909fab5SLars-Peter Clausen 
12673909fab5SLars-Peter Clausen 	if (remove_buffer && !iio_buffer_is_active(remove_buffer))
12683909fab5SLars-Peter Clausen 		remove_buffer = NULL;
12693909fab5SLars-Peter Clausen 
12703909fab5SLars-Peter Clausen 	if (!insert_buffer && !remove_buffer) {
12713909fab5SLars-Peter Clausen 		ret = 0;
12723909fab5SLars-Peter Clausen 		goto out_unlock;
12733909fab5SLars-Peter Clausen 	}
12743909fab5SLars-Peter Clausen 
1275a9519456SLars-Peter Clausen 	if (indio_dev->info == NULL) {
1276a9519456SLars-Peter Clausen 		ret = -ENODEV;
1277a9519456SLars-Peter Clausen 		goto out_unlock;
1278a9519456SLars-Peter Clausen 	}
1279a9519456SLars-Peter Clausen 
1280a9519456SLars-Peter Clausen 	ret = __iio_update_buffers(indio_dev, insert_buffer, remove_buffer);
1281a9519456SLars-Peter Clausen 
1282a9519456SLars-Peter Clausen out_unlock:
1283*16afe125SNuno Sá 	mutex_unlock(&iio_dev_opaque->mlock);
1284b804e2b7SJonathan Cameron 	mutex_unlock(&iio_dev_opaque->info_exist_lock);
1285a9519456SLars-Peter Clausen 
1286a9519456SLars-Peter Clausen 	return ret;
1287a9519456SLars-Peter Clausen }
128884b36ce5SJonathan Cameron EXPORT_SYMBOL_GPL(iio_update_buffers);
128984b36ce5SJonathan Cameron 
1290623d74e3SLars-Peter Clausen void iio_disable_all_buffers(struct iio_dev *indio_dev)
1291623d74e3SLars-Peter Clausen {
1292623d74e3SLars-Peter Clausen 	iio_disable_buffers(indio_dev);
12931250186aSLars-Peter Clausen 	iio_buffer_deactivate_all(indio_dev);
1294623d74e3SLars-Peter Clausen }
1295623d74e3SLars-Peter Clausen 
12969cf0b618SJoe Simmons-Talbott static ssize_t enable_store(struct device *dev, struct device_attribute *attr,
12979cf0b618SJoe Simmons-Talbott 			    const char *buf, size_t len)
129884b36ce5SJonathan Cameron {
129984b36ce5SJonathan Cameron 	int ret;
130084b36ce5SJonathan Cameron 	bool requested_state;
130184b36ce5SJonathan Cameron 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
1302*16afe125SNuno Sá 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
130315097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
130484b36ce5SJonathan Cameron 	bool inlist;
130584b36ce5SJonathan Cameron 
130674f582ecSLars-Peter Clausen 	ret = kstrtobool(buf, &requested_state);
130784b36ce5SJonathan Cameron 	if (ret < 0)
130884b36ce5SJonathan Cameron 		return ret;
130984b36ce5SJonathan Cameron 
1310*16afe125SNuno Sá 	mutex_lock(&iio_dev_opaque->mlock);
131184b36ce5SJonathan Cameron 
131284b36ce5SJonathan Cameron 	/* Find out if it is in the list */
1313ff3f7e04SAlexandru Ardelean 	inlist = iio_buffer_is_active(buffer);
131484b36ce5SJonathan Cameron 	/* Already in desired state */
131584b36ce5SJonathan Cameron 	if (inlist == requested_state)
131684b36ce5SJonathan Cameron 		goto done;
131784b36ce5SJonathan Cameron 
131884b36ce5SJonathan Cameron 	if (requested_state)
1319ff3f7e04SAlexandru Ardelean 		ret = __iio_update_buffers(indio_dev, buffer, NULL);
132084b36ce5SJonathan Cameron 	else
1321ff3f7e04SAlexandru Ardelean 		ret = __iio_update_buffers(indio_dev, NULL, buffer);
132284b36ce5SJonathan Cameron 
132384b36ce5SJonathan Cameron done:
1324*16afe125SNuno Sá 	mutex_unlock(&iio_dev_opaque->mlock);
132584b36ce5SJonathan Cameron 	return (ret < 0) ? ret : len;
132684b36ce5SJonathan Cameron }
132784b36ce5SJonathan Cameron 
13289cf0b618SJoe Simmons-Talbott static ssize_t watermark_show(struct device *dev, struct device_attribute *attr,
132937d34556SJosselin Costanzi 			      char *buf)
133037d34556SJosselin Costanzi {
133115097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
133237d34556SJosselin Costanzi 
133383ca56b6SLars-Peter Clausen 	return sysfs_emit(buf, "%u\n", buffer->watermark);
133437d34556SJosselin Costanzi }
133537d34556SJosselin Costanzi 
13369cf0b618SJoe Simmons-Talbott static ssize_t watermark_store(struct device *dev,
133737d34556SJosselin Costanzi 			       struct device_attribute *attr,
13389cf0b618SJoe Simmons-Talbott 			       const char *buf, size_t len)
133937d34556SJosselin Costanzi {
134037d34556SJosselin Costanzi 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
1341*16afe125SNuno Sá 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
134215097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
134337d34556SJosselin Costanzi 	unsigned int val;
134437d34556SJosselin Costanzi 	int ret;
134537d34556SJosselin Costanzi 
134637d34556SJosselin Costanzi 	ret = kstrtouint(buf, 10, &val);
134737d34556SJosselin Costanzi 	if (ret)
134837d34556SJosselin Costanzi 		return ret;
134937d34556SJosselin Costanzi 	if (!val)
135037d34556SJosselin Costanzi 		return -EINVAL;
135137d34556SJosselin Costanzi 
1352*16afe125SNuno Sá 	mutex_lock(&iio_dev_opaque->mlock);
135337d34556SJosselin Costanzi 
135437d34556SJosselin Costanzi 	if (val > buffer->length) {
135537d34556SJosselin Costanzi 		ret = -EINVAL;
135637d34556SJosselin Costanzi 		goto out;
135737d34556SJosselin Costanzi 	}
135837d34556SJosselin Costanzi 
1359ff3f7e04SAlexandru Ardelean 	if (iio_buffer_is_active(buffer)) {
136037d34556SJosselin Costanzi 		ret = -EBUSY;
136137d34556SJosselin Costanzi 		goto out;
136237d34556SJosselin Costanzi 	}
136337d34556SJosselin Costanzi 
136437d34556SJosselin Costanzi 	buffer->watermark = val;
136537d34556SJosselin Costanzi out:
1366*16afe125SNuno Sá 	mutex_unlock(&iio_dev_opaque->mlock);
136737d34556SJosselin Costanzi 
136837d34556SJosselin Costanzi 	return ret ? ret : len;
136937d34556SJosselin Costanzi }
137037d34556SJosselin Costanzi 
13719cf0b618SJoe Simmons-Talbott static ssize_t data_available_show(struct device *dev,
13729cf0b618SJoe Simmons-Talbott 				   struct device_attribute *attr, char *buf)
1373350f6c75SMatt Fornero {
137415097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
1375350f6c75SMatt Fornero 
137683ca56b6SLars-Peter Clausen 	return sysfs_emit(buf, "%zu\n", iio_buffer_data_available(buffer));
1377350f6c75SMatt Fornero }
1378350f6c75SMatt Fornero 
13799eeee3b0SMihail Chindris static ssize_t direction_show(struct device *dev,
13809eeee3b0SMihail Chindris 			      struct device_attribute *attr,
13819eeee3b0SMihail Chindris 			      char *buf)
13829eeee3b0SMihail Chindris {
13839eeee3b0SMihail Chindris 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
13849eeee3b0SMihail Chindris 
13859eeee3b0SMihail Chindris 	switch (buffer->direction) {
13869eeee3b0SMihail Chindris 	case IIO_BUFFER_DIRECTION_IN:
1387c3154defSLars-Peter Clausen 		return sysfs_emit(buf, "in\n");
13889eeee3b0SMihail Chindris 	case IIO_BUFFER_DIRECTION_OUT:
1389c3154defSLars-Peter Clausen 		return sysfs_emit(buf, "out\n");
13909eeee3b0SMihail Chindris 	default:
13919eeee3b0SMihail Chindris 		return -EINVAL;
13929eeee3b0SMihail Chindris 	}
13939eeee3b0SMihail Chindris }
13949eeee3b0SMihail Chindris 
13959cf0b618SJoe Simmons-Talbott static DEVICE_ATTR_RW(length);
13969cf0b618SJoe Simmons-Talbott static struct device_attribute dev_attr_length_ro = __ATTR_RO(length);
13979cf0b618SJoe Simmons-Talbott static DEVICE_ATTR_RW(enable);
13989cf0b618SJoe Simmons-Talbott static DEVICE_ATTR_RW(watermark);
13999cf0b618SJoe Simmons-Talbott static struct device_attribute dev_attr_watermark_ro = __ATTR_RO(watermark);
14009cf0b618SJoe Simmons-Talbott static DEVICE_ATTR_RO(data_available);
14019eeee3b0SMihail Chindris static DEVICE_ATTR_RO(direction);
140208e7e0adSLars-Peter Clausen 
14039eeee3b0SMihail Chindris /*
14049eeee3b0SMihail Chindris  * When adding new attributes here, put the at the end, at least until
14059eeee3b0SMihail Chindris  * the code that handles the length/length_ro & watermark/watermark_ro
14069eeee3b0SMihail Chindris  * assignments gets cleaned up. Otherwise these can create some weird
14079eeee3b0SMihail Chindris  * duplicate attributes errors under some setups.
14089eeee3b0SMihail Chindris  */
14096da9b382SOctavian Purdila static struct attribute *iio_buffer_attrs[] = {
14106da9b382SOctavian Purdila 	&dev_attr_length.attr,
14116da9b382SOctavian Purdila 	&dev_attr_enable.attr,
141237d34556SJosselin Costanzi 	&dev_attr_watermark.attr,
1413350f6c75SMatt Fornero 	&dev_attr_data_available.attr,
14149eeee3b0SMihail Chindris 	&dev_attr_direction.attr,
14156da9b382SOctavian Purdila };
14166da9b382SOctavian Purdila 
141715097c7aSAlexandru Ardelean #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
141815097c7aSAlexandru Ardelean 
141915097c7aSAlexandru Ardelean static struct attribute *iio_buffer_wrap_attr(struct iio_buffer *buffer,
142015097c7aSAlexandru Ardelean 					      struct attribute *attr)
142115097c7aSAlexandru Ardelean {
142215097c7aSAlexandru Ardelean 	struct device_attribute *dattr = to_dev_attr(attr);
142315097c7aSAlexandru Ardelean 	struct iio_dev_attr *iio_attr;
142415097c7aSAlexandru Ardelean 
142515097c7aSAlexandru Ardelean 	iio_attr = kzalloc(sizeof(*iio_attr), GFP_KERNEL);
142615097c7aSAlexandru Ardelean 	if (!iio_attr)
142715097c7aSAlexandru Ardelean 		return NULL;
142815097c7aSAlexandru Ardelean 
142915097c7aSAlexandru Ardelean 	iio_attr->buffer = buffer;
143015097c7aSAlexandru Ardelean 	memcpy(&iio_attr->dev_attr, dattr, sizeof(iio_attr->dev_attr));
143115097c7aSAlexandru Ardelean 	iio_attr->dev_attr.attr.name = kstrdup_const(attr->name, GFP_KERNEL);
14322c0ad3f0SYang Yingliang 	if (!iio_attr->dev_attr.attr.name) {
14332c0ad3f0SYang Yingliang 		kfree(iio_attr);
14342c0ad3f0SYang Yingliang 		return NULL;
14352c0ad3f0SYang Yingliang 	}
14362c0ad3f0SYang Yingliang 
1437ca3e7d52SAlexandru Ardelean 	sysfs_attr_init(&iio_attr->dev_attr.attr);
143815097c7aSAlexandru Ardelean 
143915097c7aSAlexandru Ardelean 	list_add(&iio_attr->l, &buffer->buffer_attr_list);
144015097c7aSAlexandru Ardelean 
144115097c7aSAlexandru Ardelean 	return &iio_attr->dev_attr.attr;
144215097c7aSAlexandru Ardelean }
144315097c7aSAlexandru Ardelean 
1444d9a62574SAlexandru Ardelean static int iio_buffer_register_legacy_sysfs_groups(struct iio_dev *indio_dev,
1445d9a62574SAlexandru Ardelean 						   struct attribute **buffer_attrs,
1446d9a62574SAlexandru Ardelean 						   int buffer_attrcount,
1447d9a62574SAlexandru Ardelean 						   int scan_el_attrcount)
1448d9a62574SAlexandru Ardelean {
1449d9a62574SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1450d9a62574SAlexandru Ardelean 	struct attribute_group *group;
1451d9a62574SAlexandru Ardelean 	struct attribute **attrs;
1452d9a62574SAlexandru Ardelean 	int ret;
1453d9a62574SAlexandru Ardelean 
1454d9a62574SAlexandru Ardelean 	attrs = kcalloc(buffer_attrcount + 1, sizeof(*attrs), GFP_KERNEL);
1455d9a62574SAlexandru Ardelean 	if (!attrs)
1456d9a62574SAlexandru Ardelean 		return -ENOMEM;
1457d9a62574SAlexandru Ardelean 
1458d9a62574SAlexandru Ardelean 	memcpy(attrs, buffer_attrs, buffer_attrcount * sizeof(*attrs));
1459d9a62574SAlexandru Ardelean 
1460d9a62574SAlexandru Ardelean 	group = &iio_dev_opaque->legacy_buffer_group;
1461d9a62574SAlexandru Ardelean 	group->attrs = attrs;
1462d9a62574SAlexandru Ardelean 	group->name = "buffer";
1463d9a62574SAlexandru Ardelean 
1464d9a62574SAlexandru Ardelean 	ret = iio_device_register_sysfs_group(indio_dev, group);
1465d9a62574SAlexandru Ardelean 	if (ret)
1466d9a62574SAlexandru Ardelean 		goto error_free_buffer_attrs;
1467d9a62574SAlexandru Ardelean 
1468d9a62574SAlexandru Ardelean 	attrs = kcalloc(scan_el_attrcount + 1, sizeof(*attrs), GFP_KERNEL);
1469d9a62574SAlexandru Ardelean 	if (!attrs) {
1470d9a62574SAlexandru Ardelean 		ret = -ENOMEM;
1471d9a62574SAlexandru Ardelean 		goto error_free_buffer_attrs;
1472d9a62574SAlexandru Ardelean 	}
1473d9a62574SAlexandru Ardelean 
1474d9a62574SAlexandru Ardelean 	memcpy(attrs, &buffer_attrs[buffer_attrcount],
1475d9a62574SAlexandru Ardelean 	       scan_el_attrcount * sizeof(*attrs));
1476d9a62574SAlexandru Ardelean 
1477d9a62574SAlexandru Ardelean 	group = &iio_dev_opaque->legacy_scan_el_group;
1478d9a62574SAlexandru Ardelean 	group->attrs = attrs;
1479d9a62574SAlexandru Ardelean 	group->name = "scan_elements";
1480d9a62574SAlexandru Ardelean 
1481d9a62574SAlexandru Ardelean 	ret = iio_device_register_sysfs_group(indio_dev, group);
1482d9a62574SAlexandru Ardelean 	if (ret)
1483d9a62574SAlexandru Ardelean 		goto error_free_scan_el_attrs;
1484d9a62574SAlexandru Ardelean 
1485d9a62574SAlexandru Ardelean 	return 0;
1486d9a62574SAlexandru Ardelean 
1487d9a62574SAlexandru Ardelean error_free_scan_el_attrs:
1488d9a62574SAlexandru Ardelean 	kfree(iio_dev_opaque->legacy_scan_el_group.attrs);
1489604faf9aSYang Yingliang error_free_buffer_attrs:
1490604faf9aSYang Yingliang 	kfree(iio_dev_opaque->legacy_buffer_group.attrs);
1491d9a62574SAlexandru Ardelean 
1492d9a62574SAlexandru Ardelean 	return ret;
1493d9a62574SAlexandru Ardelean }
1494d9a62574SAlexandru Ardelean 
1495d9a62574SAlexandru Ardelean static void iio_buffer_unregister_legacy_sysfs_groups(struct iio_dev *indio_dev)
1496d9a62574SAlexandru Ardelean {
1497d9a62574SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1498d9a62574SAlexandru Ardelean 
1499d9a62574SAlexandru Ardelean 	kfree(iio_dev_opaque->legacy_buffer_group.attrs);
1500d9a62574SAlexandru Ardelean 	kfree(iio_dev_opaque->legacy_scan_el_group.attrs);
1501d9a62574SAlexandru Ardelean }
1502d9a62574SAlexandru Ardelean 
1503f73f7f4dSAlexandru Ardelean static int iio_buffer_chrdev_release(struct inode *inode, struct file *filep)
1504f73f7f4dSAlexandru Ardelean {
1505f73f7f4dSAlexandru Ardelean 	struct iio_dev_buffer_pair *ib = filep->private_data;
1506f73f7f4dSAlexandru Ardelean 	struct iio_dev *indio_dev = ib->indio_dev;
1507f73f7f4dSAlexandru Ardelean 	struct iio_buffer *buffer = ib->buffer;
1508f73f7f4dSAlexandru Ardelean 
1509f73f7f4dSAlexandru Ardelean 	wake_up(&buffer->pollq);
1510f73f7f4dSAlexandru Ardelean 
1511f73f7f4dSAlexandru Ardelean 	kfree(ib);
1512f73f7f4dSAlexandru Ardelean 	clear_bit(IIO_BUSY_BIT_POS, &buffer->flags);
1513f73f7f4dSAlexandru Ardelean 	iio_device_put(indio_dev);
1514f73f7f4dSAlexandru Ardelean 
1515f73f7f4dSAlexandru Ardelean 	return 0;
1516f73f7f4dSAlexandru Ardelean }
1517f73f7f4dSAlexandru Ardelean 
1518f73f7f4dSAlexandru Ardelean static const struct file_operations iio_buffer_chrdev_fileops = {
1519f73f7f4dSAlexandru Ardelean 	.owner = THIS_MODULE,
1520f73f7f4dSAlexandru Ardelean 	.llseek = noop_llseek,
1521f73f7f4dSAlexandru Ardelean 	.read = iio_buffer_read,
15229eeee3b0SMihail Chindris 	.write = iio_buffer_write,
1523f73f7f4dSAlexandru Ardelean 	.poll = iio_buffer_poll,
1524f73f7f4dSAlexandru Ardelean 	.release = iio_buffer_chrdev_release,
1525f73f7f4dSAlexandru Ardelean };
1526f73f7f4dSAlexandru Ardelean 
1527f73f7f4dSAlexandru Ardelean static long iio_device_buffer_getfd(struct iio_dev *indio_dev, unsigned long arg)
1528f73f7f4dSAlexandru Ardelean {
1529f73f7f4dSAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1530f73f7f4dSAlexandru Ardelean 	int __user *ival = (int __user *)arg;
1531f73f7f4dSAlexandru Ardelean 	struct iio_dev_buffer_pair *ib;
1532f73f7f4dSAlexandru Ardelean 	struct iio_buffer *buffer;
1533f73f7f4dSAlexandru Ardelean 	int fd, idx, ret;
1534f73f7f4dSAlexandru Ardelean 
1535f73f7f4dSAlexandru Ardelean 	if (copy_from_user(&idx, ival, sizeof(idx)))
1536f73f7f4dSAlexandru Ardelean 		return -EFAULT;
1537f73f7f4dSAlexandru Ardelean 
1538f73f7f4dSAlexandru Ardelean 	if (idx >= iio_dev_opaque->attached_buffers_cnt)
1539f73f7f4dSAlexandru Ardelean 		return -ENODEV;
1540f73f7f4dSAlexandru Ardelean 
1541f73f7f4dSAlexandru Ardelean 	iio_device_get(indio_dev);
1542f73f7f4dSAlexandru Ardelean 
1543f73f7f4dSAlexandru Ardelean 	buffer = iio_dev_opaque->attached_buffers[idx];
1544f73f7f4dSAlexandru Ardelean 
1545f73f7f4dSAlexandru Ardelean 	if (test_and_set_bit(IIO_BUSY_BIT_POS, &buffer->flags)) {
1546f73f7f4dSAlexandru Ardelean 		ret = -EBUSY;
1547f73f7f4dSAlexandru Ardelean 		goto error_iio_dev_put;
1548f73f7f4dSAlexandru Ardelean 	}
1549f73f7f4dSAlexandru Ardelean 
1550f73f7f4dSAlexandru Ardelean 	ib = kzalloc(sizeof(*ib), GFP_KERNEL);
1551f73f7f4dSAlexandru Ardelean 	if (!ib) {
1552f73f7f4dSAlexandru Ardelean 		ret = -ENOMEM;
1553f73f7f4dSAlexandru Ardelean 		goto error_clear_busy_bit;
1554f73f7f4dSAlexandru Ardelean 	}
1555f73f7f4dSAlexandru Ardelean 
1556f73f7f4dSAlexandru Ardelean 	ib->indio_dev = indio_dev;
1557f73f7f4dSAlexandru Ardelean 	ib->buffer = buffer;
1558f73f7f4dSAlexandru Ardelean 
1559f73f7f4dSAlexandru Ardelean 	fd = anon_inode_getfd("iio:buffer", &iio_buffer_chrdev_fileops,
1560f73f7f4dSAlexandru Ardelean 			      ib, O_RDWR | O_CLOEXEC);
1561f73f7f4dSAlexandru Ardelean 	if (fd < 0) {
1562f73f7f4dSAlexandru Ardelean 		ret = fd;
1563f73f7f4dSAlexandru Ardelean 		goto error_free_ib;
1564f73f7f4dSAlexandru Ardelean 	}
1565f73f7f4dSAlexandru Ardelean 
1566f73f7f4dSAlexandru Ardelean 	if (copy_to_user(ival, &fd, sizeof(fd))) {
1567c72ea205SMathias Krause 		/*
1568c72ea205SMathias Krause 		 * "Leak" the fd, as there's not much we can do about this
1569c72ea205SMathias Krause 		 * anyway. 'fd' might have been closed already, as
1570c72ea205SMathias Krause 		 * anon_inode_getfd() called fd_install() on it, which made
1571c72ea205SMathias Krause 		 * it reachable by userland.
1572c72ea205SMathias Krause 		 *
1573c72ea205SMathias Krause 		 * Instead of allowing a malicious user to play tricks with
1574c72ea205SMathias Krause 		 * us, rely on the process exit path to do any necessary
1575c72ea205SMathias Krause 		 * cleanup, as in releasing the file, if still needed.
1576c72ea205SMathias Krause 		 */
1577c72ea205SMathias Krause 		return -EFAULT;
1578f73f7f4dSAlexandru Ardelean 	}
1579f73f7f4dSAlexandru Ardelean 
15804c822244SAlexandru Ardelean 	return 0;
1581f73f7f4dSAlexandru Ardelean 
1582f73f7f4dSAlexandru Ardelean error_free_ib:
1583f73f7f4dSAlexandru Ardelean 	kfree(ib);
1584f73f7f4dSAlexandru Ardelean error_clear_busy_bit:
1585f73f7f4dSAlexandru Ardelean 	clear_bit(IIO_BUSY_BIT_POS, &buffer->flags);
1586f73f7f4dSAlexandru Ardelean error_iio_dev_put:
1587f73f7f4dSAlexandru Ardelean 	iio_device_put(indio_dev);
1588f73f7f4dSAlexandru Ardelean 	return ret;
1589f73f7f4dSAlexandru Ardelean }
1590f73f7f4dSAlexandru Ardelean 
1591f73f7f4dSAlexandru Ardelean static long iio_device_buffer_ioctl(struct iio_dev *indio_dev, struct file *filp,
1592f73f7f4dSAlexandru Ardelean 				    unsigned int cmd, unsigned long arg)
1593f73f7f4dSAlexandru Ardelean {
1594f73f7f4dSAlexandru Ardelean 	switch (cmd) {
1595f73f7f4dSAlexandru Ardelean 	case IIO_BUFFER_GET_FD_IOCTL:
1596f73f7f4dSAlexandru Ardelean 		return iio_device_buffer_getfd(indio_dev, arg);
1597f73f7f4dSAlexandru Ardelean 	default:
1598f73f7f4dSAlexandru Ardelean 		return IIO_IOCTL_UNHANDLED;
1599f73f7f4dSAlexandru Ardelean 	}
1600f73f7f4dSAlexandru Ardelean }
1601f73f7f4dSAlexandru Ardelean 
1602e16e0a77SAlexandru Ardelean static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
1603d9a62574SAlexandru Ardelean 					     struct iio_dev *indio_dev,
1604d9a62574SAlexandru Ardelean 					     int index)
1605d967cb6bSLars-Peter Clausen {
160662f4f36cSJonathan Cameron 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1607d967cb6bSLars-Peter Clausen 	struct iio_dev_attr *p;
1608d967cb6bSLars-Peter Clausen 	struct attribute **attr;
1609e2b4d7acSAlexandru Ardelean 	int ret, i, attrn, scan_el_attrcount, buffer_attrcount;
1610d967cb6bSLars-Peter Clausen 	const struct iio_chan_spec *channels;
1611d967cb6bSLars-Peter Clausen 
1612e2b4d7acSAlexandru Ardelean 	buffer_attrcount = 0;
161308e7e0adSLars-Peter Clausen 	if (buffer->attrs) {
1614e2b4d7acSAlexandru Ardelean 		while (buffer->attrs[buffer_attrcount] != NULL)
1615e2b4d7acSAlexandru Ardelean 			buffer_attrcount++;
161608e7e0adSLars-Peter Clausen 	}
161708e7e0adSLars-Peter Clausen 
1618e2b4d7acSAlexandru Ardelean 	scan_el_attrcount = 0;
161915097c7aSAlexandru Ardelean 	INIT_LIST_HEAD(&buffer->buffer_attr_list);
1620d967cb6bSLars-Peter Clausen 	channels = indio_dev->channels;
1621d967cb6bSLars-Peter Clausen 	if (channels) {
1622d967cb6bSLars-Peter Clausen 		/* new magic */
1623d967cb6bSLars-Peter Clausen 		for (i = 0; i < indio_dev->num_channels; i++) {
1624d967cb6bSLars-Peter Clausen 			if (channels[i].scan_index < 0)
1625d967cb6bSLars-Peter Clausen 				continue;
1626d967cb6bSLars-Peter Clausen 
1627fd542c5eSMarek Vasut 			/* Verify that sample bits fit into storage */
1628fd542c5eSMarek Vasut 			if (channels[i].scan_type.storagebits <
1629fd542c5eSMarek Vasut 			    channels[i].scan_type.realbits +
1630fd542c5eSMarek Vasut 			    channels[i].scan_type.shift) {
1631fd542c5eSMarek Vasut 				dev_err(&indio_dev->dev,
1632fd542c5eSMarek Vasut 					"Channel %d storagebits (%d) < shifted realbits (%d + %d)\n",
1633fd542c5eSMarek Vasut 					i, channels[i].scan_type.storagebits,
1634fd542c5eSMarek Vasut 					channels[i].scan_type.realbits,
1635fd542c5eSMarek Vasut 					channels[i].scan_type.shift);
1636fd542c5eSMarek Vasut 				ret = -EINVAL;
1637fd542c5eSMarek Vasut 				goto error_cleanup_dynamic;
1638fd542c5eSMarek Vasut 			}
1639fd542c5eSMarek Vasut 
1640ff3f7e04SAlexandru Ardelean 			ret = iio_buffer_add_channel_sysfs(indio_dev, buffer,
1641d967cb6bSLars-Peter Clausen 							 &channels[i]);
1642d967cb6bSLars-Peter Clausen 			if (ret < 0)
1643d967cb6bSLars-Peter Clausen 				goto error_cleanup_dynamic;
1644e2b4d7acSAlexandru Ardelean 			scan_el_attrcount += ret;
1645d967cb6bSLars-Peter Clausen 			if (channels[i].type == IIO_TIMESTAMP)
164662f4f36cSJonathan Cameron 				iio_dev_opaque->scan_index_timestamp =
1647d967cb6bSLars-Peter Clausen 					channels[i].scan_index;
1648d967cb6bSLars-Peter Clausen 		}
1649d967cb6bSLars-Peter Clausen 		if (indio_dev->masklength && buffer->scan_mask == NULL) {
16503862828aSAndy Shevchenko 			buffer->scan_mask = bitmap_zalloc(indio_dev->masklength,
1651d967cb6bSLars-Peter Clausen 							  GFP_KERNEL);
1652d967cb6bSLars-Peter Clausen 			if (buffer->scan_mask == NULL) {
1653d967cb6bSLars-Peter Clausen 				ret = -ENOMEM;
1654d967cb6bSLars-Peter Clausen 				goto error_cleanup_dynamic;
1655d967cb6bSLars-Peter Clausen 			}
1656d967cb6bSLars-Peter Clausen 		}
1657d967cb6bSLars-Peter Clausen 	}
1658d967cb6bSLars-Peter Clausen 
1659d9a62574SAlexandru Ardelean 	attrn = buffer_attrcount + scan_el_attrcount + ARRAY_SIZE(iio_buffer_attrs);
1660d9a62574SAlexandru Ardelean 	attr = kcalloc(attrn + 1, sizeof(*attr), GFP_KERNEL);
1661e2b4d7acSAlexandru Ardelean 	if (!attr) {
1662e2b4d7acSAlexandru Ardelean 		ret = -ENOMEM;
1663e2b4d7acSAlexandru Ardelean 		goto error_free_scan_mask;
1664e2b4d7acSAlexandru Ardelean 	}
1665e2b4d7acSAlexandru Ardelean 
1666e2b4d7acSAlexandru Ardelean 	memcpy(attr, iio_buffer_attrs, sizeof(iio_buffer_attrs));
1667e2b4d7acSAlexandru Ardelean 	if (!buffer->access->set_length)
1668e2b4d7acSAlexandru Ardelean 		attr[0] = &dev_attr_length_ro.attr;
1669e2b4d7acSAlexandru Ardelean 
1670e2b4d7acSAlexandru Ardelean 	if (buffer->access->flags & INDIO_BUFFER_FLAG_FIXED_WATERMARK)
1671e2b4d7acSAlexandru Ardelean 		attr[2] = &dev_attr_watermark_ro.attr;
1672e2b4d7acSAlexandru Ardelean 
1673e2b4d7acSAlexandru Ardelean 	if (buffer->attrs)
1674e2b4d7acSAlexandru Ardelean 		memcpy(&attr[ARRAY_SIZE(iio_buffer_attrs)], buffer->attrs,
1675e2b4d7acSAlexandru Ardelean 		       sizeof(struct attribute *) * buffer_attrcount);
1676e2b4d7acSAlexandru Ardelean 
1677e2b4d7acSAlexandru Ardelean 	buffer_attrcount += ARRAY_SIZE(iio_buffer_attrs);
16789a2ff800SYang Yingliang 	buffer->buffer_group.attrs = attr;
1679e2b4d7acSAlexandru Ardelean 
168015097c7aSAlexandru Ardelean 	for (i = 0; i < buffer_attrcount; i++) {
168115097c7aSAlexandru Ardelean 		struct attribute *wrapped;
1682d9a62574SAlexandru Ardelean 
168315097c7aSAlexandru Ardelean 		wrapped = iio_buffer_wrap_attr(buffer, attr[i]);
168415097c7aSAlexandru Ardelean 		if (!wrapped) {
168515097c7aSAlexandru Ardelean 			ret = -ENOMEM;
16869a2ff800SYang Yingliang 			goto error_free_buffer_attrs;
168715097c7aSAlexandru Ardelean 		}
168815097c7aSAlexandru Ardelean 		attr[i] = wrapped;
168915097c7aSAlexandru Ardelean 	}
169015097c7aSAlexandru Ardelean 
169115097c7aSAlexandru Ardelean 	attrn = 0;
169215097c7aSAlexandru Ardelean 	list_for_each_entry(p, &buffer->buffer_attr_list, l)
1693d9a62574SAlexandru Ardelean 		attr[attrn++] = &p->dev_attr.attr;
1694d9a62574SAlexandru Ardelean 
1695d9a62574SAlexandru Ardelean 	buffer->buffer_group.name = kasprintf(GFP_KERNEL, "buffer%d", index);
1696d9a62574SAlexandru Ardelean 	if (!buffer->buffer_group.name) {
1697d9a62574SAlexandru Ardelean 		ret = -ENOMEM;
1698d9a62574SAlexandru Ardelean 		goto error_free_buffer_attrs;
1699d9a62574SAlexandru Ardelean 	}
1700d9a62574SAlexandru Ardelean 
1701e2b4d7acSAlexandru Ardelean 	ret = iio_device_register_sysfs_group(indio_dev, &buffer->buffer_group);
1702e2b4d7acSAlexandru Ardelean 	if (ret)
1703d9a62574SAlexandru Ardelean 		goto error_free_buffer_attr_group_name;
1704e2b4d7acSAlexandru Ardelean 
1705d9a62574SAlexandru Ardelean 	/* we only need to register the legacy groups for the first buffer */
1706d9a62574SAlexandru Ardelean 	if (index > 0)
1707d9a62574SAlexandru Ardelean 		return 0;
1708d967cb6bSLars-Peter Clausen 
1709d9a62574SAlexandru Ardelean 	ret = iio_buffer_register_legacy_sysfs_groups(indio_dev, attr,
1710d9a62574SAlexandru Ardelean 						      buffer_attrcount,
1711d9a62574SAlexandru Ardelean 						      scan_el_attrcount);
171232f17172SAlexandru Ardelean 	if (ret)
1713d9a62574SAlexandru Ardelean 		goto error_free_buffer_attr_group_name;
1714d967cb6bSLars-Peter Clausen 
1715d967cb6bSLars-Peter Clausen 	return 0;
1716d967cb6bSLars-Peter Clausen 
1717d9a62574SAlexandru Ardelean error_free_buffer_attr_group_name:
1718d9a62574SAlexandru Ardelean 	kfree(buffer->buffer_group.name);
1719e2b4d7acSAlexandru Ardelean error_free_buffer_attrs:
1720e2b4d7acSAlexandru Ardelean 	kfree(buffer->buffer_group.attrs);
1721d967cb6bSLars-Peter Clausen error_free_scan_mask:
17223862828aSAndy Shevchenko 	bitmap_free(buffer->scan_mask);
1723d967cb6bSLars-Peter Clausen error_cleanup_dynamic:
172415097c7aSAlexandru Ardelean 	iio_free_chan_devattr_list(&buffer->buffer_attr_list);
1725d967cb6bSLars-Peter Clausen 
1726d967cb6bSLars-Peter Clausen 	return ret;
1727d967cb6bSLars-Peter Clausen }
1728d967cb6bSLars-Peter Clausen 
1729486a2508SYang Yingliang static void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer,
1730486a2508SYang Yingliang 					     struct iio_dev *indio_dev,
1731486a2508SYang Yingliang 					     int index)
17320224af85SAlexandru Ardelean {
1733486a2508SYang Yingliang 	if (index == 0)
1734486a2508SYang Yingliang 		iio_buffer_unregister_legacy_sysfs_groups(indio_dev);
17350224af85SAlexandru Ardelean 	bitmap_free(buffer->scan_mask);
17360224af85SAlexandru Ardelean 	kfree(buffer->buffer_group.name);
17370224af85SAlexandru Ardelean 	kfree(buffer->buffer_group.attrs);
17380224af85SAlexandru Ardelean 	iio_free_chan_devattr_list(&buffer->buffer_attr_list);
17390224af85SAlexandru Ardelean }
17400224af85SAlexandru Ardelean 
1741ee708e6bSAlexandru Ardelean int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
1742e16e0a77SAlexandru Ardelean {
1743ee708e6bSAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1744e16e0a77SAlexandru Ardelean 	const struct iio_chan_spec *channels;
1745ee708e6bSAlexandru Ardelean 	struct iio_buffer *buffer;
1746e5cc9840SAndy Shevchenko 	int ret, i, idx;
1747f73f7f4dSAlexandru Ardelean 	size_t sz;
1748e16e0a77SAlexandru Ardelean 
1749e16e0a77SAlexandru Ardelean 	channels = indio_dev->channels;
1750e16e0a77SAlexandru Ardelean 	if (channels) {
1751e16e0a77SAlexandru Ardelean 		int ml = indio_dev->masklength;
1752e16e0a77SAlexandru Ardelean 
1753e16e0a77SAlexandru Ardelean 		for (i = 0; i < indio_dev->num_channels; i++)
1754e16e0a77SAlexandru Ardelean 			ml = max(ml, channels[i].scan_index + 1);
1755e16e0a77SAlexandru Ardelean 		indio_dev->masklength = ml;
1756e16e0a77SAlexandru Ardelean 	}
1757e16e0a77SAlexandru Ardelean 
1758ee708e6bSAlexandru Ardelean 	if (!iio_dev_opaque->attached_buffers_cnt)
1759e16e0a77SAlexandru Ardelean 		return 0;
1760e16e0a77SAlexandru Ardelean 
1761e5cc9840SAndy Shevchenko 	for (idx = 0; idx < iio_dev_opaque->attached_buffers_cnt; idx++) {
1762e5cc9840SAndy Shevchenko 		buffer = iio_dev_opaque->attached_buffers[idx];
1763e5cc9840SAndy Shevchenko 		ret = __iio_buffer_alloc_sysfs_and_mask(buffer, indio_dev, idx);
1764e5cc9840SAndy Shevchenko 		if (ret)
1765ee708e6bSAlexandru Ardelean 			goto error_unwind_sysfs_and_mask;
1766ee708e6bSAlexandru Ardelean 	}
1767f73f7f4dSAlexandru Ardelean 
1768f73f7f4dSAlexandru Ardelean 	sz = sizeof(*(iio_dev_opaque->buffer_ioctl_handler));
1769f73f7f4dSAlexandru Ardelean 	iio_dev_opaque->buffer_ioctl_handler = kzalloc(sz, GFP_KERNEL);
1770f73f7f4dSAlexandru Ardelean 	if (!iio_dev_opaque->buffer_ioctl_handler) {
1771f73f7f4dSAlexandru Ardelean 		ret = -ENOMEM;
1772f73f7f4dSAlexandru Ardelean 		goto error_unwind_sysfs_and_mask;
1773f73f7f4dSAlexandru Ardelean 	}
1774f73f7f4dSAlexandru Ardelean 
1775f73f7f4dSAlexandru Ardelean 	iio_dev_opaque->buffer_ioctl_handler->ioctl = iio_device_buffer_ioctl;
1776f73f7f4dSAlexandru Ardelean 	iio_device_ioctl_handler_register(indio_dev,
1777f73f7f4dSAlexandru Ardelean 					  iio_dev_opaque->buffer_ioctl_handler);
1778e16e0a77SAlexandru Ardelean 
1779ee708e6bSAlexandru Ardelean 	return 0;
1780ff3f7e04SAlexandru Ardelean 
1781ee708e6bSAlexandru Ardelean error_unwind_sysfs_and_mask:
1782e5cc9840SAndy Shevchenko 	while (idx--) {
1783e5cc9840SAndy Shevchenko 		buffer = iio_dev_opaque->attached_buffers[idx];
1784e5cc9840SAndy Shevchenko 		__iio_buffer_free_sysfs_and_mask(buffer, indio_dev, idx);
1785ee708e6bSAlexandru Ardelean 	}
1786ee708e6bSAlexandru Ardelean 	return ret;
1787ee708e6bSAlexandru Ardelean }
1788ee708e6bSAlexandru Ardelean 
1789ee708e6bSAlexandru Ardelean void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev)
1790ee708e6bSAlexandru Ardelean {
1791ee708e6bSAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1792ee708e6bSAlexandru Ardelean 	struct iio_buffer *buffer;
1793ee708e6bSAlexandru Ardelean 	int i;
1794ee708e6bSAlexandru Ardelean 
1795ee708e6bSAlexandru Ardelean 	if (!iio_dev_opaque->attached_buffers_cnt)
1796d967cb6bSLars-Peter Clausen 		return;
1797d967cb6bSLars-Peter Clausen 
1798f73f7f4dSAlexandru Ardelean 	iio_device_ioctl_handler_unregister(iio_dev_opaque->buffer_ioctl_handler);
1799f73f7f4dSAlexandru Ardelean 	kfree(iio_dev_opaque->buffer_ioctl_handler);
1800f73f7f4dSAlexandru Ardelean 
1801ee708e6bSAlexandru Ardelean 	for (i = iio_dev_opaque->attached_buffers_cnt - 1; i >= 0; i--) {
1802ee708e6bSAlexandru Ardelean 		buffer = iio_dev_opaque->attached_buffers[i];
1803486a2508SYang Yingliang 		__iio_buffer_free_sysfs_and_mask(buffer, indio_dev, i);
1804d967cb6bSLars-Peter Clausen 	}
1805ee708e6bSAlexandru Ardelean }
1806ee708e6bSAlexandru Ardelean 
1807a980e046SJonathan Cameron /**
180881636632SLars-Peter Clausen  * iio_validate_scan_mask_onehot() - Validates that exactly one channel is selected
180981636632SLars-Peter Clausen  * @indio_dev: the iio device
181081636632SLars-Peter Clausen  * @mask: scan mask to be checked
181181636632SLars-Peter Clausen  *
181281636632SLars-Peter Clausen  * Return true if exactly one bit is set in the scan mask, false otherwise. It
181381636632SLars-Peter Clausen  * can be used for devices where only one channel can be active for sampling at
181481636632SLars-Peter Clausen  * a time.
181581636632SLars-Peter Clausen  */
181681636632SLars-Peter Clausen bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev,
181781636632SLars-Peter Clausen 	const unsigned long *mask)
181881636632SLars-Peter Clausen {
181981636632SLars-Peter Clausen 	return bitmap_weight(mask, indio_dev->masklength) == 1;
182081636632SLars-Peter Clausen }
182181636632SLars-Peter Clausen EXPORT_SYMBOL_GPL(iio_validate_scan_mask_onehot);
182281636632SLars-Peter Clausen 
18235d65d920SLars-Peter Clausen static const void *iio_demux(struct iio_buffer *buffer,
18245d65d920SLars-Peter Clausen 				 const void *datain)
1825a980e046SJonathan Cameron {
1826a980e046SJonathan Cameron 	struct iio_demux_table *t;
1827a980e046SJonathan Cameron 
1828a980e046SJonathan Cameron 	if (list_empty(&buffer->demux_list))
1829a980e046SJonathan Cameron 		return datain;
1830a980e046SJonathan Cameron 	list_for_each_entry(t, &buffer->demux_list, l)
1831a980e046SJonathan Cameron 		memcpy(buffer->demux_bounce + t->to,
1832a980e046SJonathan Cameron 		       datain + t->from, t->length);
1833a980e046SJonathan Cameron 
1834a980e046SJonathan Cameron 	return buffer->demux_bounce;
1835a980e046SJonathan Cameron }
1836a980e046SJonathan Cameron 
18375d65d920SLars-Peter Clausen static int iio_push_to_buffer(struct iio_buffer *buffer, const void *data)
1838a980e046SJonathan Cameron {
18395d65d920SLars-Peter Clausen 	const void *dataout = iio_demux(buffer, data);
184037d34556SJosselin Costanzi 	int ret;
1841a980e046SJonathan Cameron 
184237d34556SJosselin Costanzi 	ret = buffer->access->store_to(buffer, dataout);
184337d34556SJosselin Costanzi 	if (ret)
184437d34556SJosselin Costanzi 		return ret;
184537d34556SJosselin Costanzi 
184637d34556SJosselin Costanzi 	/*
184737d34556SJosselin Costanzi 	 * We can't just test for watermark to decide if we wake the poll queue
184837d34556SJosselin Costanzi 	 * because read may request less samples than the watermark.
184937d34556SJosselin Costanzi 	 */
1850a9a08845SLinus Torvalds 	wake_up_interruptible_poll(&buffer->pollq, EPOLLIN | EPOLLRDNORM);
185137d34556SJosselin Costanzi 	return 0;
1852a980e046SJonathan Cameron }
1853a980e046SJonathan Cameron 
1854315a19ecSJonathan Cameron /**
1855315a19ecSJonathan Cameron  * iio_push_to_buffers() - push to a registered buffer.
1856315a19ecSJonathan Cameron  * @indio_dev:		iio_dev structure for device.
1857315a19ecSJonathan Cameron  * @data:		Full scan.
1858315a19ecSJonathan Cameron  */
18595d65d920SLars-Peter Clausen int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data)
186084b36ce5SJonathan Cameron {
18616a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
186284b36ce5SJonathan Cameron 	int ret;
186384b36ce5SJonathan Cameron 	struct iio_buffer *buf;
186484b36ce5SJonathan Cameron 
18656a8c6b26SAlexandru Ardelean 	list_for_each_entry(buf, &iio_dev_opaque->buffer_list, buffer_list) {
186684b36ce5SJonathan Cameron 		ret = iio_push_to_buffer(buf, data);
186784b36ce5SJonathan Cameron 		if (ret < 0)
186884b36ce5SJonathan Cameron 			return ret;
186984b36ce5SJonathan Cameron 	}
187084b36ce5SJonathan Cameron 
187184b36ce5SJonathan Cameron 	return 0;
187284b36ce5SJonathan Cameron }
187384b36ce5SJonathan Cameron EXPORT_SYMBOL_GPL(iio_push_to_buffers);
187484b36ce5SJonathan Cameron 
18759e69c935SLars-Peter Clausen /**
187695ec3fdfSJonathan Cameron  * iio_push_to_buffers_with_ts_unaligned() - push to registered buffer,
187795ec3fdfSJonathan Cameron  *    no alignment or space requirements.
187895ec3fdfSJonathan Cameron  * @indio_dev:		iio_dev structure for device.
187995ec3fdfSJonathan Cameron  * @data:		channel data excluding the timestamp.
188095ec3fdfSJonathan Cameron  * @data_sz:		size of data.
188195ec3fdfSJonathan Cameron  * @timestamp:		timestamp for the sample data.
188295ec3fdfSJonathan Cameron  *
188395ec3fdfSJonathan Cameron  * This special variant of iio_push_to_buffers_with_timestamp() does
188495ec3fdfSJonathan Cameron  * not require space for the timestamp, or 8 byte alignment of data.
188595ec3fdfSJonathan Cameron  * It does however require an allocation on first call and additional
188695ec3fdfSJonathan Cameron  * copies on all calls, so should be avoided if possible.
188795ec3fdfSJonathan Cameron  */
188895ec3fdfSJonathan Cameron int iio_push_to_buffers_with_ts_unaligned(struct iio_dev *indio_dev,
188995ec3fdfSJonathan Cameron 					  const void *data,
189095ec3fdfSJonathan Cameron 					  size_t data_sz,
189195ec3fdfSJonathan Cameron 					  int64_t timestamp)
189295ec3fdfSJonathan Cameron {
189395ec3fdfSJonathan Cameron 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
189495ec3fdfSJonathan Cameron 
189595ec3fdfSJonathan Cameron 	/*
189695ec3fdfSJonathan Cameron 	 * Conservative estimate - we can always safely copy the minimum
189795ec3fdfSJonathan Cameron 	 * of either the data provided or the length of the destination buffer.
189895ec3fdfSJonathan Cameron 	 * This relaxed limit allows the calling drivers to be lax about
189995ec3fdfSJonathan Cameron 	 * tracking the size of the data they are pushing, at the cost of
190095ec3fdfSJonathan Cameron 	 * unnecessary copying of padding.
190195ec3fdfSJonathan Cameron 	 */
190295ec3fdfSJonathan Cameron 	data_sz = min_t(size_t, indio_dev->scan_bytes, data_sz);
190395ec3fdfSJonathan Cameron 	if (iio_dev_opaque->bounce_buffer_size !=  indio_dev->scan_bytes) {
190495ec3fdfSJonathan Cameron 		void *bb;
190595ec3fdfSJonathan Cameron 
190695ec3fdfSJonathan Cameron 		bb = devm_krealloc(&indio_dev->dev,
190795ec3fdfSJonathan Cameron 				   iio_dev_opaque->bounce_buffer,
190895ec3fdfSJonathan Cameron 				   indio_dev->scan_bytes, GFP_KERNEL);
190995ec3fdfSJonathan Cameron 		if (!bb)
191095ec3fdfSJonathan Cameron 			return -ENOMEM;
191195ec3fdfSJonathan Cameron 		iio_dev_opaque->bounce_buffer = bb;
191295ec3fdfSJonathan Cameron 		iio_dev_opaque->bounce_buffer_size = indio_dev->scan_bytes;
191395ec3fdfSJonathan Cameron 	}
191495ec3fdfSJonathan Cameron 	memcpy(iio_dev_opaque->bounce_buffer, data, data_sz);
191595ec3fdfSJonathan Cameron 	return iio_push_to_buffers_with_timestamp(indio_dev,
191695ec3fdfSJonathan Cameron 						  iio_dev_opaque->bounce_buffer,
191795ec3fdfSJonathan Cameron 						  timestamp);
191895ec3fdfSJonathan Cameron }
191995ec3fdfSJonathan Cameron EXPORT_SYMBOL_GPL(iio_push_to_buffers_with_ts_unaligned);
192095ec3fdfSJonathan Cameron 
192195ec3fdfSJonathan Cameron /**
19229e69c935SLars-Peter Clausen  * iio_buffer_release() - Free a buffer's resources
19239e69c935SLars-Peter Clausen  * @ref: Pointer to the kref embedded in the iio_buffer struct
19249e69c935SLars-Peter Clausen  *
19259e69c935SLars-Peter Clausen  * This function is called when the last reference to the buffer has been
19269e69c935SLars-Peter Clausen  * dropped. It will typically free all resources allocated by the buffer. Do not
19279e69c935SLars-Peter Clausen  * call this function manually, always use iio_buffer_put() when done using a
19289e69c935SLars-Peter Clausen  * buffer.
19299e69c935SLars-Peter Clausen  */
19309e69c935SLars-Peter Clausen static void iio_buffer_release(struct kref *ref)
19319e69c935SLars-Peter Clausen {
19329e69c935SLars-Peter Clausen 	struct iio_buffer *buffer = container_of(ref, struct iio_buffer, ref);
19339e69c935SLars-Peter Clausen 
19349e69c935SLars-Peter Clausen 	buffer->access->release(buffer);
19359e69c935SLars-Peter Clausen }
19369e69c935SLars-Peter Clausen 
19379e69c935SLars-Peter Clausen /**
19389e69c935SLars-Peter Clausen  * iio_buffer_get() - Grab a reference to the buffer
19399e69c935SLars-Peter Clausen  * @buffer: The buffer to grab a reference for, may be NULL
19409e69c935SLars-Peter Clausen  *
19419e69c935SLars-Peter Clausen  * Returns the pointer to the buffer that was passed into the function.
19429e69c935SLars-Peter Clausen  */
19439e69c935SLars-Peter Clausen struct iio_buffer *iio_buffer_get(struct iio_buffer *buffer)
19449e69c935SLars-Peter Clausen {
19459e69c935SLars-Peter Clausen 	if (buffer)
19469e69c935SLars-Peter Clausen 		kref_get(&buffer->ref);
19479e69c935SLars-Peter Clausen 
19489e69c935SLars-Peter Clausen 	return buffer;
19499e69c935SLars-Peter Clausen }
19509e69c935SLars-Peter Clausen EXPORT_SYMBOL_GPL(iio_buffer_get);
19519e69c935SLars-Peter Clausen 
19529e69c935SLars-Peter Clausen /**
19539e69c935SLars-Peter Clausen  * iio_buffer_put() - Release the reference to the buffer
19549e69c935SLars-Peter Clausen  * @buffer: The buffer to release the reference for, may be NULL
19559e69c935SLars-Peter Clausen  */
19569e69c935SLars-Peter Clausen void iio_buffer_put(struct iio_buffer *buffer)
19579e69c935SLars-Peter Clausen {
19589e69c935SLars-Peter Clausen 	if (buffer)
19599e69c935SLars-Peter Clausen 		kref_put(&buffer->ref, iio_buffer_release);
19609e69c935SLars-Peter Clausen }
19619e69c935SLars-Peter Clausen EXPORT_SYMBOL_GPL(iio_buffer_put);
19622b827ad5SJonathan Cameron 
19632b827ad5SJonathan Cameron /**
19642b827ad5SJonathan Cameron  * iio_device_attach_buffer - Attach a buffer to a IIO device
19652b827ad5SJonathan Cameron  * @indio_dev: The device the buffer should be attached to
19662b827ad5SJonathan Cameron  * @buffer: The buffer to attach to the device
19672b827ad5SJonathan Cameron  *
1968ee708e6bSAlexandru Ardelean  * Return 0 if successful, negative if error.
1969ee708e6bSAlexandru Ardelean  *
19702b827ad5SJonathan Cameron  * This function attaches a buffer to a IIO device. The buffer stays attached to
1971ee708e6bSAlexandru Ardelean  * the device until the device is freed. For legacy reasons, the first attached
1972ee708e6bSAlexandru Ardelean  * buffer will also be assigned to 'indio_dev->buffer'.
1973218bc53dSAlexandru Ardelean  * The array allocated here, will be free'd via the iio_device_detach_buffers()
1974218bc53dSAlexandru Ardelean  * call which is handled by the iio_device_free().
19752b827ad5SJonathan Cameron  */
1976ee708e6bSAlexandru Ardelean int iio_device_attach_buffer(struct iio_dev *indio_dev,
19772b827ad5SJonathan Cameron 			     struct iio_buffer *buffer)
19782b827ad5SJonathan Cameron {
1979ee708e6bSAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1980ee708e6bSAlexandru Ardelean 	struct iio_buffer **new, **old = iio_dev_opaque->attached_buffers;
1981ee708e6bSAlexandru Ardelean 	unsigned int cnt = iio_dev_opaque->attached_buffers_cnt;
1982ee708e6bSAlexandru Ardelean 
1983ee708e6bSAlexandru Ardelean 	cnt++;
1984ee708e6bSAlexandru Ardelean 
1985ee708e6bSAlexandru Ardelean 	new = krealloc(old, sizeof(*new) * cnt, GFP_KERNEL);
1986ee708e6bSAlexandru Ardelean 	if (!new)
1987ee708e6bSAlexandru Ardelean 		return -ENOMEM;
1988ee708e6bSAlexandru Ardelean 	iio_dev_opaque->attached_buffers = new;
1989ee708e6bSAlexandru Ardelean 
1990ee708e6bSAlexandru Ardelean 	buffer = iio_buffer_get(buffer);
1991ee708e6bSAlexandru Ardelean 
1992ee708e6bSAlexandru Ardelean 	/* first buffer is legacy; attach it to the IIO device directly */
1993ee708e6bSAlexandru Ardelean 	if (!indio_dev->buffer)
1994ee708e6bSAlexandru Ardelean 		indio_dev->buffer = buffer;
1995ee708e6bSAlexandru Ardelean 
1996ee708e6bSAlexandru Ardelean 	iio_dev_opaque->attached_buffers[cnt - 1] = buffer;
1997ee708e6bSAlexandru Ardelean 	iio_dev_opaque->attached_buffers_cnt = cnt;
1998ee708e6bSAlexandru Ardelean 
1999ee708e6bSAlexandru Ardelean 	return 0;
20002b827ad5SJonathan Cameron }
20012b827ad5SJonathan Cameron EXPORT_SYMBOL_GPL(iio_device_attach_buffer);
2002