xref: /openbmc/linux/drivers/iio/industrialio-buffer.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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 
iio_buffer_is_active(struct iio_buffer * buf)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 
iio_buffer_data_available(struct iio_buffer * buf)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 
iio_buffer_flush_hwfifo(struct iio_dev * indio_dev,struct iio_buffer * buf,size_t required)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 
iio_buffer_ready(struct iio_dev * indio_dev,struct iio_buffer * buf,size_t to_wait,int to_flush)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  **/
iio_buffer_read(struct file * filp,char __user * buf,size_t n,loff_t * f_ps)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 
iio_buffer_space_available(struct iio_buffer * buf)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 
iio_buffer_write(struct file * filp,const char __user * buf,size_t n,loff_t * f_ps)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)
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 
206*3da18141SNuno Sá 			if (filp->f_flags & O_NONBLOCK) {
207*3da18141SNuno Sá 				if (!written)
208*3da18141SNuno Sá 					ret = -EAGAIN;
209*3da18141SNuno Sá 				break;
210*3da18141SNuno Sá 			}
211*3da18141SNuno Sá 
2129eeee3b0SMihail Chindris 			wait_woken(&wait, TASK_INTERRUPTIBLE,
2139eeee3b0SMihail Chindris 				   MAX_SCHEDULE_TIMEOUT);
2149eeee3b0SMihail Chindris 			continue;
2159eeee3b0SMihail Chindris 		}
2169eeee3b0SMihail Chindris 
2179eeee3b0SMihail Chindris 		ret = rb->access->write(rb, n - written, buf + written);
218*3da18141SNuno Sá 		if (ret < 0)
219*3da18141SNuno Sá 			break;
2209eeee3b0SMihail Chindris 
2219eeee3b0SMihail Chindris 		written += ret;
222*3da18141SNuno Sá 
223*3da18141SNuno Sá 	} while (written != n);
2249eeee3b0SMihail Chindris 	remove_wait_queue(&rb->pollq, &wait);
2259eeee3b0SMihail Chindris 
226b5184a26SNuno Sá 	return ret < 0 ? ret : written;
2279eeee3b0SMihail Chindris }
2289eeee3b0SMihail Chindris 
229a980e046SJonathan Cameron /**
230a980e046SJonathan Cameron  * iio_buffer_poll() - poll the buffer to find out if it has data
2310123635aSCristina Opriceana  * @filp:	File structure pointer for device access
2320123635aSCristina Opriceana  * @wait:	Poll table structure pointer for which the driver adds
2330123635aSCristina Opriceana  *		a wait queue
2340123635aSCristina Opriceana  *
235a9a08845SLinus Torvalds  * Return: (EPOLLIN | EPOLLRDNORM) if data is available for reading
2360123635aSCristina Opriceana  *	   or 0 for other cases
237a980e046SJonathan Cameron  */
iio_buffer_poll(struct file * filp,struct poll_table_struct * wait)238f73f7f4dSAlexandru Ardelean static __poll_t iio_buffer_poll(struct file *filp,
239a980e046SJonathan Cameron 				struct poll_table_struct *wait)
240a980e046SJonathan Cameron {
241be24dcb1SAlexandru Ardelean 	struct iio_dev_buffer_pair *ib = filp->private_data;
242be24dcb1SAlexandru Ardelean 	struct iio_buffer *rb = ib->buffer;
243be24dcb1SAlexandru Ardelean 	struct iio_dev *indio_dev = ib->indio_dev;
244a980e046SJonathan Cameron 
2454cd140bdSStefan Windfeldt-Prytz 	if (!indio_dev->info || !rb)
2461bdc0293SCristina Opriceana 		return 0;
247f18e7a06SLars-Peter Clausen 
248a980e046SJonathan Cameron 	poll_wait(filp, &rb->pollq, wait);
2499eeee3b0SMihail Chindris 
2509eeee3b0SMihail Chindris 	switch (rb->direction) {
2519eeee3b0SMihail Chindris 	case IIO_BUFFER_DIRECTION_IN:
252f4f4673bSOctavian Purdila 		if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0))
253a9a08845SLinus Torvalds 			return EPOLLIN | EPOLLRDNORM;
2549eeee3b0SMihail Chindris 		break;
2559eeee3b0SMihail Chindris 	case IIO_BUFFER_DIRECTION_OUT:
2569eeee3b0SMihail Chindris 		if (iio_buffer_space_available(rb))
2579eeee3b0SMihail Chindris 			return EPOLLOUT | EPOLLWRNORM;
2589eeee3b0SMihail Chindris 		break;
2599eeee3b0SMihail Chindris 	}
2609eeee3b0SMihail Chindris 
261a980e046SJonathan Cameron 	return 0;
262a980e046SJonathan Cameron }
263a980e046SJonathan Cameron 
iio_buffer_read_wrapper(struct file * filp,char __user * buf,size_t n,loff_t * f_ps)264f73f7f4dSAlexandru Ardelean ssize_t iio_buffer_read_wrapper(struct file *filp, char __user *buf,
265f73f7f4dSAlexandru Ardelean 				size_t n, loff_t *f_ps)
266f73f7f4dSAlexandru Ardelean {
267f73f7f4dSAlexandru Ardelean 	struct iio_dev_buffer_pair *ib = filp->private_data;
268f73f7f4dSAlexandru Ardelean 	struct iio_buffer *rb = ib->buffer;
269f73f7f4dSAlexandru Ardelean 
270f73f7f4dSAlexandru Ardelean 	/* check if buffer was opened through new API */
271f73f7f4dSAlexandru Ardelean 	if (test_bit(IIO_BUSY_BIT_POS, &rb->flags))
272f73f7f4dSAlexandru Ardelean 		return -EBUSY;
273f73f7f4dSAlexandru Ardelean 
274f73f7f4dSAlexandru Ardelean 	return iio_buffer_read(filp, buf, n, f_ps);
275f73f7f4dSAlexandru Ardelean }
276f73f7f4dSAlexandru Ardelean 
iio_buffer_write_wrapper(struct file * filp,const char __user * buf,size_t n,loff_t * f_ps)2779eeee3b0SMihail Chindris ssize_t iio_buffer_write_wrapper(struct file *filp, const char __user *buf,
2789eeee3b0SMihail Chindris 				 size_t n, loff_t *f_ps)
2799eeee3b0SMihail Chindris {
2809eeee3b0SMihail Chindris 	struct iio_dev_buffer_pair *ib = filp->private_data;
2819eeee3b0SMihail Chindris 	struct iio_buffer *rb = ib->buffer;
2829eeee3b0SMihail Chindris 
2839eeee3b0SMihail Chindris 	/* check if buffer was opened through new API */
2849eeee3b0SMihail Chindris 	if (test_bit(IIO_BUSY_BIT_POS, &rb->flags))
2859eeee3b0SMihail Chindris 		return -EBUSY;
2869eeee3b0SMihail Chindris 
2879eeee3b0SMihail Chindris 	return iio_buffer_write(filp, buf, n, f_ps);
2889eeee3b0SMihail Chindris }
2899eeee3b0SMihail Chindris 
iio_buffer_poll_wrapper(struct file * filp,struct poll_table_struct * wait)290f73f7f4dSAlexandru Ardelean __poll_t iio_buffer_poll_wrapper(struct file *filp,
291f73f7f4dSAlexandru Ardelean 				 struct poll_table_struct *wait)
292f73f7f4dSAlexandru Ardelean {
293f73f7f4dSAlexandru Ardelean 	struct iio_dev_buffer_pair *ib = filp->private_data;
294f73f7f4dSAlexandru Ardelean 	struct iio_buffer *rb = ib->buffer;
295f73f7f4dSAlexandru Ardelean 
296f73f7f4dSAlexandru Ardelean 	/* check if buffer was opened through new API */
297f73f7f4dSAlexandru Ardelean 	if (test_bit(IIO_BUSY_BIT_POS, &rb->flags))
298f73f7f4dSAlexandru Ardelean 		return 0;
299f73f7f4dSAlexandru Ardelean 
300f73f7f4dSAlexandru Ardelean 	return iio_buffer_poll(filp, wait);
301f73f7f4dSAlexandru Ardelean }
302f73f7f4dSAlexandru Ardelean 
303d2f0a48fSLars-Peter Clausen /**
304d2f0a48fSLars-Peter Clausen  * iio_buffer_wakeup_poll - Wakes up the buffer waitqueue
305d2f0a48fSLars-Peter Clausen  * @indio_dev: The IIO device
306d2f0a48fSLars-Peter Clausen  *
307d2f0a48fSLars-Peter Clausen  * Wakes up the event waitqueue used for poll(). Should usually
308d2f0a48fSLars-Peter Clausen  * be called when the device is unregistered.
309d2f0a48fSLars-Peter Clausen  */
iio_buffer_wakeup_poll(struct iio_dev * indio_dev)310d2f0a48fSLars-Peter Clausen void iio_buffer_wakeup_poll(struct iio_dev *indio_dev)
311d2f0a48fSLars-Peter Clausen {
312ee708e6bSAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
313ee708e6bSAlexandru Ardelean 	struct iio_buffer *buffer;
314ee708e6bSAlexandru Ardelean 	unsigned int i;
315ff3f7e04SAlexandru Ardelean 
316ee708e6bSAlexandru Ardelean 	for (i = 0; i < iio_dev_opaque->attached_buffers_cnt; i++) {
317ee708e6bSAlexandru Ardelean 		buffer = iio_dev_opaque->attached_buffers[i];
318ff3f7e04SAlexandru Ardelean 		wake_up(&buffer->pollq);
319d2f0a48fSLars-Peter Clausen 	}
320ee708e6bSAlexandru Ardelean }
321d2f0a48fSLars-Peter Clausen 
iio_pop_from_buffer(struct iio_buffer * buffer,void * data)3229eeee3b0SMihail Chindris int iio_pop_from_buffer(struct iio_buffer *buffer, void *data)
3239eeee3b0SMihail Chindris {
3249eeee3b0SMihail Chindris 	if (!buffer || !buffer->access || !buffer->access->remove_from)
3259eeee3b0SMihail Chindris 		return -EINVAL;
3269eeee3b0SMihail Chindris 
3279eeee3b0SMihail Chindris 	return buffer->access->remove_from(buffer, data);
3289eeee3b0SMihail Chindris }
3299eeee3b0SMihail Chindris EXPORT_SYMBOL_GPL(iio_pop_from_buffer);
3309eeee3b0SMihail Chindris 
iio_buffer_init(struct iio_buffer * buffer)331a980e046SJonathan Cameron void iio_buffer_init(struct iio_buffer *buffer)
332a980e046SJonathan Cameron {
333a980e046SJonathan Cameron 	INIT_LIST_HEAD(&buffer->demux_list);
334705ee2c9SLars-Peter Clausen 	INIT_LIST_HEAD(&buffer->buffer_list);
335a980e046SJonathan Cameron 	init_waitqueue_head(&buffer->pollq);
3369e69c935SLars-Peter Clausen 	kref_init(&buffer->ref);
3374a605357SLars-Peter Clausen 	if (!buffer->watermark)
33837d34556SJosselin Costanzi 		buffer->watermark = 1;
339a980e046SJonathan Cameron }
340a980e046SJonathan Cameron EXPORT_SYMBOL(iio_buffer_init);
341a980e046SJonathan Cameron 
iio_device_detach_buffers(struct iio_dev * indio_dev)342218bc53dSAlexandru Ardelean void iio_device_detach_buffers(struct iio_dev *indio_dev)
343ee708e6bSAlexandru Ardelean {
344ee708e6bSAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
345ee708e6bSAlexandru Ardelean 	struct iio_buffer *buffer;
346ee708e6bSAlexandru Ardelean 	unsigned int i;
347ee708e6bSAlexandru Ardelean 
348ee708e6bSAlexandru Ardelean 	for (i = 0; i < iio_dev_opaque->attached_buffers_cnt; i++) {
349ee708e6bSAlexandru Ardelean 		buffer = iio_dev_opaque->attached_buffers[i];
350ee708e6bSAlexandru Ardelean 		iio_buffer_put(buffer);
351ee708e6bSAlexandru Ardelean 	}
352218bc53dSAlexandru Ardelean 
353218bc53dSAlexandru Ardelean 	kfree(iio_dev_opaque->attached_buffers);
354ee708e6bSAlexandru Ardelean }
355ee708e6bSAlexandru Ardelean 
iio_show_scan_index(struct device * dev,struct device_attribute * attr,char * buf)356a980e046SJonathan Cameron static ssize_t iio_show_scan_index(struct device *dev,
357a980e046SJonathan Cameron 				   struct device_attribute *attr,
358a980e046SJonathan Cameron 				   char *buf)
359a980e046SJonathan Cameron {
36083ca56b6SLars-Peter Clausen 	return sysfs_emit(buf, "%u\n", to_iio_dev_attr(attr)->c->scan_index);
361a980e046SJonathan Cameron }
362a980e046SJonathan Cameron 
iio_show_fixed_type(struct device * dev,struct device_attribute * attr,char * buf)363a980e046SJonathan Cameron static ssize_t iio_show_fixed_type(struct device *dev,
364a980e046SJonathan Cameron 				   struct device_attribute *attr,
365a980e046SJonathan Cameron 				   char *buf)
366a980e046SJonathan Cameron {
367a980e046SJonathan Cameron 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
368a980e046SJonathan Cameron 	u8 type = this_attr->c->scan_type.endianness;
369a980e046SJonathan Cameron 
370a980e046SJonathan Cameron 	if (type == IIO_CPU) {
371a980e046SJonathan Cameron #ifdef __LITTLE_ENDIAN
372a980e046SJonathan Cameron 		type = IIO_LE;
373a980e046SJonathan Cameron #else
374a980e046SJonathan Cameron 		type = IIO_BE;
375a980e046SJonathan Cameron #endif
376a980e046SJonathan Cameron 	}
3770ee8546aSSrinivas Pandruvada 	if (this_attr->c->scan_type.repeat > 1)
37883ca56b6SLars-Peter Clausen 		return sysfs_emit(buf, "%s:%c%d/%dX%d>>%u\n",
3790ee8546aSSrinivas Pandruvada 		       iio_endian_prefix[type],
3800ee8546aSSrinivas Pandruvada 		       this_attr->c->scan_type.sign,
3810ee8546aSSrinivas Pandruvada 		       this_attr->c->scan_type.realbits,
3820ee8546aSSrinivas Pandruvada 		       this_attr->c->scan_type.storagebits,
3830ee8546aSSrinivas Pandruvada 		       this_attr->c->scan_type.repeat,
3840ee8546aSSrinivas Pandruvada 		       this_attr->c->scan_type.shift);
3850ee8546aSSrinivas Pandruvada 	else
38683ca56b6SLars-Peter Clausen 		return sysfs_emit(buf, "%s:%c%d/%d>>%u\n",
387a980e046SJonathan Cameron 		       iio_endian_prefix[type],
388a980e046SJonathan Cameron 		       this_attr->c->scan_type.sign,
389a980e046SJonathan Cameron 		       this_attr->c->scan_type.realbits,
390a980e046SJonathan Cameron 		       this_attr->c->scan_type.storagebits,
391a980e046SJonathan Cameron 		       this_attr->c->scan_type.shift);
392a980e046SJonathan Cameron }
393a980e046SJonathan Cameron 
iio_scan_el_show(struct device * dev,struct device_attribute * attr,char * buf)394a980e046SJonathan Cameron static ssize_t iio_scan_el_show(struct device *dev,
395a980e046SJonathan Cameron 				struct device_attribute *attr,
396a980e046SJonathan Cameron 				char *buf)
397a980e046SJonathan Cameron {
398a980e046SJonathan Cameron 	int ret;
39915097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
400a980e046SJonathan Cameron 
4012076a20fSAlec Berg 	/* Ensure ret is 0 or 1. */
4022076a20fSAlec Berg 	ret = !!test_bit(to_iio_dev_attr(attr)->address,
403ff3f7e04SAlexandru Ardelean 		       buffer->scan_mask);
404a980e046SJonathan Cameron 
40583ca56b6SLars-Peter Clausen 	return sysfs_emit(buf, "%d\n", ret);
406a980e046SJonathan Cameron }
407a980e046SJonathan Cameron 
408217a5cf0SLars-Peter Clausen /* Note NULL used as error indicator as it doesn't make sense. */
iio_scan_mask_match(const unsigned long * av_masks,unsigned int masklength,const unsigned long * mask,bool strict)409217a5cf0SLars-Peter Clausen static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks,
410217a5cf0SLars-Peter Clausen 						unsigned int masklength,
4111e1ec286SLars-Peter Clausen 						const unsigned long *mask,
4121e1ec286SLars-Peter Clausen 						bool strict)
413217a5cf0SLars-Peter Clausen {
414217a5cf0SLars-Peter Clausen 	if (bitmap_empty(mask, masklength))
415217a5cf0SLars-Peter Clausen 		return NULL;
416217a5cf0SLars-Peter Clausen 	while (*av_masks) {
4171e1ec286SLars-Peter Clausen 		if (strict) {
4181e1ec286SLars-Peter Clausen 			if (bitmap_equal(mask, av_masks, masklength))
4191e1ec286SLars-Peter Clausen 				return av_masks;
4201e1ec286SLars-Peter Clausen 		} else {
421217a5cf0SLars-Peter Clausen 			if (bitmap_subset(mask, av_masks, masklength))
422217a5cf0SLars-Peter Clausen 				return av_masks;
4231e1ec286SLars-Peter Clausen 		}
424217a5cf0SLars-Peter Clausen 		av_masks += BITS_TO_LONGS(masklength);
425217a5cf0SLars-Peter Clausen 	}
426217a5cf0SLars-Peter Clausen 	return NULL;
427217a5cf0SLars-Peter Clausen }
428217a5cf0SLars-Peter Clausen 
iio_validate_scan_mask(struct iio_dev * indio_dev,const unsigned long * mask)429217a5cf0SLars-Peter Clausen static bool iio_validate_scan_mask(struct iio_dev *indio_dev,
430217a5cf0SLars-Peter Clausen 				   const unsigned long *mask)
431217a5cf0SLars-Peter Clausen {
432217a5cf0SLars-Peter Clausen 	if (!indio_dev->setup_ops->validate_scan_mask)
433217a5cf0SLars-Peter Clausen 		return true;
434217a5cf0SLars-Peter Clausen 
435217a5cf0SLars-Peter Clausen 	return indio_dev->setup_ops->validate_scan_mask(indio_dev, mask);
436217a5cf0SLars-Peter Clausen }
437217a5cf0SLars-Peter Clausen 
438217a5cf0SLars-Peter Clausen /**
439217a5cf0SLars-Peter Clausen  * iio_scan_mask_set() - set particular bit in the scan mask
440217a5cf0SLars-Peter Clausen  * @indio_dev: the iio device
441217a5cf0SLars-Peter Clausen  * @buffer: the buffer whose scan mask we are interested in
442217a5cf0SLars-Peter Clausen  * @bit: the bit to be set.
443217a5cf0SLars-Peter Clausen  *
444217a5cf0SLars-Peter Clausen  * Note that at this point we have no way of knowing what other
445217a5cf0SLars-Peter Clausen  * buffers might request, hence this code only verifies that the
446217a5cf0SLars-Peter Clausen  * individual buffers request is plausible.
447217a5cf0SLars-Peter Clausen  */
iio_scan_mask_set(struct iio_dev * indio_dev,struct iio_buffer * buffer,int bit)448217a5cf0SLars-Peter Clausen static int iio_scan_mask_set(struct iio_dev *indio_dev,
449217a5cf0SLars-Peter Clausen 			     struct iio_buffer *buffer, int bit)
450217a5cf0SLars-Peter Clausen {
451217a5cf0SLars-Peter Clausen 	const unsigned long *mask;
452217a5cf0SLars-Peter Clausen 	unsigned long *trialmask;
453217a5cf0SLars-Peter Clausen 
454d21fed06SChristophe JAILLET 	if (!indio_dev->masklength) {
455d21fed06SChristophe JAILLET 		WARN(1, "Trying to set scanmask prior to registering buffer\n");
456d21fed06SChristophe JAILLET 		return -EINVAL;
457d21fed06SChristophe JAILLET 	}
458d21fed06SChristophe JAILLET 
45945851650SChristophe JAILLET 	trialmask = bitmap_alloc(indio_dev->masklength, GFP_KERNEL);
46045851650SChristophe JAILLET 	if (!trialmask)
461217a5cf0SLars-Peter Clausen 		return -ENOMEM;
462217a5cf0SLars-Peter Clausen 	bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength);
463217a5cf0SLars-Peter Clausen 	set_bit(bit, trialmask);
464217a5cf0SLars-Peter Clausen 
465217a5cf0SLars-Peter Clausen 	if (!iio_validate_scan_mask(indio_dev, trialmask))
466217a5cf0SLars-Peter Clausen 		goto err_invalid_mask;
467217a5cf0SLars-Peter Clausen 
468217a5cf0SLars-Peter Clausen 	if (indio_dev->available_scan_masks) {
469217a5cf0SLars-Peter Clausen 		mask = iio_scan_mask_match(indio_dev->available_scan_masks,
470217a5cf0SLars-Peter Clausen 					   indio_dev->masklength,
4711e1ec286SLars-Peter Clausen 					   trialmask, false);
472217a5cf0SLars-Peter Clausen 		if (!mask)
473217a5cf0SLars-Peter Clausen 			goto err_invalid_mask;
474217a5cf0SLars-Peter Clausen 	}
475217a5cf0SLars-Peter Clausen 	bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength);
476217a5cf0SLars-Peter Clausen 
4773862828aSAndy Shevchenko 	bitmap_free(trialmask);
478217a5cf0SLars-Peter Clausen 
479217a5cf0SLars-Peter Clausen 	return 0;
480217a5cf0SLars-Peter Clausen 
481217a5cf0SLars-Peter Clausen err_invalid_mask:
4823862828aSAndy Shevchenko 	bitmap_free(trialmask);
483217a5cf0SLars-Peter Clausen 	return -EINVAL;
484217a5cf0SLars-Peter Clausen }
485217a5cf0SLars-Peter Clausen 
iio_scan_mask_clear(struct iio_buffer * buffer,int bit)486a980e046SJonathan Cameron static int iio_scan_mask_clear(struct iio_buffer *buffer, int bit)
487a980e046SJonathan Cameron {
488a980e046SJonathan Cameron 	clear_bit(bit, buffer->scan_mask);
489a980e046SJonathan Cameron 	return 0;
490a980e046SJonathan Cameron }
491a980e046SJonathan Cameron 
iio_scan_mask_query(struct iio_dev * indio_dev,struct iio_buffer * buffer,int bit)492c2bf8d5fSJonathan Cameron static int iio_scan_mask_query(struct iio_dev *indio_dev,
493c2bf8d5fSJonathan Cameron 			       struct iio_buffer *buffer, int bit)
494c2bf8d5fSJonathan Cameron {
495c2bf8d5fSJonathan Cameron 	if (bit > indio_dev->masklength)
496c2bf8d5fSJonathan Cameron 		return -EINVAL;
497c2bf8d5fSJonathan Cameron 
498c2bf8d5fSJonathan Cameron 	if (!buffer->scan_mask)
499c2bf8d5fSJonathan Cameron 		return 0;
500c2bf8d5fSJonathan Cameron 
501c2bf8d5fSJonathan Cameron 	/* Ensure return value is 0 or 1. */
502c2bf8d5fSJonathan Cameron 	return !!test_bit(bit, buffer->scan_mask);
503c2bf8d5fSJonathan Cameron };
504c2bf8d5fSJonathan Cameron 
iio_scan_el_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)505a980e046SJonathan Cameron static ssize_t iio_scan_el_store(struct device *dev,
506a980e046SJonathan Cameron 				 struct device_attribute *attr,
507a980e046SJonathan Cameron 				 const char *buf,
508a980e046SJonathan Cameron 				 size_t len)
509a980e046SJonathan Cameron {
510a980e046SJonathan Cameron 	int ret;
511a980e046SJonathan Cameron 	bool state;
512e53f5ac5SLars-Peter Clausen 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
51316afe125SNuno Sá 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
514a980e046SJonathan Cameron 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
51515097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = this_attr->buffer;
516a980e046SJonathan Cameron 
51774f582ecSLars-Peter Clausen 	ret = kstrtobool(buf, &state);
518a980e046SJonathan Cameron 	if (ret < 0)
519a980e046SJonathan Cameron 		return ret;
52016afe125SNuno Sá 	mutex_lock(&iio_dev_opaque->mlock);
521ff3f7e04SAlexandru Ardelean 	if (iio_buffer_is_active(buffer)) {
522a980e046SJonathan Cameron 		ret = -EBUSY;
523a980e046SJonathan Cameron 		goto error_ret;
524a980e046SJonathan Cameron 	}
525a980e046SJonathan Cameron 	ret = iio_scan_mask_query(indio_dev, buffer, this_attr->address);
526a980e046SJonathan Cameron 	if (ret < 0)
527a980e046SJonathan Cameron 		goto error_ret;
528a980e046SJonathan Cameron 	if (!state && ret) {
529a980e046SJonathan Cameron 		ret = iio_scan_mask_clear(buffer, this_attr->address);
530a980e046SJonathan Cameron 		if (ret)
531a980e046SJonathan Cameron 			goto error_ret;
532a980e046SJonathan Cameron 	} else if (state && !ret) {
533a980e046SJonathan Cameron 		ret = iio_scan_mask_set(indio_dev, buffer, this_attr->address);
534a980e046SJonathan Cameron 		if (ret)
535a980e046SJonathan Cameron 			goto error_ret;
536a980e046SJonathan Cameron 	}
537a980e046SJonathan Cameron 
538a980e046SJonathan Cameron error_ret:
53916afe125SNuno Sá 	mutex_unlock(&iio_dev_opaque->mlock);
540a980e046SJonathan Cameron 
541a980e046SJonathan Cameron 	return ret < 0 ? ret : len;
542a980e046SJonathan Cameron }
543a980e046SJonathan Cameron 
iio_scan_el_ts_show(struct device * dev,struct device_attribute * attr,char * buf)544a980e046SJonathan Cameron static ssize_t iio_scan_el_ts_show(struct device *dev,
545a980e046SJonathan Cameron 				   struct device_attribute *attr,
546a980e046SJonathan Cameron 				   char *buf)
547a980e046SJonathan Cameron {
548a980e046SJonathan Cameron 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
54915097c7aSAlexandru Ardelean 
550ff3f7e04SAlexandru Ardelean 	return sysfs_emit(buf, "%d\n", buffer->scan_timestamp);
55183ca56b6SLars-Peter Clausen }
552a980e046SJonathan Cameron 
iio_scan_el_ts_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)553a980e046SJonathan Cameron static ssize_t iio_scan_el_ts_store(struct device *dev,
554a980e046SJonathan Cameron 				    struct device_attribute *attr,
555a980e046SJonathan Cameron 				    const char *buf,
556a980e046SJonathan Cameron 				    size_t len)
557a980e046SJonathan Cameron {
558a980e046SJonathan Cameron 	int ret;
559a980e046SJonathan Cameron 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
560e53f5ac5SLars-Peter Clausen 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
56116afe125SNuno Sá 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
56215097c7aSAlexandru Ardelean 	bool state;
563a980e046SJonathan Cameron 
564a980e046SJonathan Cameron 	ret = kstrtobool(buf, &state);
56574f582ecSLars-Peter Clausen 	if (ret < 0)
566a980e046SJonathan Cameron 		return ret;
567a980e046SJonathan Cameron 
568a980e046SJonathan Cameron 	mutex_lock(&iio_dev_opaque->mlock);
56916afe125SNuno Sá 	if (iio_buffer_is_active(buffer)) {
570ff3f7e04SAlexandru Ardelean 		ret = -EBUSY;
571a980e046SJonathan Cameron 		goto error_ret;
572a980e046SJonathan Cameron 	}
573a980e046SJonathan Cameron 	buffer->scan_timestamp = state;
574ff3f7e04SAlexandru Ardelean error_ret:
575a980e046SJonathan Cameron 	mutex_unlock(&iio_dev_opaque->mlock);
57616afe125SNuno Sá 
577a980e046SJonathan Cameron 	return ret ? ret : len;
578a980e046SJonathan Cameron }
579a980e046SJonathan Cameron 
iio_buffer_add_channel_sysfs(struct iio_dev * indio_dev,struct iio_buffer * buffer,const struct iio_chan_spec * chan)580a980e046SJonathan Cameron static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
581a980e046SJonathan Cameron 					struct iio_buffer *buffer,
582ff3f7e04SAlexandru Ardelean 					const struct iio_chan_spec *chan)
583a980e046SJonathan Cameron {
584a980e046SJonathan Cameron 	int ret, attrcount = 0;
585a980e046SJonathan Cameron 
586a980e046SJonathan Cameron 	ret = __iio_add_chan_devattr("index",
587a980e046SJonathan Cameron 				     chan,
588a980e046SJonathan Cameron 				     &iio_show_scan_index,
589a980e046SJonathan Cameron 				     NULL,
590a980e046SJonathan Cameron 				     0,
591a980e046SJonathan Cameron 				     IIO_SEPARATE,
5923704432fSJonathan Cameron 				     &indio_dev->dev,
593a980e046SJonathan Cameron 				     buffer,
5943e3d11b2SAlexandru Ardelean 				     &buffer->buffer_attr_list);
59515097c7aSAlexandru Ardelean 	if (ret)
596a980e046SJonathan Cameron 		return ret;
59792825ff9SHartmut Knaack 	attrcount++;
598a980e046SJonathan Cameron 	ret = __iio_add_chan_devattr("type",
599a980e046SJonathan Cameron 				     chan,
600a980e046SJonathan Cameron 				     &iio_show_fixed_type,
601a980e046SJonathan Cameron 				     NULL,
602a980e046SJonathan Cameron 				     0,
603a980e046SJonathan Cameron 				     0,
604a980e046SJonathan Cameron 				     &indio_dev->dev,
605a980e046SJonathan Cameron 				     buffer,
6063e3d11b2SAlexandru Ardelean 				     &buffer->buffer_attr_list);
60715097c7aSAlexandru Ardelean 	if (ret)
608a980e046SJonathan Cameron 		return ret;
60992825ff9SHartmut Knaack 	attrcount++;
610a980e046SJonathan Cameron 	if (chan->type != IIO_TIMESTAMP)
611a980e046SJonathan Cameron 		ret = __iio_add_chan_devattr("en",
612a980e046SJonathan Cameron 					     chan,
613a980e046SJonathan Cameron 					     &iio_scan_el_show,
614a980e046SJonathan Cameron 					     &iio_scan_el_store,
615a980e046SJonathan Cameron 					     chan->scan_index,
616a980e046SJonathan Cameron 					     0,
617a980e046SJonathan Cameron 					     &indio_dev->dev,
618a980e046SJonathan Cameron 					     buffer,
6193e3d11b2SAlexandru Ardelean 					     &buffer->buffer_attr_list);
62015097c7aSAlexandru Ardelean 	else
621a980e046SJonathan Cameron 		ret = __iio_add_chan_devattr("en",
622a980e046SJonathan Cameron 					     chan,
623a980e046SJonathan Cameron 					     &iio_scan_el_ts_show,
624a980e046SJonathan Cameron 					     &iio_scan_el_ts_store,
625a980e046SJonathan Cameron 					     chan->scan_index,
626a980e046SJonathan Cameron 					     0,
627a980e046SJonathan Cameron 					     &indio_dev->dev,
628a980e046SJonathan Cameron 					     buffer,
6293e3d11b2SAlexandru Ardelean 					     &buffer->buffer_attr_list);
63015097c7aSAlexandru Ardelean 	if (ret)
6319572588cSPeter Meerwald 		return ret;
63292825ff9SHartmut Knaack 	attrcount++;
633a980e046SJonathan Cameron 	ret = attrcount;
634a980e046SJonathan Cameron 	return ret;
635a980e046SJonathan Cameron }
636a980e046SJonathan Cameron 
length_show(struct device * dev,struct device_attribute * attr,char * buf)637a980e046SJonathan Cameron static ssize_t length_show(struct device *dev, struct device_attribute *attr,
6389cf0b618SJoe Simmons-Talbott 			   char *buf)
639a980e046SJonathan Cameron {
640a980e046SJonathan Cameron 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
64115097c7aSAlexandru Ardelean 
642a980e046SJonathan Cameron 	return sysfs_emit(buf, "%d\n", buffer->length);
64383ca56b6SLars-Peter Clausen }
644a980e046SJonathan Cameron 
length_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)645a980e046SJonathan Cameron static ssize_t length_store(struct device *dev, struct device_attribute *attr,
6469cf0b618SJoe Simmons-Talbott 			    const char *buf, size_t len)
64708e7e0adSLars-Peter Clausen {
648a980e046SJonathan Cameron 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
649e53f5ac5SLars-Peter Clausen 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
65016afe125SNuno Sá 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
65115097c7aSAlexandru Ardelean 	unsigned int val;
652948ad205SLars-Peter Clausen 	int ret;
653948ad205SLars-Peter Clausen 
654a980e046SJonathan Cameron 	ret = kstrtouint(buf, 10, &val);
655948ad205SLars-Peter Clausen 	if (ret)
656a980e046SJonathan Cameron 		return ret;
657a980e046SJonathan Cameron 
658a980e046SJonathan Cameron 	if (val == buffer->length)
65937495660SLars-Peter Clausen 		return len;
660a980e046SJonathan Cameron 
661a980e046SJonathan Cameron 	mutex_lock(&iio_dev_opaque->mlock);
66216afe125SNuno Sá 	if (iio_buffer_is_active(buffer)) {
663ff3f7e04SAlexandru Ardelean 		ret = -EBUSY;
664a980e046SJonathan Cameron 	} else {
665a980e046SJonathan Cameron 		buffer->access->set_length(buffer, val);
666a980e046SJonathan Cameron 		ret = 0;
667a980e046SJonathan Cameron 	}
668a980e046SJonathan Cameron 	if (ret)
66937d34556SJosselin Costanzi 		goto out;
67037d34556SJosselin Costanzi 	if (buffer->length && buffer->length < buffer->watermark)
67137d34556SJosselin Costanzi 		buffer->watermark = buffer->length;
67237d34556SJosselin Costanzi out:
67337d34556SJosselin Costanzi 	mutex_unlock(&iio_dev_opaque->mlock);
67416afe125SNuno Sá 
675a980e046SJonathan Cameron 	return ret ? ret : len;
676a980e046SJonathan Cameron }
677a980e046SJonathan Cameron 
enable_show(struct device * dev,struct device_attribute * attr,char * buf)678a980e046SJonathan Cameron static ssize_t enable_show(struct device *dev, struct device_attribute *attr,
6799cf0b618SJoe Simmons-Talbott 			   char *buf)
680a980e046SJonathan Cameron {
681a980e046SJonathan Cameron 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
68215097c7aSAlexandru Ardelean 
683ff3f7e04SAlexandru Ardelean 	return sysfs_emit(buf, "%d\n", iio_buffer_is_active(buffer));
68483ca56b6SLars-Peter Clausen }
685a980e046SJonathan Cameron 
iio_storage_bytes_for_si(struct iio_dev * indio_dev,unsigned int scan_index)686a980e046SJonathan Cameron static unsigned int iio_storage_bytes_for_si(struct iio_dev *indio_dev,
687182b4905SLars-Peter Clausen 					     unsigned int scan_index)
688182b4905SLars-Peter Clausen {
689182b4905SLars-Peter Clausen 	const struct iio_chan_spec *ch;
690182b4905SLars-Peter Clausen 	unsigned int bytes;
691182b4905SLars-Peter Clausen 
692182b4905SLars-Peter Clausen 	ch = iio_find_channel_from_si(indio_dev, scan_index);
693182b4905SLars-Peter Clausen 	bytes = ch->scan_type.storagebits / 8;
694182b4905SLars-Peter Clausen 	if (ch->scan_type.repeat > 1)
695182b4905SLars-Peter Clausen 		bytes *= ch->scan_type.repeat;
696182b4905SLars-Peter Clausen 	return bytes;
697182b4905SLars-Peter Clausen }
698182b4905SLars-Peter Clausen 
iio_storage_bytes_for_timestamp(struct iio_dev * indio_dev)699182b4905SLars-Peter Clausen static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev)
700182b4905SLars-Peter Clausen {
701182b4905SLars-Peter Clausen 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
70262f4f36cSJonathan Cameron 
70362f4f36cSJonathan Cameron 	return iio_storage_bytes_for_si(indio_dev,
704182b4905SLars-Peter Clausen 					iio_dev_opaque->scan_index_timestamp);
70562f4f36cSJonathan Cameron }
706182b4905SLars-Peter Clausen 
iio_compute_scan_bytes(struct iio_dev * indio_dev,const unsigned long * mask,bool timestamp)707182b4905SLars-Peter Clausen static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
708183f4173SPeter Meerwald 				  const unsigned long *mask, bool timestamp)
709183f4173SPeter Meerwald {
710a980e046SJonathan Cameron 	unsigned int bytes = 0;
711abeba59fSJoe Simmons-Talbott 	int length, i, largest = 0;
712883f6165SLars Möllendorf 
713a980e046SJonathan Cameron 	/* How much space will the demuxed element take? */
714a980e046SJonathan Cameron 	for_each_set_bit(i, mask,
715a980e046SJonathan Cameron 			 indio_dev->masklength) {
716a980e046SJonathan Cameron 		length = iio_storage_bytes_for_si(indio_dev, i);
717182b4905SLars-Peter Clausen 		bytes = ALIGN(bytes, length);
718a980e046SJonathan Cameron 		bytes += length;
719a980e046SJonathan Cameron 		largest = max(largest, length);
720883f6165SLars Möllendorf 	}
721a980e046SJonathan Cameron 
722182b4905SLars-Peter Clausen 	if (timestamp) {
723a980e046SJonathan Cameron 		length = iio_storage_bytes_for_timestamp(indio_dev);
724182b4905SLars-Peter Clausen 		bytes = ALIGN(bytes, length);
725a980e046SJonathan Cameron 		bytes += length;
726a980e046SJonathan Cameron 		largest = max(largest, length);
727883f6165SLars Möllendorf 	}
728a980e046SJonathan Cameron 
729883f6165SLars Möllendorf 	bytes = ALIGN(bytes, largest);
730883f6165SLars Möllendorf 	return bytes;
731a980e046SJonathan Cameron }
732a980e046SJonathan Cameron 
iio_buffer_activate(struct iio_dev * indio_dev,struct iio_buffer * buffer)733a980e046SJonathan Cameron static void iio_buffer_activate(struct iio_dev *indio_dev,
7349e69c935SLars-Peter Clausen 				struct iio_buffer *buffer)
7359e69c935SLars-Peter Clausen {
7369e69c935SLars-Peter Clausen 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
7376a8c6b26SAlexandru Ardelean 
7386a8c6b26SAlexandru Ardelean 	iio_buffer_get(buffer);
7399e69c935SLars-Peter Clausen 	list_add(&buffer->buffer_list, &iio_dev_opaque->buffer_list);
7406a8c6b26SAlexandru Ardelean }
7419e69c935SLars-Peter Clausen 
iio_buffer_deactivate(struct iio_buffer * buffer)7429e69c935SLars-Peter Clausen static void iio_buffer_deactivate(struct iio_buffer *buffer)
7439e69c935SLars-Peter Clausen {
7449e69c935SLars-Peter Clausen 	list_del_init(&buffer->buffer_list);
7459e69c935SLars-Peter Clausen 	wake_up_interruptible(&buffer->pollq);
74637d34556SJosselin Costanzi 	iio_buffer_put(buffer);
7479e69c935SLars-Peter Clausen }
7489e69c935SLars-Peter Clausen 
iio_buffer_deactivate_all(struct iio_dev * indio_dev)7499e69c935SLars-Peter Clausen static void iio_buffer_deactivate_all(struct iio_dev *indio_dev)
7501250186aSLars-Peter Clausen {
7511250186aSLars-Peter Clausen 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
7526a8c6b26SAlexandru Ardelean 	struct iio_buffer *buffer, *_buffer;
7531250186aSLars-Peter Clausen 
7541250186aSLars-Peter Clausen 	list_for_each_entry_safe(buffer, _buffer,
7551250186aSLars-Peter Clausen 				 &iio_dev_opaque->buffer_list, buffer_list)
7566a8c6b26SAlexandru Ardelean 		iio_buffer_deactivate(buffer);
7571250186aSLars-Peter Clausen }
7581250186aSLars-Peter Clausen 
iio_buffer_enable(struct iio_buffer * buffer,struct iio_dev * indio_dev)7591250186aSLars-Peter Clausen static int iio_buffer_enable(struct iio_buffer *buffer,
760e18a2ad4SLars-Peter Clausen 			     struct iio_dev *indio_dev)
761e18a2ad4SLars-Peter Clausen {
762e18a2ad4SLars-Peter Clausen 	if (!buffer->access->enable)
763e18a2ad4SLars-Peter Clausen 		return 0;
764e18a2ad4SLars-Peter Clausen 	return buffer->access->enable(buffer, indio_dev);
765e18a2ad4SLars-Peter Clausen }
766e18a2ad4SLars-Peter Clausen 
iio_buffer_disable(struct iio_buffer * buffer,struct iio_dev * indio_dev)767e18a2ad4SLars-Peter Clausen static int iio_buffer_disable(struct iio_buffer *buffer,
768e18a2ad4SLars-Peter Clausen 			      struct iio_dev *indio_dev)
769e18a2ad4SLars-Peter Clausen {
770e18a2ad4SLars-Peter Clausen 	if (!buffer->access->disable)
771e18a2ad4SLars-Peter Clausen 		return 0;
772e18a2ad4SLars-Peter Clausen 	return buffer->access->disable(buffer, indio_dev);
773e18a2ad4SLars-Peter Clausen }
774e18a2ad4SLars-Peter Clausen 
iio_buffer_update_bytes_per_datum(struct iio_dev * indio_dev,struct iio_buffer * buffer)775e18a2ad4SLars-Peter Clausen static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev,
7768e050996SLars-Peter Clausen 					      struct iio_buffer *buffer)
7778e050996SLars-Peter Clausen {
7788e050996SLars-Peter Clausen 	unsigned int bytes;
7798e050996SLars-Peter Clausen 
7808e050996SLars-Peter Clausen 	if (!buffer->access->set_bytes_per_datum)
7818e050996SLars-Peter Clausen 		return;
7828e050996SLars-Peter Clausen 
7838e050996SLars-Peter Clausen 	bytes = iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
7848e050996SLars-Peter Clausen 				       buffer->scan_timestamp);
7858e050996SLars-Peter Clausen 
7868e050996SLars-Peter Clausen 	buffer->access->set_bytes_per_datum(buffer, bytes);
7878e050996SLars-Peter Clausen }
7888e050996SLars-Peter Clausen 
iio_buffer_request_update(struct iio_dev * indio_dev,struct iio_buffer * buffer)7898e050996SLars-Peter Clausen static int iio_buffer_request_update(struct iio_dev *indio_dev,
790fcc1b2f5SLars-Peter Clausen 				     struct iio_buffer *buffer)
791fcc1b2f5SLars-Peter Clausen {
792fcc1b2f5SLars-Peter Clausen 	int ret;
793fcc1b2f5SLars-Peter Clausen 
794fcc1b2f5SLars-Peter Clausen 	iio_buffer_update_bytes_per_datum(indio_dev, buffer);
795fcc1b2f5SLars-Peter Clausen 	if (buffer->access->request_update) {
796fcc1b2f5SLars-Peter Clausen 		ret = buffer->access->request_update(buffer);
797fcc1b2f5SLars-Peter Clausen 		if (ret) {
798fcc1b2f5SLars-Peter Clausen 			dev_dbg(&indio_dev->dev,
799fcc1b2f5SLars-Peter Clausen 				"Buffer not started: buffer parameter update failed (%d)\n",
800fcc1b2f5SLars-Peter Clausen 				ret);
801fcc1b2f5SLars-Peter Clausen 			return ret;
802fcc1b2f5SLars-Peter Clausen 		}
803fcc1b2f5SLars-Peter Clausen 	}
804fcc1b2f5SLars-Peter Clausen 
805fcc1b2f5SLars-Peter Clausen 	return 0;
806fcc1b2f5SLars-Peter Clausen }
807fcc1b2f5SLars-Peter Clausen 
iio_free_scan_mask(struct iio_dev * indio_dev,const unsigned long * mask)808fcc1b2f5SLars-Peter Clausen static void iio_free_scan_mask(struct iio_dev *indio_dev,
809248be5aaSLars-Peter Clausen 			       const unsigned long *mask)
810248be5aaSLars-Peter Clausen {
811248be5aaSLars-Peter Clausen 	/* If the mask is dynamically allocated free it, otherwise do nothing */
812248be5aaSLars-Peter Clausen 	if (!indio_dev->available_scan_masks)
813248be5aaSLars-Peter Clausen 		bitmap_free(mask);
8143862828aSAndy Shevchenko }
815248be5aaSLars-Peter Clausen 
816248be5aaSLars-Peter Clausen struct iio_device_config {
8176e509c4dSLars-Peter Clausen 	unsigned int mode;
8186e509c4dSLars-Peter Clausen 	unsigned int watermark;
819f0566c0cSLars-Peter Clausen 	const unsigned long *scan_mask;
8206e509c4dSLars-Peter Clausen 	unsigned int scan_bytes;
8216e509c4dSLars-Peter Clausen 	bool scan_timestamp;
8226e509c4dSLars-Peter Clausen };
8236e509c4dSLars-Peter Clausen 
iio_verify_update(struct iio_dev * indio_dev,struct iio_buffer * insert_buffer,struct iio_buffer * remove_buffer,struct iio_device_config * config)8246e509c4dSLars-Peter Clausen static int iio_verify_update(struct iio_dev *indio_dev,
8256e509c4dSLars-Peter Clausen 			     struct iio_buffer *insert_buffer,
8266e509c4dSLars-Peter Clausen 			     struct iio_buffer *remove_buffer,
8276e509c4dSLars-Peter Clausen 			     struct iio_device_config *config)
8286e509c4dSLars-Peter Clausen {
8296a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
8306e509c4dSLars-Peter Clausen 	unsigned long *compound_mask;
8316e509c4dSLars-Peter Clausen 	const unsigned long *scan_mask;
8321e1ec286SLars-Peter Clausen 	bool strict_scanmask = false;
8336e509c4dSLars-Peter Clausen 	struct iio_buffer *buffer;
8346e509c4dSLars-Peter Clausen 	bool scan_timestamp;
835225d59adSLars-Peter Clausen 	unsigned int modes;
8366e509c4dSLars-Peter Clausen 
837b7329249SLars-Peter Clausen 	if (insert_buffer &&
838b7329249SLars-Peter Clausen 	    bitmap_empty(insert_buffer->scan_mask, indio_dev->masklength)) {
839b7329249SLars-Peter Clausen 		dev_dbg(&indio_dev->dev,
840b7329249SLars-Peter Clausen 			"At least one scan element must be enabled first\n");
841b7329249SLars-Peter Clausen 		return -EINVAL;
842b7329249SLars-Peter Clausen 	}
843b7329249SLars-Peter Clausen 
8446e509c4dSLars-Peter Clausen 	memset(config, 0, sizeof(*config));
8451bef2c1dSIrina Tirdea 	config->watermark = ~0;
8466e509c4dSLars-Peter Clausen 
8476e509c4dSLars-Peter Clausen 	/*
8486e509c4dSLars-Peter Clausen 	 * If there is just one buffer and we are removing it there is nothing
8496e509c4dSLars-Peter Clausen 	 * to verify.
8506e509c4dSLars-Peter Clausen 	 */
8516e509c4dSLars-Peter Clausen 	if (remove_buffer && !insert_buffer &&
8526a8c6b26SAlexandru Ardelean 	    list_is_singular(&iio_dev_opaque->buffer_list))
8536e509c4dSLars-Peter Clausen 		return 0;
8546e509c4dSLars-Peter Clausen 
855225d59adSLars-Peter Clausen 	modes = indio_dev->modes;
856225d59adSLars-Peter Clausen 
8576a8c6b26SAlexandru Ardelean 	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
858225d59adSLars-Peter Clausen 		if (buffer == remove_buffer)
859225d59adSLars-Peter Clausen 			continue;
860225d59adSLars-Peter Clausen 		modes &= buffer->access->modes;
861f0566c0cSLars-Peter Clausen 		config->watermark = min(config->watermark, buffer->watermark);
862225d59adSLars-Peter Clausen 	}
863225d59adSLars-Peter Clausen 
864f0566c0cSLars-Peter Clausen 	if (insert_buffer) {
865225d59adSLars-Peter Clausen 		modes &= insert_buffer->access->modes;
866f0566c0cSLars-Peter Clausen 		config->watermark = min(config->watermark,
867f0566c0cSLars-Peter Clausen 					insert_buffer->watermark);
868f0566c0cSLars-Peter Clausen 	}
869225d59adSLars-Peter Clausen 
8706e509c4dSLars-Peter Clausen 	/* Definitely possible for devices to support both of these. */
871225d59adSLars-Peter Clausen 	if ((modes & INDIO_BUFFER_TRIGGERED) && indio_dev->trig) {
8726e509c4dSLars-Peter Clausen 		config->mode = INDIO_BUFFER_TRIGGERED;
873225d59adSLars-Peter Clausen 	} else if (modes & INDIO_BUFFER_HARDWARE) {
8741e1ec286SLars-Peter Clausen 		/*
8751e1ec286SLars-Peter Clausen 		 * Keep things simple for now and only allow a single buffer to
8761e1ec286SLars-Peter Clausen 		 * be connected in hardware mode.
8771e1ec286SLars-Peter Clausen 		 */
8786a8c6b26SAlexandru Ardelean 		if (insert_buffer && !list_empty(&iio_dev_opaque->buffer_list))
8791e1ec286SLars-Peter Clausen 			return -EINVAL;
8806e509c4dSLars-Peter Clausen 		config->mode = INDIO_BUFFER_HARDWARE;
8811e1ec286SLars-Peter Clausen 		strict_scanmask = true;
882225d59adSLars-Peter Clausen 	} else if (modes & INDIO_BUFFER_SOFTWARE) {
8836e509c4dSLars-Peter Clausen 		config->mode = INDIO_BUFFER_SOFTWARE;
8846e509c4dSLars-Peter Clausen 	} else {
8856e509c4dSLars-Peter Clausen 		/* Can only occur on first buffer */
8866e509c4dSLars-Peter Clausen 		if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
8876e509c4dSLars-Peter Clausen 			dev_dbg(&indio_dev->dev, "Buffer not started: no trigger\n");
8886e509c4dSLars-Peter Clausen 		return -EINVAL;
8896e509c4dSLars-Peter Clausen 	}
8906e509c4dSLars-Peter Clausen 
8916e509c4dSLars-Peter Clausen 	/* What scan mask do we actually have? */
8923862828aSAndy Shevchenko 	compound_mask = bitmap_zalloc(indio_dev->masklength, GFP_KERNEL);
8936e509c4dSLars-Peter Clausen 	if (!compound_mask)
8946e509c4dSLars-Peter Clausen 		return -ENOMEM;
8956e509c4dSLars-Peter Clausen 
8966e509c4dSLars-Peter Clausen 	scan_timestamp = false;
8976e509c4dSLars-Peter Clausen 
8986a8c6b26SAlexandru Ardelean 	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
8996e509c4dSLars-Peter Clausen 		if (buffer == remove_buffer)
9006e509c4dSLars-Peter Clausen 			continue;
9016e509c4dSLars-Peter Clausen 		bitmap_or(compound_mask, compound_mask, buffer->scan_mask,
9026e509c4dSLars-Peter Clausen 			  indio_dev->masklength);
9036e509c4dSLars-Peter Clausen 		scan_timestamp |= buffer->scan_timestamp;
9046e509c4dSLars-Peter Clausen 	}
9056e509c4dSLars-Peter Clausen 
9066e509c4dSLars-Peter Clausen 	if (insert_buffer) {
9076e509c4dSLars-Peter Clausen 		bitmap_or(compound_mask, compound_mask,
9086e509c4dSLars-Peter Clausen 			  insert_buffer->scan_mask, indio_dev->masklength);
9096e509c4dSLars-Peter Clausen 		scan_timestamp |= insert_buffer->scan_timestamp;
9106e509c4dSLars-Peter Clausen 	}
9116e509c4dSLars-Peter Clausen 
9126e509c4dSLars-Peter Clausen 	if (indio_dev->available_scan_masks) {
9136e509c4dSLars-Peter Clausen 		scan_mask = iio_scan_mask_match(indio_dev->available_scan_masks,
9146e509c4dSLars-Peter Clausen 						indio_dev->masklength,
9151e1ec286SLars-Peter Clausen 						compound_mask,
9161e1ec286SLars-Peter Clausen 						strict_scanmask);
9173862828aSAndy Shevchenko 		bitmap_free(compound_mask);
9186e509c4dSLars-Peter Clausen 		if (!scan_mask)
9196e509c4dSLars-Peter Clausen 			return -EINVAL;
9206e509c4dSLars-Peter Clausen 	} else {
9216e509c4dSLars-Peter Clausen 		scan_mask = compound_mask;
9226e509c4dSLars-Peter Clausen 	}
9236e509c4dSLars-Peter Clausen 
9246e509c4dSLars-Peter Clausen 	config->scan_bytes = iio_compute_scan_bytes(indio_dev,
9256e509c4dSLars-Peter Clausen 						    scan_mask, scan_timestamp);
9266e509c4dSLars-Peter Clausen 	config->scan_mask = scan_mask;
9276e509c4dSLars-Peter Clausen 	config->scan_timestamp = scan_timestamp;
9286e509c4dSLars-Peter Clausen 
9296e509c4dSLars-Peter Clausen 	return 0;
9306e509c4dSLars-Peter Clausen }
9316e509c4dSLars-Peter Clausen 
93278c9981fSJonathan Cameron /**
93378c9981fSJonathan Cameron  * struct iio_demux_table - table describing demux memcpy ops
93478c9981fSJonathan Cameron  * @from:	index to copy from
93578c9981fSJonathan Cameron  * @to:		index to copy to
93678c9981fSJonathan Cameron  * @length:	how many bytes to copy
93778c9981fSJonathan Cameron  * @l:		list head used for management
93878c9981fSJonathan Cameron  */
93978c9981fSJonathan Cameron struct iio_demux_table {
940abeba59fSJoe Simmons-Talbott 	unsigned int from;
941abeba59fSJoe Simmons-Talbott 	unsigned int to;
942abeba59fSJoe Simmons-Talbott 	unsigned int length;
94378c9981fSJonathan Cameron 	struct list_head l;
94478c9981fSJonathan Cameron };
94578c9981fSJonathan Cameron 
iio_buffer_demux_free(struct iio_buffer * buffer)94678c9981fSJonathan Cameron static void iio_buffer_demux_free(struct iio_buffer *buffer)
94778c9981fSJonathan Cameron {
94878c9981fSJonathan Cameron 	struct iio_demux_table *p, *q;
9499d9ec8d0SJoe Simmons-Talbott 
95078c9981fSJonathan Cameron 	list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
95178c9981fSJonathan Cameron 		list_del(&p->l);
95278c9981fSJonathan Cameron 		kfree(p);
95378c9981fSJonathan Cameron 	}
95478c9981fSJonathan Cameron }
95578c9981fSJonathan Cameron 
iio_buffer_add_demux(struct iio_buffer * buffer,struct iio_demux_table ** p,unsigned int in_loc,unsigned int out_loc,unsigned int length)95678c9981fSJonathan Cameron static int iio_buffer_add_demux(struct iio_buffer *buffer,
95778c9981fSJonathan Cameron 				struct iio_demux_table **p, unsigned int in_loc,
95878c9981fSJonathan Cameron 				unsigned int out_loc,
95978c9981fSJonathan Cameron 				unsigned int length)
96078c9981fSJonathan Cameron {
96178c9981fSJonathan Cameron 	if (*p && (*p)->from + (*p)->length == in_loc &&
96278c9981fSJonathan Cameron 	    (*p)->to + (*p)->length == out_loc) {
96378c9981fSJonathan Cameron 		(*p)->length += length;
96478c9981fSJonathan Cameron 	} else {
96578c9981fSJonathan Cameron 		*p = kmalloc(sizeof(**p), GFP_KERNEL);
96678c9981fSJonathan Cameron 		if (!(*p))
96778c9981fSJonathan Cameron 			return -ENOMEM;
96878c9981fSJonathan Cameron 		(*p)->from = in_loc;
96978c9981fSJonathan Cameron 		(*p)->to = out_loc;
97078c9981fSJonathan Cameron 		(*p)->length = length;
97178c9981fSJonathan Cameron 		list_add_tail(&(*p)->l, &buffer->demux_list);
97278c9981fSJonathan Cameron 	}
97378c9981fSJonathan Cameron 
97478c9981fSJonathan Cameron 	return 0;
97578c9981fSJonathan Cameron }
97678c9981fSJonathan Cameron 
iio_buffer_update_demux(struct iio_dev * indio_dev,struct iio_buffer * buffer)97778c9981fSJonathan Cameron static int iio_buffer_update_demux(struct iio_dev *indio_dev,
97878c9981fSJonathan Cameron 				   struct iio_buffer *buffer)
97978c9981fSJonathan Cameron {
98078c9981fSJonathan Cameron 	int ret, in_ind = -1, out_ind, length;
981abeba59fSJoe Simmons-Talbott 	unsigned int in_loc = 0, out_loc = 0;
98278c9981fSJonathan Cameron 	struct iio_demux_table *p = NULL;
98378c9981fSJonathan Cameron 
98478c9981fSJonathan Cameron 	/* Clear out any old demux */
98578c9981fSJonathan Cameron 	iio_buffer_demux_free(buffer);
98678c9981fSJonathan Cameron 	kfree(buffer->demux_bounce);
98778c9981fSJonathan Cameron 	buffer->demux_bounce = NULL;
98878c9981fSJonathan Cameron 
98978c9981fSJonathan Cameron 	/* First work out which scan mode we will actually have */
99078c9981fSJonathan Cameron 	if (bitmap_equal(indio_dev->active_scan_mask,
99178c9981fSJonathan Cameron 			 buffer->scan_mask,
99278c9981fSJonathan Cameron 			 indio_dev->masklength))
99378c9981fSJonathan Cameron 		return 0;
99478c9981fSJonathan Cameron 
99578c9981fSJonathan Cameron 	/* Now we have the two masks, work from least sig and build up sizes */
99678c9981fSJonathan Cameron 	for_each_set_bit(out_ind,
99778c9981fSJonathan Cameron 			 buffer->scan_mask,
99878c9981fSJonathan Cameron 			 indio_dev->masklength) {
99978c9981fSJonathan Cameron 		in_ind = find_next_bit(indio_dev->active_scan_mask,
100078c9981fSJonathan Cameron 				       indio_dev->masklength,
100178c9981fSJonathan Cameron 				       in_ind + 1);
100278c9981fSJonathan Cameron 		while (in_ind != out_ind) {
100378c9981fSJonathan Cameron 			length = iio_storage_bytes_for_si(indio_dev, in_ind);
100478c9981fSJonathan Cameron 			/* Make sure we are aligned */
100578c9981fSJonathan Cameron 			in_loc = roundup(in_loc, length) + length;
100619ef7b70SNuno Sá 			in_ind = find_next_bit(indio_dev->active_scan_mask,
100719ef7b70SNuno Sá 					       indio_dev->masklength,
100819ef7b70SNuno Sá 					       in_ind + 1);
100978c9981fSJonathan Cameron 		}
101078c9981fSJonathan Cameron 		length = iio_storage_bytes_for_si(indio_dev, in_ind);
101178c9981fSJonathan Cameron 		out_loc = roundup(out_loc, length);
101278c9981fSJonathan Cameron 		in_loc = roundup(in_loc, length);
101378c9981fSJonathan Cameron 		ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length);
101478c9981fSJonathan Cameron 		if (ret)
101578c9981fSJonathan Cameron 			goto error_clear_mux_table;
101678c9981fSJonathan Cameron 		out_loc += length;
101778c9981fSJonathan Cameron 		in_loc += length;
101878c9981fSJonathan Cameron 	}
101978c9981fSJonathan Cameron 	/* Relies on scan_timestamp being last */
102078c9981fSJonathan Cameron 	if (buffer->scan_timestamp) {
102178c9981fSJonathan Cameron 		length = iio_storage_bytes_for_timestamp(indio_dev);
102278c9981fSJonathan Cameron 		out_loc = roundup(out_loc, length);
102378c9981fSJonathan Cameron 		in_loc = roundup(in_loc, length);
102478c9981fSJonathan Cameron 		ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length);
102578c9981fSJonathan Cameron 		if (ret)
102678c9981fSJonathan Cameron 			goto error_clear_mux_table;
102778c9981fSJonathan Cameron 		out_loc += length;
102878c9981fSJonathan Cameron 	}
102978c9981fSJonathan Cameron 	buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL);
103078c9981fSJonathan Cameron 	if (!buffer->demux_bounce) {
103178c9981fSJonathan Cameron 		ret = -ENOMEM;
103278c9981fSJonathan Cameron 		goto error_clear_mux_table;
103378c9981fSJonathan Cameron 	}
103478c9981fSJonathan Cameron 	return 0;
103578c9981fSJonathan Cameron 
103678c9981fSJonathan Cameron error_clear_mux_table:
103778c9981fSJonathan Cameron 	iio_buffer_demux_free(buffer);
103878c9981fSJonathan Cameron 
103978c9981fSJonathan Cameron 	return ret;
104078c9981fSJonathan Cameron }
104178c9981fSJonathan Cameron 
iio_update_demux(struct iio_dev * indio_dev)104278c9981fSJonathan Cameron static int iio_update_demux(struct iio_dev *indio_dev)
104378c9981fSJonathan Cameron {
10446a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
104578c9981fSJonathan Cameron 	struct iio_buffer *buffer;
104678c9981fSJonathan Cameron 	int ret;
104778c9981fSJonathan Cameron 
10486a8c6b26SAlexandru Ardelean 	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
104978c9981fSJonathan Cameron 		ret = iio_buffer_update_demux(indio_dev, buffer);
105078c9981fSJonathan Cameron 		if (ret < 0)
105178c9981fSJonathan Cameron 			goto error_clear_mux_table;
105278c9981fSJonathan Cameron 	}
105378c9981fSJonathan Cameron 	return 0;
105478c9981fSJonathan Cameron 
105578c9981fSJonathan Cameron error_clear_mux_table:
10566a8c6b26SAlexandru Ardelean 	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list)
105778c9981fSJonathan Cameron 		iio_buffer_demux_free(buffer);
105878c9981fSJonathan Cameron 
105978c9981fSJonathan Cameron 	return ret;
106078c9981fSJonathan Cameron }
106178c9981fSJonathan Cameron 
iio_enable_buffers(struct iio_dev * indio_dev,struct iio_device_config * config)1062623d74e3SLars-Peter Clausen static int iio_enable_buffers(struct iio_dev *indio_dev,
1063623d74e3SLars-Peter Clausen 			      struct iio_device_config *config)
1064623d74e3SLars-Peter Clausen {
10656a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1066c22e60c3SJakob Koschel 	struct iio_buffer *buffer, *tmp = NULL;
1067623d74e3SLars-Peter Clausen 	int ret;
1068623d74e3SLars-Peter Clausen 
1069623d74e3SLars-Peter Clausen 	indio_dev->active_scan_mask = config->scan_mask;
1070623d74e3SLars-Peter Clausen 	indio_dev->scan_timestamp = config->scan_timestamp;
1071623d74e3SLars-Peter Clausen 	indio_dev->scan_bytes = config->scan_bytes;
107251570c9dSMiquel Raynal 	iio_dev_opaque->currentmode = config->mode;
1073623d74e3SLars-Peter Clausen 
1074623d74e3SLars-Peter Clausen 	iio_update_demux(indio_dev);
1075623d74e3SLars-Peter Clausen 
1076623d74e3SLars-Peter Clausen 	/* Wind up again */
1077623d74e3SLars-Peter Clausen 	if (indio_dev->setup_ops->preenable) {
1078623d74e3SLars-Peter Clausen 		ret = indio_dev->setup_ops->preenable(indio_dev);
1079623d74e3SLars-Peter Clausen 		if (ret) {
1080623d74e3SLars-Peter Clausen 			dev_dbg(&indio_dev->dev,
1081623d74e3SLars-Peter Clausen 				"Buffer not started: buffer preenable failed (%d)\n", ret);
1082623d74e3SLars-Peter Clausen 			goto err_undo_config;
1083623d74e3SLars-Peter Clausen 		}
1084623d74e3SLars-Peter Clausen 	}
1085623d74e3SLars-Peter Clausen 
1086623d74e3SLars-Peter Clausen 	if (indio_dev->info->update_scan_mode) {
1087623d74e3SLars-Peter Clausen 		ret = indio_dev->info
1088623d74e3SLars-Peter Clausen 			->update_scan_mode(indio_dev,
1089623d74e3SLars-Peter Clausen 					   indio_dev->active_scan_mask);
1090623d74e3SLars-Peter Clausen 		if (ret < 0) {
1091623d74e3SLars-Peter Clausen 			dev_dbg(&indio_dev->dev,
1092623d74e3SLars-Peter Clausen 				"Buffer not started: update scan mode failed (%d)\n",
1093623d74e3SLars-Peter Clausen 				ret);
1094623d74e3SLars-Peter Clausen 			goto err_run_postdisable;
1095623d74e3SLars-Peter Clausen 		}
1096623d74e3SLars-Peter Clausen 	}
1097623d74e3SLars-Peter Clausen 
1098f0566c0cSLars-Peter Clausen 	if (indio_dev->info->hwfifo_set_watermark)
1099f0566c0cSLars-Peter Clausen 		indio_dev->info->hwfifo_set_watermark(indio_dev,
1100f0566c0cSLars-Peter Clausen 			config->watermark);
1101f0566c0cSLars-Peter Clausen 
11026a8c6b26SAlexandru Ardelean 	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
1103e18a2ad4SLars-Peter Clausen 		ret = iio_buffer_enable(buffer, indio_dev);
1104c22e60c3SJakob Koschel 		if (ret) {
1105c22e60c3SJakob Koschel 			tmp = buffer;
1106e18a2ad4SLars-Peter Clausen 			goto err_disable_buffers;
1107e18a2ad4SLars-Peter Clausen 		}
1108c22e60c3SJakob Koschel 	}
1109e18a2ad4SLars-Peter Clausen 
111051570c9dSMiquel Raynal 	if (iio_dev_opaque->currentmode == INDIO_BUFFER_TRIGGERED) {
1111f11d59d8SLars-Peter Clausen 		ret = iio_trigger_attach_poll_func(indio_dev->trig,
1112f11d59d8SLars-Peter Clausen 						   indio_dev->pollfunc);
1113f11d59d8SLars-Peter Clausen 		if (ret)
1114f11d59d8SLars-Peter Clausen 			goto err_disable_buffers;
1115f11d59d8SLars-Peter Clausen 	}
1116f11d59d8SLars-Peter Clausen 
111762a30a29SAlexandru Ardelean 	if (indio_dev->setup_ops->postenable) {
111862a30a29SAlexandru Ardelean 		ret = indio_dev->setup_ops->postenable(indio_dev);
111962a30a29SAlexandru Ardelean 		if (ret) {
112062a30a29SAlexandru Ardelean 			dev_dbg(&indio_dev->dev,
112162a30a29SAlexandru Ardelean 				"Buffer not started: postenable failed (%d)\n", ret);
112262a30a29SAlexandru Ardelean 			goto err_detach_pollfunc;
112362a30a29SAlexandru Ardelean 		}
112462a30a29SAlexandru Ardelean 	}
112562a30a29SAlexandru Ardelean 
1126623d74e3SLars-Peter Clausen 	return 0;
1127623d74e3SLars-Peter Clausen 
112862a30a29SAlexandru Ardelean err_detach_pollfunc:
112951570c9dSMiquel Raynal 	if (iio_dev_opaque->currentmode == INDIO_BUFFER_TRIGGERED) {
113062a30a29SAlexandru Ardelean 		iio_trigger_detach_poll_func(indio_dev->trig,
113162a30a29SAlexandru Ardelean 					     indio_dev->pollfunc);
113262a30a29SAlexandru Ardelean 	}
1133e18a2ad4SLars-Peter Clausen err_disable_buffers:
1134c22e60c3SJakob Koschel 	buffer = list_prepare_entry(tmp, &iio_dev_opaque->buffer_list, buffer_list);
11356a8c6b26SAlexandru Ardelean 	list_for_each_entry_continue_reverse(buffer, &iio_dev_opaque->buffer_list,
1136e18a2ad4SLars-Peter Clausen 					     buffer_list)
1137e18a2ad4SLars-Peter Clausen 		iio_buffer_disable(buffer, indio_dev);
1138623d74e3SLars-Peter Clausen err_run_postdisable:
1139623d74e3SLars-Peter Clausen 	if (indio_dev->setup_ops->postdisable)
1140623d74e3SLars-Peter Clausen 		indio_dev->setup_ops->postdisable(indio_dev);
1141623d74e3SLars-Peter Clausen err_undo_config:
114251570c9dSMiquel Raynal 	iio_dev_opaque->currentmode = INDIO_DIRECT_MODE;
1143623d74e3SLars-Peter Clausen 	indio_dev->active_scan_mask = NULL;
1144623d74e3SLars-Peter Clausen 
1145623d74e3SLars-Peter Clausen 	return ret;
1146623d74e3SLars-Peter Clausen }
1147623d74e3SLars-Peter Clausen 
iio_disable_buffers(struct iio_dev * indio_dev)1148623d74e3SLars-Peter Clausen static int iio_disable_buffers(struct iio_dev *indio_dev)
1149623d74e3SLars-Peter Clausen {
11506a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1151e18a2ad4SLars-Peter Clausen 	struct iio_buffer *buffer;
11521250186aSLars-Peter Clausen 	int ret = 0;
11531250186aSLars-Peter Clausen 	int ret2;
1154623d74e3SLars-Peter Clausen 
1155623d74e3SLars-Peter Clausen 	/* Wind down existing buffers - iff there are any */
11566a8c6b26SAlexandru Ardelean 	if (list_empty(&iio_dev_opaque->buffer_list))
1157623d74e3SLars-Peter Clausen 		return 0;
1158623d74e3SLars-Peter Clausen 
11591250186aSLars-Peter Clausen 	/*
11601250186aSLars-Peter Clausen 	 * If things go wrong at some step in disable we still need to continue
11611250186aSLars-Peter Clausen 	 * to perform the other steps, otherwise we leave the device in a
11621250186aSLars-Peter Clausen 	 * inconsistent state. We return the error code for the first error we
11631250186aSLars-Peter Clausen 	 * encountered.
11641250186aSLars-Peter Clausen 	 */
11651250186aSLars-Peter Clausen 
1166623d74e3SLars-Peter Clausen 	if (indio_dev->setup_ops->predisable) {
11671250186aSLars-Peter Clausen 		ret2 = indio_dev->setup_ops->predisable(indio_dev);
11681250186aSLars-Peter Clausen 		if (ret2 && !ret)
11691250186aSLars-Peter Clausen 			ret = ret2;
1170623d74e3SLars-Peter Clausen 	}
1171623d74e3SLars-Peter Clausen 
117251570c9dSMiquel Raynal 	if (iio_dev_opaque->currentmode == INDIO_BUFFER_TRIGGERED) {
117362a30a29SAlexandru Ardelean 		iio_trigger_detach_poll_func(indio_dev->trig,
117462a30a29SAlexandru Ardelean 					     indio_dev->pollfunc);
117562a30a29SAlexandru Ardelean 	}
117662a30a29SAlexandru Ardelean 
11776a8c6b26SAlexandru Ardelean 	list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
1178e18a2ad4SLars-Peter Clausen 		ret2 = iio_buffer_disable(buffer, indio_dev);
1179e18a2ad4SLars-Peter Clausen 		if (ret2 && !ret)
1180e18a2ad4SLars-Peter Clausen 			ret = ret2;
1181e18a2ad4SLars-Peter Clausen 	}
1182e18a2ad4SLars-Peter Clausen 
1183623d74e3SLars-Peter Clausen 	if (indio_dev->setup_ops->postdisable) {
11841250186aSLars-Peter Clausen 		ret2 = indio_dev->setup_ops->postdisable(indio_dev);
11851250186aSLars-Peter Clausen 		if (ret2 && !ret)
11861250186aSLars-Peter Clausen 			ret = ret2;
1187623d74e3SLars-Peter Clausen 	}
1188623d74e3SLars-Peter Clausen 
11891250186aSLars-Peter Clausen 	iio_free_scan_mask(indio_dev, indio_dev->active_scan_mask);
11901250186aSLars-Peter Clausen 	indio_dev->active_scan_mask = NULL;
119151570c9dSMiquel Raynal 	iio_dev_opaque->currentmode = INDIO_DIRECT_MODE;
11921250186aSLars-Peter Clausen 
11931250186aSLars-Peter Clausen 	return ret;
1194623d74e3SLars-Peter Clausen }
1195623d74e3SLars-Peter Clausen 
__iio_update_buffers(struct iio_dev * indio_dev,struct iio_buffer * insert_buffer,struct iio_buffer * remove_buffer)1196a9519456SLars-Peter Clausen static int __iio_update_buffers(struct iio_dev *indio_dev,
119784b36ce5SJonathan Cameron 				struct iio_buffer *insert_buffer,
119884b36ce5SJonathan Cameron 				struct iio_buffer *remove_buffer)
1199a980e046SJonathan Cameron {
12006a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
12016e509c4dSLars-Peter Clausen 	struct iio_device_config new_config;
12021250186aSLars-Peter Clausen 	int ret;
12036e509c4dSLars-Peter Clausen 
12046e509c4dSLars-Peter Clausen 	ret = iio_verify_update(indio_dev, insert_buffer, remove_buffer,
12056e509c4dSLars-Peter Clausen 				&new_config);
12066e509c4dSLars-Peter Clausen 	if (ret)
12076e509c4dSLars-Peter Clausen 		return ret;
1208a980e046SJonathan Cameron 
1209fcc1b2f5SLars-Peter Clausen 	if (insert_buffer) {
1210fcc1b2f5SLars-Peter Clausen 		ret = iio_buffer_request_update(indio_dev, insert_buffer);
1211fcc1b2f5SLars-Peter Clausen 		if (ret)
12126e509c4dSLars-Peter Clausen 			goto err_free_config;
1213fcc1b2f5SLars-Peter Clausen 	}
1214fcc1b2f5SLars-Peter Clausen 
1215623d74e3SLars-Peter Clausen 	ret = iio_disable_buffers(indio_dev);
12161250186aSLars-Peter Clausen 	if (ret)
12171250186aSLars-Peter Clausen 		goto err_deactivate_all;
1218623d74e3SLars-Peter Clausen 
121984b36ce5SJonathan Cameron 	if (remove_buffer)
12209e69c935SLars-Peter Clausen 		iio_buffer_deactivate(remove_buffer);
122184b36ce5SJonathan Cameron 	if (insert_buffer)
12229e69c935SLars-Peter Clausen 		iio_buffer_activate(indio_dev, insert_buffer);
122384b36ce5SJonathan Cameron 
122484b36ce5SJonathan Cameron 	/* If no buffers in list, we are done */
12256a8c6b26SAlexandru Ardelean 	if (list_empty(&iio_dev_opaque->buffer_list))
122684b36ce5SJonathan Cameron 		return 0;
1227a980e046SJonathan Cameron 
1228623d74e3SLars-Peter Clausen 	ret = iio_enable_buffers(indio_dev, &new_config);
12291250186aSLars-Peter Clausen 	if (ret)
12301250186aSLars-Peter Clausen 		goto err_deactivate_all;
1231623d74e3SLars-Peter Clausen 
1232623d74e3SLars-Peter Clausen 	return 0;
12336e509c4dSLars-Peter Clausen 
12341250186aSLars-Peter Clausen err_deactivate_all:
12351250186aSLars-Peter Clausen 	/*
12361250186aSLars-Peter Clausen 	 * We've already verified that the config is valid earlier. If things go
12371250186aSLars-Peter Clausen 	 * wrong in either enable or disable the most likely reason is an IO
12381250186aSLars-Peter Clausen 	 * error from the device. In this case there is no good recovery
12391250186aSLars-Peter Clausen 	 * strategy. Just make sure to disable everything and leave the device
12401250186aSLars-Peter Clausen 	 * in a sane state.  With a bit of luck the device might come back to
12411250186aSLars-Peter Clausen 	 * life again later and userspace can try again.
12421250186aSLars-Peter Clausen 	 */
12431250186aSLars-Peter Clausen 	iio_buffer_deactivate_all(indio_dev);
12441250186aSLars-Peter Clausen 
12456e509c4dSLars-Peter Clausen err_free_config:
12466e509c4dSLars-Peter Clausen 	iio_free_scan_mask(indio_dev, new_config.scan_mask);
12476e509c4dSLars-Peter Clausen 	return ret;
124884b36ce5SJonathan Cameron }
1249a9519456SLars-Peter Clausen 
iio_update_buffers(struct iio_dev * indio_dev,struct iio_buffer * insert_buffer,struct iio_buffer * remove_buffer)1250a9519456SLars-Peter Clausen int iio_update_buffers(struct iio_dev *indio_dev,
1251a9519456SLars-Peter Clausen 		       struct iio_buffer *insert_buffer,
1252a9519456SLars-Peter Clausen 		       struct iio_buffer *remove_buffer)
1253a9519456SLars-Peter Clausen {
1254b804e2b7SJonathan Cameron 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1255a9519456SLars-Peter Clausen 	int ret;
1256a9519456SLars-Peter Clausen 
12573909fab5SLars-Peter Clausen 	if (insert_buffer == remove_buffer)
12583909fab5SLars-Peter Clausen 		return 0;
12593909fab5SLars-Peter Clausen 
12609eeee3b0SMihail Chindris 	if (insert_buffer &&
12619eeee3b0SMihail Chindris 	    insert_buffer->direction == IIO_BUFFER_DIRECTION_OUT)
12629eeee3b0SMihail Chindris 		return -EINVAL;
12639eeee3b0SMihail Chindris 
1264b804e2b7SJonathan Cameron 	mutex_lock(&iio_dev_opaque->info_exist_lock);
126516afe125SNuno Sá 	mutex_lock(&iio_dev_opaque->mlock);
1266a9519456SLars-Peter Clausen 
12673909fab5SLars-Peter Clausen 	if (insert_buffer && iio_buffer_is_active(insert_buffer))
12683909fab5SLars-Peter Clausen 		insert_buffer = NULL;
12693909fab5SLars-Peter Clausen 
12703909fab5SLars-Peter Clausen 	if (remove_buffer && !iio_buffer_is_active(remove_buffer))
12713909fab5SLars-Peter Clausen 		remove_buffer = NULL;
12723909fab5SLars-Peter Clausen 
12733909fab5SLars-Peter Clausen 	if (!insert_buffer && !remove_buffer) {
12743909fab5SLars-Peter Clausen 		ret = 0;
12753909fab5SLars-Peter Clausen 		goto out_unlock;
12763909fab5SLars-Peter Clausen 	}
12773909fab5SLars-Peter Clausen 
1278a9519456SLars-Peter Clausen 	if (!indio_dev->info) {
1279a9519456SLars-Peter Clausen 		ret = -ENODEV;
1280a9519456SLars-Peter Clausen 		goto out_unlock;
1281a9519456SLars-Peter Clausen 	}
1282a9519456SLars-Peter Clausen 
1283a9519456SLars-Peter Clausen 	ret = __iio_update_buffers(indio_dev, insert_buffer, remove_buffer);
1284a9519456SLars-Peter Clausen 
1285a9519456SLars-Peter Clausen out_unlock:
128616afe125SNuno Sá 	mutex_unlock(&iio_dev_opaque->mlock);
1287b804e2b7SJonathan Cameron 	mutex_unlock(&iio_dev_opaque->info_exist_lock);
1288a9519456SLars-Peter Clausen 
1289a9519456SLars-Peter Clausen 	return ret;
1290a9519456SLars-Peter Clausen }
129184b36ce5SJonathan Cameron EXPORT_SYMBOL_GPL(iio_update_buffers);
129284b36ce5SJonathan Cameron 
iio_disable_all_buffers(struct iio_dev * indio_dev)1293623d74e3SLars-Peter Clausen void iio_disable_all_buffers(struct iio_dev *indio_dev)
1294623d74e3SLars-Peter Clausen {
1295623d74e3SLars-Peter Clausen 	iio_disable_buffers(indio_dev);
12961250186aSLars-Peter Clausen 	iio_buffer_deactivate_all(indio_dev);
1297623d74e3SLars-Peter Clausen }
1298623d74e3SLars-Peter Clausen 
enable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)12999cf0b618SJoe Simmons-Talbott static ssize_t enable_store(struct device *dev, struct device_attribute *attr,
13009cf0b618SJoe Simmons-Talbott 			    const char *buf, size_t len)
130184b36ce5SJonathan Cameron {
130284b36ce5SJonathan Cameron 	int ret;
130384b36ce5SJonathan Cameron 	bool requested_state;
130484b36ce5SJonathan Cameron 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
130516afe125SNuno Sá 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
130615097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
130784b36ce5SJonathan Cameron 	bool inlist;
130884b36ce5SJonathan Cameron 
130974f582ecSLars-Peter Clausen 	ret = kstrtobool(buf, &requested_state);
131084b36ce5SJonathan Cameron 	if (ret < 0)
131184b36ce5SJonathan Cameron 		return ret;
131284b36ce5SJonathan Cameron 
131316afe125SNuno Sá 	mutex_lock(&iio_dev_opaque->mlock);
131484b36ce5SJonathan Cameron 
131584b36ce5SJonathan Cameron 	/* Find out if it is in the list */
1316ff3f7e04SAlexandru Ardelean 	inlist = iio_buffer_is_active(buffer);
131784b36ce5SJonathan Cameron 	/* Already in desired state */
131884b36ce5SJonathan Cameron 	if (inlist == requested_state)
131984b36ce5SJonathan Cameron 		goto done;
132084b36ce5SJonathan Cameron 
132184b36ce5SJonathan Cameron 	if (requested_state)
1322ff3f7e04SAlexandru Ardelean 		ret = __iio_update_buffers(indio_dev, buffer, NULL);
132384b36ce5SJonathan Cameron 	else
1324ff3f7e04SAlexandru Ardelean 		ret = __iio_update_buffers(indio_dev, NULL, buffer);
132584b36ce5SJonathan Cameron 
132684b36ce5SJonathan Cameron done:
132716afe125SNuno Sá 	mutex_unlock(&iio_dev_opaque->mlock);
132884b36ce5SJonathan Cameron 	return (ret < 0) ? ret : len;
132984b36ce5SJonathan Cameron }
133084b36ce5SJonathan Cameron 
watermark_show(struct device * dev,struct device_attribute * attr,char * buf)13319cf0b618SJoe Simmons-Talbott static ssize_t watermark_show(struct device *dev, struct device_attribute *attr,
133237d34556SJosselin Costanzi 			      char *buf)
133337d34556SJosselin Costanzi {
133415097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
133537d34556SJosselin Costanzi 
133683ca56b6SLars-Peter Clausen 	return sysfs_emit(buf, "%u\n", buffer->watermark);
133737d34556SJosselin Costanzi }
133837d34556SJosselin Costanzi 
watermark_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)13399cf0b618SJoe Simmons-Talbott static ssize_t watermark_store(struct device *dev,
134037d34556SJosselin Costanzi 			       struct device_attribute *attr,
13419cf0b618SJoe Simmons-Talbott 			       const char *buf, size_t len)
134237d34556SJosselin Costanzi {
134337d34556SJosselin Costanzi 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
134416afe125SNuno Sá 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
134515097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
134637d34556SJosselin Costanzi 	unsigned int val;
134737d34556SJosselin Costanzi 	int ret;
134837d34556SJosselin Costanzi 
134937d34556SJosselin Costanzi 	ret = kstrtouint(buf, 10, &val);
135037d34556SJosselin Costanzi 	if (ret)
135137d34556SJosselin Costanzi 		return ret;
135237d34556SJosselin Costanzi 	if (!val)
135337d34556SJosselin Costanzi 		return -EINVAL;
135437d34556SJosselin Costanzi 
135516afe125SNuno Sá 	mutex_lock(&iio_dev_opaque->mlock);
135637d34556SJosselin Costanzi 
135737d34556SJosselin Costanzi 	if (val > buffer->length) {
135837d34556SJosselin Costanzi 		ret = -EINVAL;
135937d34556SJosselin Costanzi 		goto out;
136037d34556SJosselin Costanzi 	}
136137d34556SJosselin Costanzi 
1362ff3f7e04SAlexandru Ardelean 	if (iio_buffer_is_active(buffer)) {
136337d34556SJosselin Costanzi 		ret = -EBUSY;
136437d34556SJosselin Costanzi 		goto out;
136537d34556SJosselin Costanzi 	}
136637d34556SJosselin Costanzi 
136737d34556SJosselin Costanzi 	buffer->watermark = val;
136837d34556SJosselin Costanzi out:
136916afe125SNuno Sá 	mutex_unlock(&iio_dev_opaque->mlock);
137037d34556SJosselin Costanzi 
137137d34556SJosselin Costanzi 	return ret ? ret : len;
137237d34556SJosselin Costanzi }
137337d34556SJosselin Costanzi 
data_available_show(struct device * dev,struct device_attribute * attr,char * buf)13749cf0b618SJoe Simmons-Talbott static ssize_t data_available_show(struct device *dev,
13759cf0b618SJoe Simmons-Talbott 				   struct device_attribute *attr, char *buf)
1376350f6c75SMatt Fornero {
137715097c7aSAlexandru Ardelean 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
1378350f6c75SMatt Fornero 
137983ca56b6SLars-Peter Clausen 	return sysfs_emit(buf, "%zu\n", iio_buffer_data_available(buffer));
1380350f6c75SMatt Fornero }
1381350f6c75SMatt Fornero 
direction_show(struct device * dev,struct device_attribute * attr,char * buf)13829eeee3b0SMihail Chindris static ssize_t direction_show(struct device *dev,
13839eeee3b0SMihail Chindris 			      struct device_attribute *attr,
13849eeee3b0SMihail Chindris 			      char *buf)
13859eeee3b0SMihail Chindris {
13869eeee3b0SMihail Chindris 	struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
13879eeee3b0SMihail Chindris 
13889eeee3b0SMihail Chindris 	switch (buffer->direction) {
13899eeee3b0SMihail Chindris 	case IIO_BUFFER_DIRECTION_IN:
1390c3154defSLars-Peter Clausen 		return sysfs_emit(buf, "in\n");
13919eeee3b0SMihail Chindris 	case IIO_BUFFER_DIRECTION_OUT:
1392c3154defSLars-Peter Clausen 		return sysfs_emit(buf, "out\n");
13939eeee3b0SMihail Chindris 	default:
13949eeee3b0SMihail Chindris 		return -EINVAL;
13959eeee3b0SMihail Chindris 	}
13969eeee3b0SMihail Chindris }
13979eeee3b0SMihail Chindris 
13989cf0b618SJoe Simmons-Talbott static DEVICE_ATTR_RW(length);
13999cf0b618SJoe Simmons-Talbott static struct device_attribute dev_attr_length_ro = __ATTR_RO(length);
14009cf0b618SJoe Simmons-Talbott static DEVICE_ATTR_RW(enable);
14019cf0b618SJoe Simmons-Talbott static DEVICE_ATTR_RW(watermark);
14029cf0b618SJoe Simmons-Talbott static struct device_attribute dev_attr_watermark_ro = __ATTR_RO(watermark);
14039cf0b618SJoe Simmons-Talbott static DEVICE_ATTR_RO(data_available);
14049eeee3b0SMihail Chindris static DEVICE_ATTR_RO(direction);
140508e7e0adSLars-Peter Clausen 
14069eeee3b0SMihail Chindris /*
14079eeee3b0SMihail Chindris  * When adding new attributes here, put the at the end, at least until
14089eeee3b0SMihail Chindris  * the code that handles the length/length_ro & watermark/watermark_ro
14099eeee3b0SMihail Chindris  * assignments gets cleaned up. Otherwise these can create some weird
14109eeee3b0SMihail Chindris  * duplicate attributes errors under some setups.
14119eeee3b0SMihail Chindris  */
14126da9b382SOctavian Purdila static struct attribute *iio_buffer_attrs[] = {
14136da9b382SOctavian Purdila 	&dev_attr_length.attr,
14146da9b382SOctavian Purdila 	&dev_attr_enable.attr,
141537d34556SJosselin Costanzi 	&dev_attr_watermark.attr,
1416350f6c75SMatt Fornero 	&dev_attr_data_available.attr,
14179eeee3b0SMihail Chindris 	&dev_attr_direction.attr,
14186da9b382SOctavian Purdila };
14196da9b382SOctavian Purdila 
142015097c7aSAlexandru Ardelean #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
142115097c7aSAlexandru Ardelean 
iio_buffer_wrap_attr(struct iio_buffer * buffer,struct attribute * attr)142215097c7aSAlexandru Ardelean static struct attribute *iio_buffer_wrap_attr(struct iio_buffer *buffer,
142315097c7aSAlexandru Ardelean 					      struct attribute *attr)
142415097c7aSAlexandru Ardelean {
142515097c7aSAlexandru Ardelean 	struct device_attribute *dattr = to_dev_attr(attr);
142615097c7aSAlexandru Ardelean 	struct iio_dev_attr *iio_attr;
142715097c7aSAlexandru Ardelean 
142815097c7aSAlexandru Ardelean 	iio_attr = kzalloc(sizeof(*iio_attr), GFP_KERNEL);
142915097c7aSAlexandru Ardelean 	if (!iio_attr)
143015097c7aSAlexandru Ardelean 		return NULL;
143115097c7aSAlexandru Ardelean 
143215097c7aSAlexandru Ardelean 	iio_attr->buffer = buffer;
143315097c7aSAlexandru Ardelean 	memcpy(&iio_attr->dev_attr, dattr, sizeof(iio_attr->dev_attr));
143415097c7aSAlexandru Ardelean 	iio_attr->dev_attr.attr.name = kstrdup_const(attr->name, GFP_KERNEL);
14352c0ad3f0SYang Yingliang 	if (!iio_attr->dev_attr.attr.name) {
14362c0ad3f0SYang Yingliang 		kfree(iio_attr);
14372c0ad3f0SYang Yingliang 		return NULL;
14382c0ad3f0SYang Yingliang 	}
14392c0ad3f0SYang Yingliang 
1440ca3e7d52SAlexandru Ardelean 	sysfs_attr_init(&iio_attr->dev_attr.attr);
144115097c7aSAlexandru Ardelean 
144215097c7aSAlexandru Ardelean 	list_add(&iio_attr->l, &buffer->buffer_attr_list);
144315097c7aSAlexandru Ardelean 
144415097c7aSAlexandru Ardelean 	return &iio_attr->dev_attr.attr;
144515097c7aSAlexandru Ardelean }
144615097c7aSAlexandru Ardelean 
iio_buffer_register_legacy_sysfs_groups(struct iio_dev * indio_dev,struct attribute ** buffer_attrs,int buffer_attrcount,int scan_el_attrcount)1447d9a62574SAlexandru Ardelean static int iio_buffer_register_legacy_sysfs_groups(struct iio_dev *indio_dev,
1448d9a62574SAlexandru Ardelean 						   struct attribute **buffer_attrs,
1449d9a62574SAlexandru Ardelean 						   int buffer_attrcount,
1450d9a62574SAlexandru Ardelean 						   int scan_el_attrcount)
1451d9a62574SAlexandru Ardelean {
1452d9a62574SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1453d9a62574SAlexandru Ardelean 	struct attribute_group *group;
1454d9a62574SAlexandru Ardelean 	struct attribute **attrs;
1455d9a62574SAlexandru Ardelean 	int ret;
1456d9a62574SAlexandru Ardelean 
1457d9a62574SAlexandru Ardelean 	attrs = kcalloc(buffer_attrcount + 1, sizeof(*attrs), GFP_KERNEL);
1458d9a62574SAlexandru Ardelean 	if (!attrs)
1459d9a62574SAlexandru Ardelean 		return -ENOMEM;
1460d9a62574SAlexandru Ardelean 
1461d9a62574SAlexandru Ardelean 	memcpy(attrs, buffer_attrs, buffer_attrcount * sizeof(*attrs));
1462d9a62574SAlexandru Ardelean 
1463d9a62574SAlexandru Ardelean 	group = &iio_dev_opaque->legacy_buffer_group;
1464d9a62574SAlexandru Ardelean 	group->attrs = attrs;
1465d9a62574SAlexandru Ardelean 	group->name = "buffer";
1466d9a62574SAlexandru Ardelean 
1467d9a62574SAlexandru Ardelean 	ret = iio_device_register_sysfs_group(indio_dev, group);
1468d9a62574SAlexandru Ardelean 	if (ret)
1469d9a62574SAlexandru Ardelean 		goto error_free_buffer_attrs;
1470d9a62574SAlexandru Ardelean 
1471d9a62574SAlexandru Ardelean 	attrs = kcalloc(scan_el_attrcount + 1, sizeof(*attrs), GFP_KERNEL);
1472d9a62574SAlexandru Ardelean 	if (!attrs) {
1473d9a62574SAlexandru Ardelean 		ret = -ENOMEM;
1474d9a62574SAlexandru Ardelean 		goto error_free_buffer_attrs;
1475d9a62574SAlexandru Ardelean 	}
1476d9a62574SAlexandru Ardelean 
1477d9a62574SAlexandru Ardelean 	memcpy(attrs, &buffer_attrs[buffer_attrcount],
1478d9a62574SAlexandru Ardelean 	       scan_el_attrcount * sizeof(*attrs));
1479d9a62574SAlexandru Ardelean 
1480d9a62574SAlexandru Ardelean 	group = &iio_dev_opaque->legacy_scan_el_group;
1481d9a62574SAlexandru Ardelean 	group->attrs = attrs;
1482d9a62574SAlexandru Ardelean 	group->name = "scan_elements";
1483d9a62574SAlexandru Ardelean 
1484d9a62574SAlexandru Ardelean 	ret = iio_device_register_sysfs_group(indio_dev, group);
1485d9a62574SAlexandru Ardelean 	if (ret)
1486d9a62574SAlexandru Ardelean 		goto error_free_scan_el_attrs;
1487d9a62574SAlexandru Ardelean 
1488d9a62574SAlexandru Ardelean 	return 0;
1489d9a62574SAlexandru Ardelean 
1490d9a62574SAlexandru Ardelean error_free_scan_el_attrs:
1491d9a62574SAlexandru Ardelean 	kfree(iio_dev_opaque->legacy_scan_el_group.attrs);
1492604faf9aSYang Yingliang error_free_buffer_attrs:
1493604faf9aSYang Yingliang 	kfree(iio_dev_opaque->legacy_buffer_group.attrs);
1494d9a62574SAlexandru Ardelean 
1495d9a62574SAlexandru Ardelean 	return ret;
1496d9a62574SAlexandru Ardelean }
1497d9a62574SAlexandru Ardelean 
iio_buffer_unregister_legacy_sysfs_groups(struct iio_dev * indio_dev)1498d9a62574SAlexandru Ardelean static void iio_buffer_unregister_legacy_sysfs_groups(struct iio_dev *indio_dev)
1499d9a62574SAlexandru Ardelean {
1500d9a62574SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1501d9a62574SAlexandru Ardelean 
1502d9a62574SAlexandru Ardelean 	kfree(iio_dev_opaque->legacy_buffer_group.attrs);
1503d9a62574SAlexandru Ardelean 	kfree(iio_dev_opaque->legacy_scan_el_group.attrs);
1504d9a62574SAlexandru Ardelean }
1505d9a62574SAlexandru Ardelean 
iio_buffer_chrdev_release(struct inode * inode,struct file * filep)1506f73f7f4dSAlexandru Ardelean static int iio_buffer_chrdev_release(struct inode *inode, struct file *filep)
1507f73f7f4dSAlexandru Ardelean {
1508f73f7f4dSAlexandru Ardelean 	struct iio_dev_buffer_pair *ib = filep->private_data;
1509f73f7f4dSAlexandru Ardelean 	struct iio_dev *indio_dev = ib->indio_dev;
1510f73f7f4dSAlexandru Ardelean 	struct iio_buffer *buffer = ib->buffer;
1511f73f7f4dSAlexandru Ardelean 
1512f73f7f4dSAlexandru Ardelean 	wake_up(&buffer->pollq);
1513f73f7f4dSAlexandru Ardelean 
1514f73f7f4dSAlexandru Ardelean 	kfree(ib);
1515f73f7f4dSAlexandru Ardelean 	clear_bit(IIO_BUSY_BIT_POS, &buffer->flags);
1516f73f7f4dSAlexandru Ardelean 	iio_device_put(indio_dev);
1517f73f7f4dSAlexandru Ardelean 
1518f73f7f4dSAlexandru Ardelean 	return 0;
1519f73f7f4dSAlexandru Ardelean }
1520f73f7f4dSAlexandru Ardelean 
1521f73f7f4dSAlexandru Ardelean static const struct file_operations iio_buffer_chrdev_fileops = {
1522f73f7f4dSAlexandru Ardelean 	.owner = THIS_MODULE,
1523f73f7f4dSAlexandru Ardelean 	.llseek = noop_llseek,
1524f73f7f4dSAlexandru Ardelean 	.read = iio_buffer_read,
15259eeee3b0SMihail Chindris 	.write = iio_buffer_write,
1526f73f7f4dSAlexandru Ardelean 	.poll = iio_buffer_poll,
1527f73f7f4dSAlexandru Ardelean 	.release = iio_buffer_chrdev_release,
1528f73f7f4dSAlexandru Ardelean };
1529f73f7f4dSAlexandru Ardelean 
iio_device_buffer_getfd(struct iio_dev * indio_dev,unsigned long arg)1530f73f7f4dSAlexandru Ardelean static long iio_device_buffer_getfd(struct iio_dev *indio_dev, unsigned long arg)
1531f73f7f4dSAlexandru Ardelean {
1532f73f7f4dSAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1533f73f7f4dSAlexandru Ardelean 	int __user *ival = (int __user *)arg;
1534f73f7f4dSAlexandru Ardelean 	struct iio_dev_buffer_pair *ib;
1535f73f7f4dSAlexandru Ardelean 	struct iio_buffer *buffer;
1536f73f7f4dSAlexandru Ardelean 	int fd, idx, ret;
1537f73f7f4dSAlexandru Ardelean 
1538f73f7f4dSAlexandru Ardelean 	if (copy_from_user(&idx, ival, sizeof(idx)))
1539f73f7f4dSAlexandru Ardelean 		return -EFAULT;
1540f73f7f4dSAlexandru Ardelean 
1541f73f7f4dSAlexandru Ardelean 	if (idx >= iio_dev_opaque->attached_buffers_cnt)
1542f73f7f4dSAlexandru Ardelean 		return -ENODEV;
1543f73f7f4dSAlexandru Ardelean 
1544f73f7f4dSAlexandru Ardelean 	iio_device_get(indio_dev);
1545f73f7f4dSAlexandru Ardelean 
1546f73f7f4dSAlexandru Ardelean 	buffer = iio_dev_opaque->attached_buffers[idx];
1547f73f7f4dSAlexandru Ardelean 
1548f73f7f4dSAlexandru Ardelean 	if (test_and_set_bit(IIO_BUSY_BIT_POS, &buffer->flags)) {
1549f73f7f4dSAlexandru Ardelean 		ret = -EBUSY;
1550f73f7f4dSAlexandru Ardelean 		goto error_iio_dev_put;
1551f73f7f4dSAlexandru Ardelean 	}
1552f73f7f4dSAlexandru Ardelean 
1553f73f7f4dSAlexandru Ardelean 	ib = kzalloc(sizeof(*ib), GFP_KERNEL);
1554f73f7f4dSAlexandru Ardelean 	if (!ib) {
1555f73f7f4dSAlexandru Ardelean 		ret = -ENOMEM;
1556f73f7f4dSAlexandru Ardelean 		goto error_clear_busy_bit;
1557f73f7f4dSAlexandru Ardelean 	}
1558f73f7f4dSAlexandru Ardelean 
1559f73f7f4dSAlexandru Ardelean 	ib->indio_dev = indio_dev;
1560f73f7f4dSAlexandru Ardelean 	ib->buffer = buffer;
1561f73f7f4dSAlexandru Ardelean 
1562f73f7f4dSAlexandru Ardelean 	fd = anon_inode_getfd("iio:buffer", &iio_buffer_chrdev_fileops,
1563f73f7f4dSAlexandru Ardelean 			      ib, O_RDWR | O_CLOEXEC);
1564f73f7f4dSAlexandru Ardelean 	if (fd < 0) {
1565f73f7f4dSAlexandru Ardelean 		ret = fd;
1566f73f7f4dSAlexandru Ardelean 		goto error_free_ib;
1567f73f7f4dSAlexandru Ardelean 	}
1568f73f7f4dSAlexandru Ardelean 
1569f73f7f4dSAlexandru Ardelean 	if (copy_to_user(ival, &fd, sizeof(fd))) {
1570c72ea205SMathias Krause 		/*
1571c72ea205SMathias Krause 		 * "Leak" the fd, as there's not much we can do about this
1572c72ea205SMathias Krause 		 * anyway. 'fd' might have been closed already, as
1573c72ea205SMathias Krause 		 * anon_inode_getfd() called fd_install() on it, which made
1574c72ea205SMathias Krause 		 * it reachable by userland.
1575c72ea205SMathias Krause 		 *
1576c72ea205SMathias Krause 		 * Instead of allowing a malicious user to play tricks with
1577c72ea205SMathias Krause 		 * us, rely on the process exit path to do any necessary
1578c72ea205SMathias Krause 		 * cleanup, as in releasing the file, if still needed.
1579c72ea205SMathias Krause 		 */
1580c72ea205SMathias Krause 		return -EFAULT;
1581f73f7f4dSAlexandru Ardelean 	}
1582f73f7f4dSAlexandru Ardelean 
15834c822244SAlexandru Ardelean 	return 0;
1584f73f7f4dSAlexandru Ardelean 
1585f73f7f4dSAlexandru Ardelean error_free_ib:
1586f73f7f4dSAlexandru Ardelean 	kfree(ib);
1587f73f7f4dSAlexandru Ardelean error_clear_busy_bit:
1588f73f7f4dSAlexandru Ardelean 	clear_bit(IIO_BUSY_BIT_POS, &buffer->flags);
1589f73f7f4dSAlexandru Ardelean error_iio_dev_put:
1590f73f7f4dSAlexandru Ardelean 	iio_device_put(indio_dev);
1591f73f7f4dSAlexandru Ardelean 	return ret;
1592f73f7f4dSAlexandru Ardelean }
1593f73f7f4dSAlexandru Ardelean 
iio_device_buffer_ioctl(struct iio_dev * indio_dev,struct file * filp,unsigned int cmd,unsigned long arg)1594f73f7f4dSAlexandru Ardelean static long iio_device_buffer_ioctl(struct iio_dev *indio_dev, struct file *filp,
1595f73f7f4dSAlexandru Ardelean 				    unsigned int cmd, unsigned long arg)
1596f73f7f4dSAlexandru Ardelean {
1597f73f7f4dSAlexandru Ardelean 	switch (cmd) {
1598f73f7f4dSAlexandru Ardelean 	case IIO_BUFFER_GET_FD_IOCTL:
1599f73f7f4dSAlexandru Ardelean 		return iio_device_buffer_getfd(indio_dev, arg);
1600f73f7f4dSAlexandru Ardelean 	default:
1601f73f7f4dSAlexandru Ardelean 		return IIO_IOCTL_UNHANDLED;
1602f73f7f4dSAlexandru Ardelean 	}
1603f73f7f4dSAlexandru Ardelean }
1604f73f7f4dSAlexandru Ardelean 
__iio_buffer_alloc_sysfs_and_mask(struct iio_buffer * buffer,struct iio_dev * indio_dev,int index)1605e16e0a77SAlexandru Ardelean static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
1606d9a62574SAlexandru Ardelean 					     struct iio_dev *indio_dev,
1607d9a62574SAlexandru Ardelean 					     int index)
1608d967cb6bSLars-Peter Clausen {
160962f4f36cSJonathan Cameron 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1610d967cb6bSLars-Peter Clausen 	struct iio_dev_attr *p;
16110a33755cSMatti Vaittinen 	const struct iio_dev_attr *id_attr;
1612d967cb6bSLars-Peter Clausen 	struct attribute **attr;
1613e2b4d7acSAlexandru Ardelean 	int ret, i, attrn, scan_el_attrcount, buffer_attrcount;
1614d967cb6bSLars-Peter Clausen 	const struct iio_chan_spec *channels;
1615d967cb6bSLars-Peter Clausen 
1616e2b4d7acSAlexandru Ardelean 	buffer_attrcount = 0;
161708e7e0adSLars-Peter Clausen 	if (buffer->attrs) {
1618e2b4d7acSAlexandru Ardelean 		while (buffer->attrs[buffer_attrcount])
1619e2b4d7acSAlexandru Ardelean 			buffer_attrcount++;
162008e7e0adSLars-Peter Clausen 	}
16210a33755cSMatti Vaittinen 	buffer_attrcount += ARRAY_SIZE(iio_buffer_attrs);
162208e7e0adSLars-Peter Clausen 
1623e2b4d7acSAlexandru Ardelean 	scan_el_attrcount = 0;
162415097c7aSAlexandru Ardelean 	INIT_LIST_HEAD(&buffer->buffer_attr_list);
1625d967cb6bSLars-Peter Clausen 	channels = indio_dev->channels;
1626d967cb6bSLars-Peter Clausen 	if (channels) {
1627d967cb6bSLars-Peter Clausen 		/* new magic */
1628d967cb6bSLars-Peter Clausen 		for (i = 0; i < indio_dev->num_channels; i++) {
1629d967cb6bSLars-Peter Clausen 			if (channels[i].scan_index < 0)
1630d967cb6bSLars-Peter Clausen 				continue;
1631d967cb6bSLars-Peter Clausen 
1632fd542c5eSMarek Vasut 			/* Verify that sample bits fit into storage */
1633fd542c5eSMarek Vasut 			if (channels[i].scan_type.storagebits <
1634fd542c5eSMarek Vasut 			    channels[i].scan_type.realbits +
1635fd542c5eSMarek Vasut 			    channels[i].scan_type.shift) {
1636fd542c5eSMarek Vasut 				dev_err(&indio_dev->dev,
1637fd542c5eSMarek Vasut 					"Channel %d storagebits (%d) < shifted realbits (%d + %d)\n",
1638fd542c5eSMarek Vasut 					i, channels[i].scan_type.storagebits,
1639fd542c5eSMarek Vasut 					channels[i].scan_type.realbits,
1640fd542c5eSMarek Vasut 					channels[i].scan_type.shift);
1641fd542c5eSMarek Vasut 				ret = -EINVAL;
1642fd542c5eSMarek Vasut 				goto error_cleanup_dynamic;
1643fd542c5eSMarek Vasut 			}
1644fd542c5eSMarek Vasut 
1645ff3f7e04SAlexandru Ardelean 			ret = iio_buffer_add_channel_sysfs(indio_dev, buffer,
1646d967cb6bSLars-Peter Clausen 							   &channels[i]);
1647d967cb6bSLars-Peter Clausen 			if (ret < 0)
1648d967cb6bSLars-Peter Clausen 				goto error_cleanup_dynamic;
1649e2b4d7acSAlexandru Ardelean 			scan_el_attrcount += ret;
1650d967cb6bSLars-Peter Clausen 			if (channels[i].type == IIO_TIMESTAMP)
165162f4f36cSJonathan Cameron 				iio_dev_opaque->scan_index_timestamp =
1652d967cb6bSLars-Peter Clausen 					channels[i].scan_index;
1653d967cb6bSLars-Peter Clausen 		}
1654d967cb6bSLars-Peter Clausen 		if (indio_dev->masklength && !buffer->scan_mask) {
16553862828aSAndy Shevchenko 			buffer->scan_mask = bitmap_zalloc(indio_dev->masklength,
1656d967cb6bSLars-Peter Clausen 							  GFP_KERNEL);
1657d967cb6bSLars-Peter Clausen 			if (!buffer->scan_mask) {
1658d967cb6bSLars-Peter Clausen 				ret = -ENOMEM;
1659d967cb6bSLars-Peter Clausen 				goto error_cleanup_dynamic;
1660d967cb6bSLars-Peter Clausen 			}
1661d967cb6bSLars-Peter Clausen 		}
1662d967cb6bSLars-Peter Clausen 	}
1663d967cb6bSLars-Peter Clausen 
16640a33755cSMatti Vaittinen 	attrn = buffer_attrcount + scan_el_attrcount;
1665d9a62574SAlexandru Ardelean 	attr = kcalloc(attrn + 1, sizeof(*attr), GFP_KERNEL);
1666e2b4d7acSAlexandru Ardelean 	if (!attr) {
1667e2b4d7acSAlexandru Ardelean 		ret = -ENOMEM;
1668e2b4d7acSAlexandru Ardelean 		goto error_free_scan_mask;
1669e2b4d7acSAlexandru Ardelean 	}
1670e2b4d7acSAlexandru Ardelean 
1671e2b4d7acSAlexandru Ardelean 	memcpy(attr, iio_buffer_attrs, sizeof(iio_buffer_attrs));
1672e2b4d7acSAlexandru Ardelean 	if (!buffer->access->set_length)
1673e2b4d7acSAlexandru Ardelean 		attr[0] = &dev_attr_length_ro.attr;
1674e2b4d7acSAlexandru Ardelean 
1675e2b4d7acSAlexandru Ardelean 	if (buffer->access->flags & INDIO_BUFFER_FLAG_FIXED_WATERMARK)
1676e2b4d7acSAlexandru Ardelean 		attr[2] = &dev_attr_watermark_ro.attr;
1677e2b4d7acSAlexandru Ardelean 
1678e2b4d7acSAlexandru Ardelean 	if (buffer->attrs)
16790a33755cSMatti Vaittinen 		for (i = 0, id_attr = buffer->attrs[i];
16800a33755cSMatti Vaittinen 		     (id_attr = buffer->attrs[i]); i++)
16810a33755cSMatti Vaittinen 			attr[ARRAY_SIZE(iio_buffer_attrs) + i] =
16820a33755cSMatti Vaittinen 				(struct attribute *)&id_attr->dev_attr.attr;
1683e2b4d7acSAlexandru Ardelean 
16849a2ff800SYang Yingliang 	buffer->buffer_group.attrs = attr;
1685e2b4d7acSAlexandru Ardelean 
168615097c7aSAlexandru Ardelean 	for (i = 0; i < buffer_attrcount; i++) {
168715097c7aSAlexandru Ardelean 		struct attribute *wrapped;
1688d9a62574SAlexandru Ardelean 
168915097c7aSAlexandru Ardelean 		wrapped = iio_buffer_wrap_attr(buffer, attr[i]);
169015097c7aSAlexandru Ardelean 		if (!wrapped) {
169115097c7aSAlexandru Ardelean 			ret = -ENOMEM;
16929a2ff800SYang Yingliang 			goto error_free_buffer_attrs;
169315097c7aSAlexandru Ardelean 		}
169415097c7aSAlexandru Ardelean 		attr[i] = wrapped;
169515097c7aSAlexandru Ardelean 	}
169615097c7aSAlexandru Ardelean 
169715097c7aSAlexandru Ardelean 	attrn = 0;
169815097c7aSAlexandru Ardelean 	list_for_each_entry(p, &buffer->buffer_attr_list, l)
1699d9a62574SAlexandru Ardelean 		attr[attrn++] = &p->dev_attr.attr;
1700d9a62574SAlexandru Ardelean 
1701d9a62574SAlexandru Ardelean 	buffer->buffer_group.name = kasprintf(GFP_KERNEL, "buffer%d", index);
1702d9a62574SAlexandru Ardelean 	if (!buffer->buffer_group.name) {
1703d9a62574SAlexandru Ardelean 		ret = -ENOMEM;
1704d9a62574SAlexandru Ardelean 		goto error_free_buffer_attrs;
1705d9a62574SAlexandru Ardelean 	}
1706d9a62574SAlexandru Ardelean 
1707e2b4d7acSAlexandru Ardelean 	ret = iio_device_register_sysfs_group(indio_dev, &buffer->buffer_group);
1708e2b4d7acSAlexandru Ardelean 	if (ret)
1709d9a62574SAlexandru Ardelean 		goto error_free_buffer_attr_group_name;
1710e2b4d7acSAlexandru Ardelean 
1711d9a62574SAlexandru Ardelean 	/* we only need to register the legacy groups for the first buffer */
1712d9a62574SAlexandru Ardelean 	if (index > 0)
1713d9a62574SAlexandru Ardelean 		return 0;
1714d967cb6bSLars-Peter Clausen 
1715d9a62574SAlexandru Ardelean 	ret = iio_buffer_register_legacy_sysfs_groups(indio_dev, attr,
1716d9a62574SAlexandru Ardelean 						      buffer_attrcount,
1717d9a62574SAlexandru Ardelean 						      scan_el_attrcount);
171832f17172SAlexandru Ardelean 	if (ret)
1719d9a62574SAlexandru Ardelean 		goto error_free_buffer_attr_group_name;
1720d967cb6bSLars-Peter Clausen 
1721d967cb6bSLars-Peter Clausen 	return 0;
1722d967cb6bSLars-Peter Clausen 
1723d9a62574SAlexandru Ardelean error_free_buffer_attr_group_name:
1724d9a62574SAlexandru Ardelean 	kfree(buffer->buffer_group.name);
1725e2b4d7acSAlexandru Ardelean error_free_buffer_attrs:
1726e2b4d7acSAlexandru Ardelean 	kfree(buffer->buffer_group.attrs);
1727d967cb6bSLars-Peter Clausen error_free_scan_mask:
17283862828aSAndy Shevchenko 	bitmap_free(buffer->scan_mask);
1729d967cb6bSLars-Peter Clausen error_cleanup_dynamic:
173015097c7aSAlexandru Ardelean 	iio_free_chan_devattr_list(&buffer->buffer_attr_list);
1731d967cb6bSLars-Peter Clausen 
1732d967cb6bSLars-Peter Clausen 	return ret;
1733d967cb6bSLars-Peter Clausen }
1734d967cb6bSLars-Peter Clausen 
__iio_buffer_free_sysfs_and_mask(struct iio_buffer * buffer,struct iio_dev * indio_dev,int index)1735486a2508SYang Yingliang static void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer,
1736486a2508SYang Yingliang 					     struct iio_dev *indio_dev,
1737486a2508SYang Yingliang 					     int index)
17380224af85SAlexandru Ardelean {
1739486a2508SYang Yingliang 	if (index == 0)
1740486a2508SYang Yingliang 		iio_buffer_unregister_legacy_sysfs_groups(indio_dev);
17410224af85SAlexandru Ardelean 	bitmap_free(buffer->scan_mask);
17420224af85SAlexandru Ardelean 	kfree(buffer->buffer_group.name);
17430224af85SAlexandru Ardelean 	kfree(buffer->buffer_group.attrs);
17440224af85SAlexandru Ardelean 	iio_free_chan_devattr_list(&buffer->buffer_attr_list);
17450224af85SAlexandru Ardelean }
17460224af85SAlexandru Ardelean 
iio_buffers_alloc_sysfs_and_mask(struct iio_dev * indio_dev)1747ee708e6bSAlexandru Ardelean int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
1748e16e0a77SAlexandru Ardelean {
1749ee708e6bSAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1750e16e0a77SAlexandru Ardelean 	const struct iio_chan_spec *channels;
1751ee708e6bSAlexandru Ardelean 	struct iio_buffer *buffer;
1752e5cc9840SAndy Shevchenko 	int ret, i, idx;
1753f73f7f4dSAlexandru Ardelean 	size_t sz;
1754e16e0a77SAlexandru Ardelean 
1755e16e0a77SAlexandru Ardelean 	channels = indio_dev->channels;
1756e16e0a77SAlexandru Ardelean 	if (channels) {
1757e16e0a77SAlexandru Ardelean 		int ml = indio_dev->masklength;
1758e16e0a77SAlexandru Ardelean 
1759e16e0a77SAlexandru Ardelean 		for (i = 0; i < indio_dev->num_channels; i++)
1760e16e0a77SAlexandru Ardelean 			ml = max(ml, channels[i].scan_index + 1);
1761e16e0a77SAlexandru Ardelean 		indio_dev->masklength = ml;
1762e16e0a77SAlexandru Ardelean 	}
1763e16e0a77SAlexandru Ardelean 
1764ee708e6bSAlexandru Ardelean 	if (!iio_dev_opaque->attached_buffers_cnt)
1765e16e0a77SAlexandru Ardelean 		return 0;
1766e16e0a77SAlexandru Ardelean 
1767e5cc9840SAndy Shevchenko 	for (idx = 0; idx < iio_dev_opaque->attached_buffers_cnt; idx++) {
1768e5cc9840SAndy Shevchenko 		buffer = iio_dev_opaque->attached_buffers[idx];
1769e5cc9840SAndy Shevchenko 		ret = __iio_buffer_alloc_sysfs_and_mask(buffer, indio_dev, idx);
1770e5cc9840SAndy Shevchenko 		if (ret)
1771ee708e6bSAlexandru Ardelean 			goto error_unwind_sysfs_and_mask;
1772ee708e6bSAlexandru Ardelean 	}
1773f73f7f4dSAlexandru Ardelean 
1774f73f7f4dSAlexandru Ardelean 	sz = sizeof(*iio_dev_opaque->buffer_ioctl_handler);
1775f73f7f4dSAlexandru Ardelean 	iio_dev_opaque->buffer_ioctl_handler = kzalloc(sz, GFP_KERNEL);
1776f73f7f4dSAlexandru Ardelean 	if (!iio_dev_opaque->buffer_ioctl_handler) {
1777f73f7f4dSAlexandru Ardelean 		ret = -ENOMEM;
1778f73f7f4dSAlexandru Ardelean 		goto error_unwind_sysfs_and_mask;
1779f73f7f4dSAlexandru Ardelean 	}
1780f73f7f4dSAlexandru Ardelean 
1781f73f7f4dSAlexandru Ardelean 	iio_dev_opaque->buffer_ioctl_handler->ioctl = iio_device_buffer_ioctl;
1782f73f7f4dSAlexandru Ardelean 	iio_device_ioctl_handler_register(indio_dev,
1783f73f7f4dSAlexandru Ardelean 					  iio_dev_opaque->buffer_ioctl_handler);
1784e16e0a77SAlexandru Ardelean 
1785ee708e6bSAlexandru Ardelean 	return 0;
1786ff3f7e04SAlexandru Ardelean 
1787ee708e6bSAlexandru Ardelean error_unwind_sysfs_and_mask:
1788e5cc9840SAndy Shevchenko 	while (idx--) {
1789e5cc9840SAndy Shevchenko 		buffer = iio_dev_opaque->attached_buffers[idx];
1790e5cc9840SAndy Shevchenko 		__iio_buffer_free_sysfs_and_mask(buffer, indio_dev, idx);
1791ee708e6bSAlexandru Ardelean 	}
1792ee708e6bSAlexandru Ardelean 	return ret;
1793ee708e6bSAlexandru Ardelean }
1794ee708e6bSAlexandru Ardelean 
iio_buffers_free_sysfs_and_mask(struct iio_dev * indio_dev)1795ee708e6bSAlexandru Ardelean void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev)
1796ee708e6bSAlexandru Ardelean {
1797ee708e6bSAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1798ee708e6bSAlexandru Ardelean 	struct iio_buffer *buffer;
1799ee708e6bSAlexandru Ardelean 	int i;
1800ee708e6bSAlexandru Ardelean 
1801ee708e6bSAlexandru Ardelean 	if (!iio_dev_opaque->attached_buffers_cnt)
1802d967cb6bSLars-Peter Clausen 		return;
1803d967cb6bSLars-Peter Clausen 
1804f73f7f4dSAlexandru Ardelean 	iio_device_ioctl_handler_unregister(iio_dev_opaque->buffer_ioctl_handler);
1805f73f7f4dSAlexandru Ardelean 	kfree(iio_dev_opaque->buffer_ioctl_handler);
1806f73f7f4dSAlexandru Ardelean 
1807ee708e6bSAlexandru Ardelean 	for (i = iio_dev_opaque->attached_buffers_cnt - 1; i >= 0; i--) {
1808ee708e6bSAlexandru Ardelean 		buffer = iio_dev_opaque->attached_buffers[i];
1809486a2508SYang Yingliang 		__iio_buffer_free_sysfs_and_mask(buffer, indio_dev, i);
1810d967cb6bSLars-Peter Clausen 	}
1811ee708e6bSAlexandru Ardelean }
1812ee708e6bSAlexandru Ardelean 
1813a980e046SJonathan Cameron /**
181481636632SLars-Peter Clausen  * iio_validate_scan_mask_onehot() - Validates that exactly one channel is selected
181581636632SLars-Peter Clausen  * @indio_dev: the iio device
181681636632SLars-Peter Clausen  * @mask: scan mask to be checked
181781636632SLars-Peter Clausen  *
181881636632SLars-Peter Clausen  * Return true if exactly one bit is set in the scan mask, false otherwise. It
181981636632SLars-Peter Clausen  * can be used for devices where only one channel can be active for sampling at
182081636632SLars-Peter Clausen  * a time.
182181636632SLars-Peter Clausen  */
iio_validate_scan_mask_onehot(struct iio_dev * indio_dev,const unsigned long * mask)182281636632SLars-Peter Clausen bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev,
182381636632SLars-Peter Clausen 				   const unsigned long *mask)
182481636632SLars-Peter Clausen {
182581636632SLars-Peter Clausen 	return bitmap_weight(mask, indio_dev->masklength) == 1;
182681636632SLars-Peter Clausen }
182781636632SLars-Peter Clausen EXPORT_SYMBOL_GPL(iio_validate_scan_mask_onehot);
182881636632SLars-Peter Clausen 
iio_demux(struct iio_buffer * buffer,const void * datain)18295d65d920SLars-Peter Clausen static const void *iio_demux(struct iio_buffer *buffer,
18305d65d920SLars-Peter Clausen 			     const void *datain)
1831a980e046SJonathan Cameron {
1832a980e046SJonathan Cameron 	struct iio_demux_table *t;
1833a980e046SJonathan Cameron 
1834a980e046SJonathan Cameron 	if (list_empty(&buffer->demux_list))
1835a980e046SJonathan Cameron 		return datain;
1836a980e046SJonathan Cameron 	list_for_each_entry(t, &buffer->demux_list, l)
1837a980e046SJonathan Cameron 		memcpy(buffer->demux_bounce + t->to,
1838a980e046SJonathan Cameron 		       datain + t->from, t->length);
1839a980e046SJonathan Cameron 
1840a980e046SJonathan Cameron 	return buffer->demux_bounce;
1841a980e046SJonathan Cameron }
1842a980e046SJonathan Cameron 
iio_push_to_buffer(struct iio_buffer * buffer,const void * data)18435d65d920SLars-Peter Clausen static int iio_push_to_buffer(struct iio_buffer *buffer, const void *data)
1844a980e046SJonathan Cameron {
18455d65d920SLars-Peter Clausen 	const void *dataout = iio_demux(buffer, data);
184637d34556SJosselin Costanzi 	int ret;
1847a980e046SJonathan Cameron 
184837d34556SJosselin Costanzi 	ret = buffer->access->store_to(buffer, dataout);
184937d34556SJosselin Costanzi 	if (ret)
185037d34556SJosselin Costanzi 		return ret;
185137d34556SJosselin Costanzi 
185237d34556SJosselin Costanzi 	/*
185337d34556SJosselin Costanzi 	 * We can't just test for watermark to decide if we wake the poll queue
185437d34556SJosselin Costanzi 	 * because read may request less samples than the watermark.
185537d34556SJosselin Costanzi 	 */
1856a9a08845SLinus Torvalds 	wake_up_interruptible_poll(&buffer->pollq, EPOLLIN | EPOLLRDNORM);
185737d34556SJosselin Costanzi 	return 0;
1858a980e046SJonathan Cameron }
1859a980e046SJonathan Cameron 
1860315a19ecSJonathan Cameron /**
1861315a19ecSJonathan Cameron  * iio_push_to_buffers() - push to a registered buffer.
1862315a19ecSJonathan Cameron  * @indio_dev:		iio_dev structure for device.
1863315a19ecSJonathan Cameron  * @data:		Full scan.
1864315a19ecSJonathan Cameron  */
iio_push_to_buffers(struct iio_dev * indio_dev,const void * data)18655d65d920SLars-Peter Clausen int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data)
186684b36ce5SJonathan Cameron {
18676a8c6b26SAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
186884b36ce5SJonathan Cameron 	int ret;
186984b36ce5SJonathan Cameron 	struct iio_buffer *buf;
187084b36ce5SJonathan Cameron 
18716a8c6b26SAlexandru Ardelean 	list_for_each_entry(buf, &iio_dev_opaque->buffer_list, buffer_list) {
187284b36ce5SJonathan Cameron 		ret = iio_push_to_buffer(buf, data);
187384b36ce5SJonathan Cameron 		if (ret < 0)
187484b36ce5SJonathan Cameron 			return ret;
187584b36ce5SJonathan Cameron 	}
187684b36ce5SJonathan Cameron 
187784b36ce5SJonathan Cameron 	return 0;
187884b36ce5SJonathan Cameron }
187984b36ce5SJonathan Cameron EXPORT_SYMBOL_GPL(iio_push_to_buffers);
188084b36ce5SJonathan Cameron 
18819e69c935SLars-Peter Clausen /**
188295ec3fdfSJonathan Cameron  * iio_push_to_buffers_with_ts_unaligned() - push to registered buffer,
188395ec3fdfSJonathan Cameron  *    no alignment or space requirements.
188495ec3fdfSJonathan Cameron  * @indio_dev:		iio_dev structure for device.
188595ec3fdfSJonathan Cameron  * @data:		channel data excluding the timestamp.
188695ec3fdfSJonathan Cameron  * @data_sz:		size of data.
188795ec3fdfSJonathan Cameron  * @timestamp:		timestamp for the sample data.
188895ec3fdfSJonathan Cameron  *
188995ec3fdfSJonathan Cameron  * This special variant of iio_push_to_buffers_with_timestamp() does
189095ec3fdfSJonathan Cameron  * not require space for the timestamp, or 8 byte alignment of data.
189195ec3fdfSJonathan Cameron  * It does however require an allocation on first call and additional
189295ec3fdfSJonathan Cameron  * copies on all calls, so should be avoided if possible.
189395ec3fdfSJonathan Cameron  */
iio_push_to_buffers_with_ts_unaligned(struct iio_dev * indio_dev,const void * data,size_t data_sz,int64_t timestamp)189495ec3fdfSJonathan Cameron int iio_push_to_buffers_with_ts_unaligned(struct iio_dev *indio_dev,
189595ec3fdfSJonathan Cameron 					  const void *data,
189695ec3fdfSJonathan Cameron 					  size_t data_sz,
189795ec3fdfSJonathan Cameron 					  int64_t timestamp)
189895ec3fdfSJonathan Cameron {
189995ec3fdfSJonathan Cameron 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
190095ec3fdfSJonathan Cameron 
190195ec3fdfSJonathan Cameron 	/*
190295ec3fdfSJonathan Cameron 	 * Conservative estimate - we can always safely copy the minimum
190395ec3fdfSJonathan Cameron 	 * of either the data provided or the length of the destination buffer.
190495ec3fdfSJonathan Cameron 	 * This relaxed limit allows the calling drivers to be lax about
190595ec3fdfSJonathan Cameron 	 * tracking the size of the data they are pushing, at the cost of
190695ec3fdfSJonathan Cameron 	 * unnecessary copying of padding.
190795ec3fdfSJonathan Cameron 	 */
190895ec3fdfSJonathan Cameron 	data_sz = min_t(size_t, indio_dev->scan_bytes, data_sz);
190995ec3fdfSJonathan Cameron 	if (iio_dev_opaque->bounce_buffer_size !=  indio_dev->scan_bytes) {
191095ec3fdfSJonathan Cameron 		void *bb;
191195ec3fdfSJonathan Cameron 
191295ec3fdfSJonathan Cameron 		bb = devm_krealloc(&indio_dev->dev,
191395ec3fdfSJonathan Cameron 				   iio_dev_opaque->bounce_buffer,
191495ec3fdfSJonathan Cameron 				   indio_dev->scan_bytes, GFP_KERNEL);
191595ec3fdfSJonathan Cameron 		if (!bb)
191695ec3fdfSJonathan Cameron 			return -ENOMEM;
191795ec3fdfSJonathan Cameron 		iio_dev_opaque->bounce_buffer = bb;
191895ec3fdfSJonathan Cameron 		iio_dev_opaque->bounce_buffer_size = indio_dev->scan_bytes;
191995ec3fdfSJonathan Cameron 	}
192095ec3fdfSJonathan Cameron 	memcpy(iio_dev_opaque->bounce_buffer, data, data_sz);
192195ec3fdfSJonathan Cameron 	return iio_push_to_buffers_with_timestamp(indio_dev,
192295ec3fdfSJonathan Cameron 						  iio_dev_opaque->bounce_buffer,
192395ec3fdfSJonathan Cameron 						  timestamp);
192495ec3fdfSJonathan Cameron }
192595ec3fdfSJonathan Cameron EXPORT_SYMBOL_GPL(iio_push_to_buffers_with_ts_unaligned);
192695ec3fdfSJonathan Cameron 
192795ec3fdfSJonathan Cameron /**
19289e69c935SLars-Peter Clausen  * iio_buffer_release() - Free a buffer's resources
19299e69c935SLars-Peter Clausen  * @ref: Pointer to the kref embedded in the iio_buffer struct
19309e69c935SLars-Peter Clausen  *
19319e69c935SLars-Peter Clausen  * This function is called when the last reference to the buffer has been
19329e69c935SLars-Peter Clausen  * dropped. It will typically free all resources allocated by the buffer. Do not
19339e69c935SLars-Peter Clausen  * call this function manually, always use iio_buffer_put() when done using a
19349e69c935SLars-Peter Clausen  * buffer.
19359e69c935SLars-Peter Clausen  */
iio_buffer_release(struct kref * ref)19369e69c935SLars-Peter Clausen static void iio_buffer_release(struct kref *ref)
19379e69c935SLars-Peter Clausen {
19389e69c935SLars-Peter Clausen 	struct iio_buffer *buffer = container_of(ref, struct iio_buffer, ref);
19399e69c935SLars-Peter Clausen 
19409e69c935SLars-Peter Clausen 	buffer->access->release(buffer);
19419e69c935SLars-Peter Clausen }
19429e69c935SLars-Peter Clausen 
19439e69c935SLars-Peter Clausen /**
19449e69c935SLars-Peter Clausen  * iio_buffer_get() - Grab a reference to the buffer
19459e69c935SLars-Peter Clausen  * @buffer: The buffer to grab a reference for, may be NULL
19469e69c935SLars-Peter Clausen  *
19479e69c935SLars-Peter Clausen  * Returns the pointer to the buffer that was passed into the function.
19489e69c935SLars-Peter Clausen  */
iio_buffer_get(struct iio_buffer * buffer)19499e69c935SLars-Peter Clausen struct iio_buffer *iio_buffer_get(struct iio_buffer *buffer)
19509e69c935SLars-Peter Clausen {
19519e69c935SLars-Peter Clausen 	if (buffer)
19529e69c935SLars-Peter Clausen 		kref_get(&buffer->ref);
19539e69c935SLars-Peter Clausen 
19549e69c935SLars-Peter Clausen 	return buffer;
19559e69c935SLars-Peter Clausen }
19569e69c935SLars-Peter Clausen EXPORT_SYMBOL_GPL(iio_buffer_get);
19579e69c935SLars-Peter Clausen 
19589e69c935SLars-Peter Clausen /**
19599e69c935SLars-Peter Clausen  * iio_buffer_put() - Release the reference to the buffer
19609e69c935SLars-Peter Clausen  * @buffer: The buffer to release the reference for, may be NULL
19619e69c935SLars-Peter Clausen  */
iio_buffer_put(struct iio_buffer * buffer)19629e69c935SLars-Peter Clausen void iio_buffer_put(struct iio_buffer *buffer)
19639e69c935SLars-Peter Clausen {
19649e69c935SLars-Peter Clausen 	if (buffer)
19659e69c935SLars-Peter Clausen 		kref_put(&buffer->ref, iio_buffer_release);
19669e69c935SLars-Peter Clausen }
19679e69c935SLars-Peter Clausen EXPORT_SYMBOL_GPL(iio_buffer_put);
19682b827ad5SJonathan Cameron 
19692b827ad5SJonathan Cameron /**
19702b827ad5SJonathan Cameron  * iio_device_attach_buffer - Attach a buffer to a IIO device
19712b827ad5SJonathan Cameron  * @indio_dev: The device the buffer should be attached to
19722b827ad5SJonathan Cameron  * @buffer: The buffer to attach to the device
19732b827ad5SJonathan Cameron  *
1974ee708e6bSAlexandru Ardelean  * Return 0 if successful, negative if error.
1975ee708e6bSAlexandru Ardelean  *
19762b827ad5SJonathan Cameron  * This function attaches a buffer to a IIO device. The buffer stays attached to
1977ee708e6bSAlexandru Ardelean  * the device until the device is freed. For legacy reasons, the first attached
1978ee708e6bSAlexandru Ardelean  * buffer will also be assigned to 'indio_dev->buffer'.
1979218bc53dSAlexandru Ardelean  * The array allocated here, will be free'd via the iio_device_detach_buffers()
1980218bc53dSAlexandru Ardelean  * call which is handled by the iio_device_free().
19812b827ad5SJonathan Cameron  */
iio_device_attach_buffer(struct iio_dev * indio_dev,struct iio_buffer * buffer)1982ee708e6bSAlexandru Ardelean int iio_device_attach_buffer(struct iio_dev *indio_dev,
19832b827ad5SJonathan Cameron 			     struct iio_buffer *buffer)
19842b827ad5SJonathan Cameron {
1985ee708e6bSAlexandru Ardelean 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
1986ee708e6bSAlexandru Ardelean 	struct iio_buffer **new, **old = iio_dev_opaque->attached_buffers;
1987ee708e6bSAlexandru Ardelean 	unsigned int cnt = iio_dev_opaque->attached_buffers_cnt;
1988ee708e6bSAlexandru Ardelean 
1989ee708e6bSAlexandru Ardelean 	cnt++;
1990ee708e6bSAlexandru Ardelean 
1991ee708e6bSAlexandru Ardelean 	new = krealloc(old, sizeof(*new) * cnt, GFP_KERNEL);
1992ee708e6bSAlexandru Ardelean 	if (!new)
1993ee708e6bSAlexandru Ardelean 		return -ENOMEM;
1994ee708e6bSAlexandru Ardelean 	iio_dev_opaque->attached_buffers = new;
1995ee708e6bSAlexandru Ardelean 
1996ee708e6bSAlexandru Ardelean 	buffer = iio_buffer_get(buffer);
1997ee708e6bSAlexandru Ardelean 
1998ee708e6bSAlexandru Ardelean 	/* first buffer is legacy; attach it to the IIO device directly */
1999ee708e6bSAlexandru Ardelean 	if (!indio_dev->buffer)
2000ee708e6bSAlexandru Ardelean 		indio_dev->buffer = buffer;
2001ee708e6bSAlexandru Ardelean 
2002ee708e6bSAlexandru Ardelean 	iio_dev_opaque->attached_buffers[cnt - 1] = buffer;
2003ee708e6bSAlexandru Ardelean 	iio_dev_opaque->attached_buffers_cnt = cnt;
2004ee708e6bSAlexandru Ardelean 
2005ee708e6bSAlexandru Ardelean 	return 0;
20062b827ad5SJonathan Cameron }
20072b827ad5SJonathan Cameron EXPORT_SYMBOL_GPL(iio_device_attach_buffer);
2008