1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2a980e046SJonathan Cameron /* The industrial I/O core 3a980e046SJonathan Cameron * 4a980e046SJonathan Cameron * Copyright (c) 2008 Jonathan Cameron 5a980e046SJonathan Cameron * 6a980e046SJonathan Cameron * Handling of buffer allocation / resizing. 7a980e046SJonathan Cameron * 8a980e046SJonathan Cameron * Things to look at here. 9a980e046SJonathan Cameron * - Better memory allocation techniques? 10a980e046SJonathan Cameron * - Alternative access techniques? 11a980e046SJonathan Cameron */ 12f73f7f4dSAlexandru Ardelean #include <linux/anon_inodes.h> 13a980e046SJonathan Cameron #include <linux/kernel.h> 14a980e046SJonathan Cameron #include <linux/export.h> 15a980e046SJonathan Cameron #include <linux/device.h> 16f73f7f4dSAlexandru Ardelean #include <linux/file.h> 17a980e046SJonathan Cameron #include <linux/fs.h> 18a980e046SJonathan Cameron #include <linux/cdev.h> 19a980e046SJonathan Cameron #include <linux/slab.h> 20a980e046SJonathan Cameron #include <linux/poll.h> 21174cd4b1SIngo Molnar #include <linux/sched/signal.h> 22a980e046SJonathan Cameron 23a980e046SJonathan Cameron #include <linux/iio/iio.h> 246a8c6b26SAlexandru Ardelean #include <linux/iio/iio-opaque.h> 25a980e046SJonathan Cameron #include "iio_core.h" 26f11d59d8SLars-Peter Clausen #include "iio_core_trigger.h" 27a980e046SJonathan Cameron #include <linux/iio/sysfs.h> 28a980e046SJonathan Cameron #include <linux/iio/buffer.h> 2933dd94cbSJonathan Cameron #include <linux/iio/buffer_impl.h> 30a980e046SJonathan Cameron 31a980e046SJonathan Cameron static const char * const iio_endian_prefix[] = { 32a980e046SJonathan Cameron [IIO_BE] = "be", 33a980e046SJonathan Cameron [IIO_LE] = "le", 34a980e046SJonathan Cameron }; 35a980e046SJonathan Cameron 36705ee2c9SLars-Peter Clausen static bool iio_buffer_is_active(struct iio_buffer *buf) 3784b36ce5SJonathan Cameron { 38705ee2c9SLars-Peter Clausen return !list_empty(&buf->buffer_list); 3984b36ce5SJonathan Cameron } 4084b36ce5SJonathan Cameron 4137d34556SJosselin Costanzi static size_t iio_buffer_data_available(struct iio_buffer *buf) 42647cc7b9SLars-Peter Clausen { 43647cc7b9SLars-Peter Clausen return buf->access->data_available(buf); 44647cc7b9SLars-Peter Clausen } 45647cc7b9SLars-Peter Clausen 46f4f4673bSOctavian Purdila static int iio_buffer_flush_hwfifo(struct iio_dev *indio_dev, 47f4f4673bSOctavian Purdila struct iio_buffer *buf, size_t required) 4837d34556SJosselin Costanzi { 49f4f4673bSOctavian Purdila if (!indio_dev->info->hwfifo_flush_to_buffer) 50f4f4673bSOctavian Purdila return -ENODEV; 51f4f4673bSOctavian Purdila 52f4f4673bSOctavian Purdila return indio_dev->info->hwfifo_flush_to_buffer(indio_dev, required); 53f4f4673bSOctavian Purdila } 54f4f4673bSOctavian Purdila 55f4f4673bSOctavian Purdila static bool iio_buffer_ready(struct iio_dev *indio_dev, struct iio_buffer *buf, 56f4f4673bSOctavian Purdila size_t to_wait, int to_flush) 57f4f4673bSOctavian Purdila { 58f4f4673bSOctavian Purdila size_t avail; 59f4f4673bSOctavian Purdila int flushed = 0; 60f4f4673bSOctavian Purdila 6137d34556SJosselin Costanzi /* wakeup if the device was unregistered */ 6237d34556SJosselin Costanzi if (!indio_dev->info) 6337d34556SJosselin Costanzi return true; 6437d34556SJosselin Costanzi 6537d34556SJosselin Costanzi /* drain the buffer if it was disabled */ 66f4f4673bSOctavian Purdila if (!iio_buffer_is_active(buf)) { 6737d34556SJosselin Costanzi to_wait = min_t(size_t, to_wait, 1); 68f4f4673bSOctavian Purdila to_flush = 0; 69f4f4673bSOctavian Purdila } 7037d34556SJosselin Costanzi 71f4f4673bSOctavian Purdila avail = iio_buffer_data_available(buf); 72f4f4673bSOctavian Purdila 73f4f4673bSOctavian Purdila if (avail >= to_wait) { 74f4f4673bSOctavian Purdila /* force a flush for non-blocking reads */ 75c6f67a1fSOctavian Purdila if (!to_wait && avail < to_flush) 76c6f67a1fSOctavian Purdila iio_buffer_flush_hwfifo(indio_dev, buf, 77c6f67a1fSOctavian Purdila to_flush - avail); 78f4f4673bSOctavian Purdila return true; 79f4f4673bSOctavian Purdila } 80f4f4673bSOctavian Purdila 81f4f4673bSOctavian Purdila if (to_flush) 82f4f4673bSOctavian Purdila flushed = iio_buffer_flush_hwfifo(indio_dev, buf, 83f4f4673bSOctavian Purdila to_wait - avail); 84f4f4673bSOctavian Purdila if (flushed <= 0) 85f4f4673bSOctavian Purdila return false; 86f4f4673bSOctavian Purdila 87f4f4673bSOctavian Purdila if (avail + flushed >= to_wait) 8837d34556SJosselin Costanzi return true; 8937d34556SJosselin Costanzi 9037d34556SJosselin Costanzi return false; 9137d34556SJosselin Costanzi } 9237d34556SJosselin Costanzi 93a980e046SJonathan Cameron /** 94f73f7f4dSAlexandru Ardelean * iio_buffer_read() - chrdev read for buffer access 950123635aSCristina Opriceana * @filp: File structure pointer for the char device 960123635aSCristina Opriceana * @buf: Destination buffer for iio buffer read 970123635aSCristina Opriceana * @n: First n bytes to read 980123635aSCristina Opriceana * @f_ps: Long offset provided by the user as a seek position 99a980e046SJonathan Cameron * 100a980e046SJonathan Cameron * This function relies on all buffer implementations having an 101a980e046SJonathan Cameron * iio_buffer as their first element. 1020123635aSCristina Opriceana * 1030123635aSCristina Opriceana * Return: negative values corresponding to error codes or ret != 0 1040123635aSCristina Opriceana * for ending the reading activity 105a980e046SJonathan Cameron **/ 106f73f7f4dSAlexandru Ardelean static ssize_t iio_buffer_read(struct file *filp, char __user *buf, 107a980e046SJonathan Cameron size_t n, loff_t *f_ps) 108a980e046SJonathan Cameron { 109be24dcb1SAlexandru Ardelean struct iio_dev_buffer_pair *ib = filp->private_data; 110be24dcb1SAlexandru Ardelean struct iio_buffer *rb = ib->buffer; 111be24dcb1SAlexandru Ardelean struct iio_dev *indio_dev = ib->indio_dev; 112fcf68f3cSBrian Norris DEFINE_WAIT_FUNC(wait, woken_wake_function); 11337d34556SJosselin Costanzi size_t datum_size; 114c6f67a1fSOctavian Purdila size_t to_wait; 1155dba4b14SColin Ian King int ret = 0; 116a980e046SJonathan Cameron 117f18e7a06SLars-Peter Clausen if (!indio_dev->info) 118f18e7a06SLars-Peter Clausen return -ENODEV; 119f18e7a06SLars-Peter Clausen 120f6d4033dSLars-Peter Clausen if (!rb || !rb->access->read) 121a980e046SJonathan Cameron return -EINVAL; 122ee551a10SLars-Peter Clausen 1239eeee3b0SMihail Chindris if (rb->direction != IIO_BUFFER_DIRECTION_IN) 1249eeee3b0SMihail Chindris return -EPERM; 1259eeee3b0SMihail Chindris 12637d34556SJosselin Costanzi datum_size = rb->bytes_per_datum; 127ee551a10SLars-Peter Clausen 12837d34556SJosselin Costanzi /* 12937d34556SJosselin Costanzi * If datum_size is 0 there will never be anything to read from the 13037d34556SJosselin Costanzi * buffer, so signal end of file now. 13137d34556SJosselin Costanzi */ 13237d34556SJosselin Costanzi if (!datum_size) 13337d34556SJosselin Costanzi return 0; 13437d34556SJosselin Costanzi 135c6f67a1fSOctavian Purdila if (filp->f_flags & O_NONBLOCK) 136c6f67a1fSOctavian Purdila to_wait = 0; 137c6f67a1fSOctavian Purdila else 138c6f67a1fSOctavian Purdila to_wait = min_t(size_t, n / datum_size, rb->watermark); 13937d34556SJosselin Costanzi 140fcf68f3cSBrian Norris add_wait_queue(&rb->pollq, &wait); 14137d34556SJosselin Costanzi do { 142fcf68f3cSBrian Norris if (!indio_dev->info) { 143fcf68f3cSBrian Norris ret = -ENODEV; 144fcf68f3cSBrian Norris break; 145fcf68f3cSBrian Norris } 14637d34556SJosselin Costanzi 147fcf68f3cSBrian Norris if (!iio_buffer_ready(indio_dev, rb, to_wait, n / datum_size)) { 148fcf68f3cSBrian Norris if (signal_pending(current)) { 149fcf68f3cSBrian Norris ret = -ERESTARTSYS; 150fcf68f3cSBrian Norris break; 151fcf68f3cSBrian Norris } 152fcf68f3cSBrian Norris 153fcf68f3cSBrian Norris wait_woken(&wait, TASK_INTERRUPTIBLE, 154fcf68f3cSBrian Norris MAX_SCHEDULE_TIMEOUT); 155fcf68f3cSBrian Norris continue; 156fcf68f3cSBrian Norris } 157ee551a10SLars-Peter Clausen 158f6d4033dSLars-Peter Clausen ret = rb->access->read(rb, n, buf); 159ee551a10SLars-Peter Clausen if (ret == 0 && (filp->f_flags & O_NONBLOCK)) 160ee551a10SLars-Peter Clausen ret = -EAGAIN; 161ee551a10SLars-Peter Clausen } while (ret == 0); 162fcf68f3cSBrian Norris remove_wait_queue(&rb->pollq, &wait); 163ee551a10SLars-Peter Clausen 164ee551a10SLars-Peter Clausen return ret; 165a980e046SJonathan Cameron } 166a980e046SJonathan Cameron 1679eeee3b0SMihail Chindris static size_t iio_buffer_space_available(struct iio_buffer *buf) 1689eeee3b0SMihail Chindris { 1699eeee3b0SMihail Chindris if (buf->access->space_available) 1709eeee3b0SMihail Chindris return buf->access->space_available(buf); 1719eeee3b0SMihail Chindris 1729eeee3b0SMihail Chindris return SIZE_MAX; 1739eeee3b0SMihail Chindris } 1749eeee3b0SMihail Chindris 1759eeee3b0SMihail Chindris static ssize_t iio_buffer_write(struct file *filp, const char __user *buf, 1769eeee3b0SMihail Chindris size_t n, loff_t *f_ps) 1779eeee3b0SMihail Chindris { 1789eeee3b0SMihail Chindris struct iio_dev_buffer_pair *ib = filp->private_data; 1799eeee3b0SMihail Chindris struct iio_buffer *rb = ib->buffer; 1809eeee3b0SMihail Chindris struct iio_dev *indio_dev = ib->indio_dev; 1819eeee3b0SMihail Chindris DEFINE_WAIT_FUNC(wait, woken_wake_function); 182eeb82b54SColin Ian King int ret = 0; 1839eeee3b0SMihail Chindris size_t written; 1849eeee3b0SMihail Chindris 1859eeee3b0SMihail Chindris if (!indio_dev->info) 1869eeee3b0SMihail Chindris return -ENODEV; 1879eeee3b0SMihail Chindris 1889eeee3b0SMihail Chindris if (!rb || !rb->access->write) 1899eeee3b0SMihail Chindris return -EINVAL; 1909eeee3b0SMihail Chindris 1919eeee3b0SMihail Chindris if (rb->direction != IIO_BUFFER_DIRECTION_OUT) 1929eeee3b0SMihail Chindris return -EPERM; 1939eeee3b0SMihail Chindris 1949eeee3b0SMihail Chindris written = 0; 1959eeee3b0SMihail Chindris add_wait_queue(&rb->pollq, &wait); 1969eeee3b0SMihail Chindris do { 1979eeee3b0SMihail Chindris if (indio_dev->info == NULL) 1989eeee3b0SMihail Chindris return -ENODEV; 1999eeee3b0SMihail Chindris 2009eeee3b0SMihail Chindris if (!iio_buffer_space_available(rb)) { 2019eeee3b0SMihail Chindris if (signal_pending(current)) { 2029eeee3b0SMihail Chindris ret = -ERESTARTSYS; 2039eeee3b0SMihail Chindris break; 2049eeee3b0SMihail Chindris } 2059eeee3b0SMihail Chindris 2069eeee3b0SMihail Chindris wait_woken(&wait, TASK_INTERRUPTIBLE, 2079eeee3b0SMihail Chindris MAX_SCHEDULE_TIMEOUT); 2089eeee3b0SMihail Chindris continue; 2099eeee3b0SMihail Chindris } 2109eeee3b0SMihail Chindris 2119eeee3b0SMihail Chindris ret = rb->access->write(rb, n - written, buf + written); 2129eeee3b0SMihail Chindris if (ret == 0 && (filp->f_flags & O_NONBLOCK)) 2139eeee3b0SMihail Chindris ret = -EAGAIN; 2149eeee3b0SMihail Chindris 2159eeee3b0SMihail Chindris if (ret > 0) { 2169eeee3b0SMihail Chindris written += ret; 2179eeee3b0SMihail Chindris if (written != n && !(filp->f_flags & O_NONBLOCK)) 2189eeee3b0SMihail Chindris continue; 2199eeee3b0SMihail Chindris } 2209eeee3b0SMihail Chindris } while (ret == 0); 2219eeee3b0SMihail Chindris remove_wait_queue(&rb->pollq, &wait); 2229eeee3b0SMihail Chindris 2239eeee3b0SMihail Chindris return ret < 0 ? ret : n; 2249eeee3b0SMihail Chindris } 2259eeee3b0SMihail Chindris 226a980e046SJonathan Cameron /** 227a980e046SJonathan Cameron * iio_buffer_poll() - poll the buffer to find out if it has data 2280123635aSCristina Opriceana * @filp: File structure pointer for device access 2290123635aSCristina Opriceana * @wait: Poll table structure pointer for which the driver adds 2300123635aSCristina Opriceana * a wait queue 2310123635aSCristina Opriceana * 232a9a08845SLinus Torvalds * Return: (EPOLLIN | EPOLLRDNORM) if data is available for reading 2330123635aSCristina Opriceana * or 0 for other cases 234a980e046SJonathan Cameron */ 235f73f7f4dSAlexandru Ardelean static __poll_t iio_buffer_poll(struct file *filp, 236a980e046SJonathan Cameron struct poll_table_struct *wait) 237a980e046SJonathan Cameron { 238be24dcb1SAlexandru Ardelean struct iio_dev_buffer_pair *ib = filp->private_data; 239be24dcb1SAlexandru Ardelean struct iio_buffer *rb = ib->buffer; 240be24dcb1SAlexandru Ardelean struct iio_dev *indio_dev = ib->indio_dev; 241a980e046SJonathan Cameron 2424cd140bdSStefan Windfeldt-Prytz if (!indio_dev->info || rb == NULL) 2431bdc0293SCristina Opriceana return 0; 244f18e7a06SLars-Peter Clausen 245a980e046SJonathan Cameron poll_wait(filp, &rb->pollq, wait); 2469eeee3b0SMihail Chindris 2479eeee3b0SMihail Chindris switch (rb->direction) { 2489eeee3b0SMihail Chindris case IIO_BUFFER_DIRECTION_IN: 249f4f4673bSOctavian Purdila if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0)) 250a9a08845SLinus Torvalds return EPOLLIN | EPOLLRDNORM; 2519eeee3b0SMihail Chindris break; 2529eeee3b0SMihail Chindris case IIO_BUFFER_DIRECTION_OUT: 2539eeee3b0SMihail Chindris if (iio_buffer_space_available(rb)) 2549eeee3b0SMihail Chindris return EPOLLOUT | EPOLLWRNORM; 2559eeee3b0SMihail Chindris break; 2569eeee3b0SMihail Chindris } 2579eeee3b0SMihail Chindris 258a980e046SJonathan Cameron return 0; 259a980e046SJonathan Cameron } 260a980e046SJonathan Cameron 261f73f7f4dSAlexandru Ardelean ssize_t iio_buffer_read_wrapper(struct file *filp, char __user *buf, 262f73f7f4dSAlexandru Ardelean size_t n, loff_t *f_ps) 263f73f7f4dSAlexandru Ardelean { 264f73f7f4dSAlexandru Ardelean struct iio_dev_buffer_pair *ib = filp->private_data; 265f73f7f4dSAlexandru Ardelean struct iio_buffer *rb = ib->buffer; 266f73f7f4dSAlexandru Ardelean 267f73f7f4dSAlexandru Ardelean /* check if buffer was opened through new API */ 268f73f7f4dSAlexandru Ardelean if (test_bit(IIO_BUSY_BIT_POS, &rb->flags)) 269f73f7f4dSAlexandru Ardelean return -EBUSY; 270f73f7f4dSAlexandru Ardelean 271f73f7f4dSAlexandru Ardelean return iio_buffer_read(filp, buf, n, f_ps); 272f73f7f4dSAlexandru Ardelean } 273f73f7f4dSAlexandru Ardelean 2749eeee3b0SMihail Chindris ssize_t iio_buffer_write_wrapper(struct file *filp, const char __user *buf, 2759eeee3b0SMihail Chindris size_t n, loff_t *f_ps) 2769eeee3b0SMihail Chindris { 2779eeee3b0SMihail Chindris struct iio_dev_buffer_pair *ib = filp->private_data; 2789eeee3b0SMihail Chindris struct iio_buffer *rb = ib->buffer; 2799eeee3b0SMihail Chindris 2809eeee3b0SMihail Chindris /* check if buffer was opened through new API */ 2819eeee3b0SMihail Chindris if (test_bit(IIO_BUSY_BIT_POS, &rb->flags)) 2829eeee3b0SMihail Chindris return -EBUSY; 2839eeee3b0SMihail Chindris 2849eeee3b0SMihail Chindris return iio_buffer_write(filp, buf, n, f_ps); 2859eeee3b0SMihail Chindris } 2869eeee3b0SMihail Chindris 287f73f7f4dSAlexandru Ardelean __poll_t iio_buffer_poll_wrapper(struct file *filp, 288f73f7f4dSAlexandru Ardelean struct poll_table_struct *wait) 289f73f7f4dSAlexandru Ardelean { 290f73f7f4dSAlexandru Ardelean struct iio_dev_buffer_pair *ib = filp->private_data; 291f73f7f4dSAlexandru Ardelean struct iio_buffer *rb = ib->buffer; 292f73f7f4dSAlexandru Ardelean 293f73f7f4dSAlexandru Ardelean /* check if buffer was opened through new API */ 294f73f7f4dSAlexandru Ardelean if (test_bit(IIO_BUSY_BIT_POS, &rb->flags)) 295f73f7f4dSAlexandru Ardelean return 0; 296f73f7f4dSAlexandru Ardelean 297f73f7f4dSAlexandru Ardelean return iio_buffer_poll(filp, wait); 298f73f7f4dSAlexandru Ardelean } 299f73f7f4dSAlexandru Ardelean 300d2f0a48fSLars-Peter Clausen /** 301d2f0a48fSLars-Peter Clausen * iio_buffer_wakeup_poll - Wakes up the buffer waitqueue 302d2f0a48fSLars-Peter Clausen * @indio_dev: The IIO device 303d2f0a48fSLars-Peter Clausen * 304d2f0a48fSLars-Peter Clausen * Wakes up the event waitqueue used for poll(). Should usually 305d2f0a48fSLars-Peter Clausen * be called when the device is unregistered. 306d2f0a48fSLars-Peter Clausen */ 307d2f0a48fSLars-Peter Clausen void iio_buffer_wakeup_poll(struct iio_dev *indio_dev) 308d2f0a48fSLars-Peter Clausen { 309ee708e6bSAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 310ee708e6bSAlexandru Ardelean struct iio_buffer *buffer; 311ee708e6bSAlexandru Ardelean unsigned int i; 312ff3f7e04SAlexandru Ardelean 313ee708e6bSAlexandru Ardelean for (i = 0; i < iio_dev_opaque->attached_buffers_cnt; i++) { 314ee708e6bSAlexandru Ardelean buffer = iio_dev_opaque->attached_buffers[i]; 315ff3f7e04SAlexandru Ardelean wake_up(&buffer->pollq); 316d2f0a48fSLars-Peter Clausen } 317ee708e6bSAlexandru Ardelean } 318d2f0a48fSLars-Peter Clausen 3199eeee3b0SMihail Chindris int iio_pop_from_buffer(struct iio_buffer *buffer, void *data) 3209eeee3b0SMihail Chindris { 3219eeee3b0SMihail Chindris if (!buffer || !buffer->access || !buffer->access->remove_from) 3229eeee3b0SMihail Chindris return -EINVAL; 3239eeee3b0SMihail Chindris 3249eeee3b0SMihail Chindris return buffer->access->remove_from(buffer, data); 3259eeee3b0SMihail Chindris } 3269eeee3b0SMihail Chindris EXPORT_SYMBOL_GPL(iio_pop_from_buffer); 3279eeee3b0SMihail Chindris 328a980e046SJonathan Cameron void iio_buffer_init(struct iio_buffer *buffer) 329a980e046SJonathan Cameron { 330a980e046SJonathan Cameron INIT_LIST_HEAD(&buffer->demux_list); 331705ee2c9SLars-Peter Clausen INIT_LIST_HEAD(&buffer->buffer_list); 332a980e046SJonathan Cameron init_waitqueue_head(&buffer->pollq); 3339e69c935SLars-Peter Clausen kref_init(&buffer->ref); 3344a605357SLars-Peter Clausen if (!buffer->watermark) 33537d34556SJosselin Costanzi buffer->watermark = 1; 336a980e046SJonathan Cameron } 337a980e046SJonathan Cameron EXPORT_SYMBOL(iio_buffer_init); 338a980e046SJonathan Cameron 339218bc53dSAlexandru Ardelean void iio_device_detach_buffers(struct iio_dev *indio_dev) 340ee708e6bSAlexandru Ardelean { 341ee708e6bSAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 342ee708e6bSAlexandru Ardelean struct iio_buffer *buffer; 343ee708e6bSAlexandru Ardelean unsigned int i; 344ee708e6bSAlexandru Ardelean 345ee708e6bSAlexandru Ardelean for (i = 0; i < iio_dev_opaque->attached_buffers_cnt; i++) { 346ee708e6bSAlexandru Ardelean buffer = iio_dev_opaque->attached_buffers[i]; 347ee708e6bSAlexandru Ardelean iio_buffer_put(buffer); 348ee708e6bSAlexandru Ardelean } 349218bc53dSAlexandru Ardelean 350218bc53dSAlexandru Ardelean kfree(iio_dev_opaque->attached_buffers); 351ee708e6bSAlexandru Ardelean } 352ee708e6bSAlexandru Ardelean 353a980e046SJonathan Cameron static ssize_t iio_show_scan_index(struct device *dev, 354a980e046SJonathan Cameron struct device_attribute *attr, 355a980e046SJonathan Cameron char *buf) 356a980e046SJonathan Cameron { 35783ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%u\n", to_iio_dev_attr(attr)->c->scan_index); 358a980e046SJonathan Cameron } 359a980e046SJonathan Cameron 360a980e046SJonathan Cameron static ssize_t iio_show_fixed_type(struct device *dev, 361a980e046SJonathan Cameron struct device_attribute *attr, 362a980e046SJonathan Cameron char *buf) 363a980e046SJonathan Cameron { 364a980e046SJonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 365a980e046SJonathan Cameron u8 type = this_attr->c->scan_type.endianness; 366a980e046SJonathan Cameron 367a980e046SJonathan Cameron if (type == IIO_CPU) { 368a980e046SJonathan Cameron #ifdef __LITTLE_ENDIAN 369a980e046SJonathan Cameron type = IIO_LE; 370a980e046SJonathan Cameron #else 371a980e046SJonathan Cameron type = IIO_BE; 372a980e046SJonathan Cameron #endif 373a980e046SJonathan Cameron } 3740ee8546aSSrinivas Pandruvada if (this_attr->c->scan_type.repeat > 1) 37583ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%s:%c%d/%dX%d>>%u\n", 3760ee8546aSSrinivas Pandruvada iio_endian_prefix[type], 3770ee8546aSSrinivas Pandruvada this_attr->c->scan_type.sign, 3780ee8546aSSrinivas Pandruvada this_attr->c->scan_type.realbits, 3790ee8546aSSrinivas Pandruvada this_attr->c->scan_type.storagebits, 3800ee8546aSSrinivas Pandruvada this_attr->c->scan_type.repeat, 3810ee8546aSSrinivas Pandruvada this_attr->c->scan_type.shift); 3820ee8546aSSrinivas Pandruvada else 38383ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%s:%c%d/%d>>%u\n", 384a980e046SJonathan Cameron iio_endian_prefix[type], 385a980e046SJonathan Cameron this_attr->c->scan_type.sign, 386a980e046SJonathan Cameron this_attr->c->scan_type.realbits, 387a980e046SJonathan Cameron this_attr->c->scan_type.storagebits, 388a980e046SJonathan Cameron this_attr->c->scan_type.shift); 389a980e046SJonathan Cameron } 390a980e046SJonathan Cameron 391a980e046SJonathan Cameron static ssize_t iio_scan_el_show(struct device *dev, 392a980e046SJonathan Cameron struct device_attribute *attr, 393a980e046SJonathan Cameron char *buf) 394a980e046SJonathan Cameron { 395a980e046SJonathan Cameron int ret; 39615097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 397a980e046SJonathan Cameron 3982076a20fSAlec Berg /* Ensure ret is 0 or 1. */ 3992076a20fSAlec Berg ret = !!test_bit(to_iio_dev_attr(attr)->address, 400ff3f7e04SAlexandru Ardelean buffer->scan_mask); 401a980e046SJonathan Cameron 40283ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%d\n", ret); 403a980e046SJonathan Cameron } 404a980e046SJonathan Cameron 405217a5cf0SLars-Peter Clausen /* Note NULL used as error indicator as it doesn't make sense. */ 406217a5cf0SLars-Peter Clausen static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks, 407217a5cf0SLars-Peter Clausen unsigned int masklength, 4081e1ec286SLars-Peter Clausen const unsigned long *mask, 4091e1ec286SLars-Peter Clausen bool strict) 410217a5cf0SLars-Peter Clausen { 411217a5cf0SLars-Peter Clausen if (bitmap_empty(mask, masklength)) 412217a5cf0SLars-Peter Clausen return NULL; 413217a5cf0SLars-Peter Clausen while (*av_masks) { 4141e1ec286SLars-Peter Clausen if (strict) { 4151e1ec286SLars-Peter Clausen if (bitmap_equal(mask, av_masks, masklength)) 4161e1ec286SLars-Peter Clausen return av_masks; 4171e1ec286SLars-Peter Clausen } else { 418217a5cf0SLars-Peter Clausen if (bitmap_subset(mask, av_masks, masklength)) 419217a5cf0SLars-Peter Clausen return av_masks; 4201e1ec286SLars-Peter Clausen } 421217a5cf0SLars-Peter Clausen av_masks += BITS_TO_LONGS(masklength); 422217a5cf0SLars-Peter Clausen } 423217a5cf0SLars-Peter Clausen return NULL; 424217a5cf0SLars-Peter Clausen } 425217a5cf0SLars-Peter Clausen 426217a5cf0SLars-Peter Clausen static bool iio_validate_scan_mask(struct iio_dev *indio_dev, 427217a5cf0SLars-Peter Clausen const unsigned long *mask) 428217a5cf0SLars-Peter Clausen { 429217a5cf0SLars-Peter Clausen if (!indio_dev->setup_ops->validate_scan_mask) 430217a5cf0SLars-Peter Clausen return true; 431217a5cf0SLars-Peter Clausen 432217a5cf0SLars-Peter Clausen return indio_dev->setup_ops->validate_scan_mask(indio_dev, mask); 433217a5cf0SLars-Peter Clausen } 434217a5cf0SLars-Peter Clausen 435217a5cf0SLars-Peter Clausen /** 436217a5cf0SLars-Peter Clausen * iio_scan_mask_set() - set particular bit in the scan mask 437217a5cf0SLars-Peter Clausen * @indio_dev: the iio device 438217a5cf0SLars-Peter Clausen * @buffer: the buffer whose scan mask we are interested in 439217a5cf0SLars-Peter Clausen * @bit: the bit to be set. 440217a5cf0SLars-Peter Clausen * 441217a5cf0SLars-Peter Clausen * Note that at this point we have no way of knowing what other 442217a5cf0SLars-Peter Clausen * buffers might request, hence this code only verifies that the 443217a5cf0SLars-Peter Clausen * individual buffers request is plausible. 444217a5cf0SLars-Peter Clausen */ 445217a5cf0SLars-Peter Clausen static int iio_scan_mask_set(struct iio_dev *indio_dev, 446217a5cf0SLars-Peter Clausen struct iio_buffer *buffer, int bit) 447217a5cf0SLars-Peter Clausen { 448217a5cf0SLars-Peter Clausen const unsigned long *mask; 449217a5cf0SLars-Peter Clausen unsigned long *trialmask; 450217a5cf0SLars-Peter Clausen 451d21fed06SChristophe JAILLET if (!indio_dev->masklength) { 452d21fed06SChristophe JAILLET WARN(1, "Trying to set scanmask prior to registering buffer\n"); 453d21fed06SChristophe JAILLET return -EINVAL; 454d21fed06SChristophe JAILLET } 455d21fed06SChristophe JAILLET 45645851650SChristophe JAILLET trialmask = bitmap_alloc(indio_dev->masklength, GFP_KERNEL); 45745851650SChristophe JAILLET if (!trialmask) 458217a5cf0SLars-Peter Clausen return -ENOMEM; 459217a5cf0SLars-Peter Clausen bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength); 460217a5cf0SLars-Peter Clausen set_bit(bit, trialmask); 461217a5cf0SLars-Peter Clausen 462217a5cf0SLars-Peter Clausen if (!iio_validate_scan_mask(indio_dev, trialmask)) 463217a5cf0SLars-Peter Clausen goto err_invalid_mask; 464217a5cf0SLars-Peter Clausen 465217a5cf0SLars-Peter Clausen if (indio_dev->available_scan_masks) { 466217a5cf0SLars-Peter Clausen mask = iio_scan_mask_match(indio_dev->available_scan_masks, 467217a5cf0SLars-Peter Clausen indio_dev->masklength, 4681e1ec286SLars-Peter Clausen trialmask, false); 469217a5cf0SLars-Peter Clausen if (!mask) 470217a5cf0SLars-Peter Clausen goto err_invalid_mask; 471217a5cf0SLars-Peter Clausen } 472217a5cf0SLars-Peter Clausen bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength); 473217a5cf0SLars-Peter Clausen 4743862828aSAndy Shevchenko bitmap_free(trialmask); 475217a5cf0SLars-Peter Clausen 476217a5cf0SLars-Peter Clausen return 0; 477217a5cf0SLars-Peter Clausen 478217a5cf0SLars-Peter Clausen err_invalid_mask: 4793862828aSAndy Shevchenko bitmap_free(trialmask); 480217a5cf0SLars-Peter Clausen return -EINVAL; 481217a5cf0SLars-Peter Clausen } 482217a5cf0SLars-Peter Clausen 483a980e046SJonathan Cameron static int iio_scan_mask_clear(struct iio_buffer *buffer, int bit) 484a980e046SJonathan Cameron { 485a980e046SJonathan Cameron clear_bit(bit, buffer->scan_mask); 486a980e046SJonathan Cameron return 0; 487a980e046SJonathan Cameron } 488a980e046SJonathan Cameron 489c2bf8d5fSJonathan Cameron static int iio_scan_mask_query(struct iio_dev *indio_dev, 490c2bf8d5fSJonathan Cameron struct iio_buffer *buffer, int bit) 491c2bf8d5fSJonathan Cameron { 492c2bf8d5fSJonathan Cameron if (bit > indio_dev->masklength) 493c2bf8d5fSJonathan Cameron return -EINVAL; 494c2bf8d5fSJonathan Cameron 495c2bf8d5fSJonathan Cameron if (!buffer->scan_mask) 496c2bf8d5fSJonathan Cameron return 0; 497c2bf8d5fSJonathan Cameron 498c2bf8d5fSJonathan Cameron /* Ensure return value is 0 or 1. */ 499c2bf8d5fSJonathan Cameron return !!test_bit(bit, buffer->scan_mask); 500c2bf8d5fSJonathan Cameron }; 501c2bf8d5fSJonathan Cameron 502a980e046SJonathan Cameron static ssize_t iio_scan_el_store(struct device *dev, 503a980e046SJonathan Cameron struct device_attribute *attr, 504a980e046SJonathan Cameron const char *buf, 505a980e046SJonathan Cameron size_t len) 506a980e046SJonathan Cameron { 507a980e046SJonathan Cameron int ret; 508a980e046SJonathan Cameron bool state; 509e53f5ac5SLars-Peter Clausen struct iio_dev *indio_dev = dev_to_iio_dev(dev); 510a980e046SJonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 51115097c7aSAlexandru Ardelean struct iio_buffer *buffer = this_attr->buffer; 512a980e046SJonathan Cameron 51374f582ecSLars-Peter Clausen ret = kstrtobool(buf, &state); 514a980e046SJonathan Cameron if (ret < 0) 515a980e046SJonathan Cameron return ret; 516a980e046SJonathan Cameron mutex_lock(&indio_dev->mlock); 517ff3f7e04SAlexandru Ardelean if (iio_buffer_is_active(buffer)) { 518a980e046SJonathan Cameron ret = -EBUSY; 519a980e046SJonathan Cameron goto error_ret; 520a980e046SJonathan Cameron } 521a980e046SJonathan Cameron ret = iio_scan_mask_query(indio_dev, buffer, this_attr->address); 522a980e046SJonathan Cameron if (ret < 0) 523a980e046SJonathan Cameron goto error_ret; 524a980e046SJonathan Cameron if (!state && ret) { 525a980e046SJonathan Cameron ret = iio_scan_mask_clear(buffer, this_attr->address); 526a980e046SJonathan Cameron if (ret) 527a980e046SJonathan Cameron goto error_ret; 528a980e046SJonathan Cameron } else if (state && !ret) { 529a980e046SJonathan Cameron ret = iio_scan_mask_set(indio_dev, buffer, this_attr->address); 530a980e046SJonathan Cameron if (ret) 531a980e046SJonathan Cameron goto error_ret; 532a980e046SJonathan Cameron } 533a980e046SJonathan Cameron 534a980e046SJonathan Cameron error_ret: 535a980e046SJonathan Cameron mutex_unlock(&indio_dev->mlock); 536a980e046SJonathan Cameron 537a980e046SJonathan Cameron return ret < 0 ? ret : len; 538a980e046SJonathan Cameron 539a980e046SJonathan Cameron } 540a980e046SJonathan Cameron 541a980e046SJonathan Cameron static ssize_t iio_scan_el_ts_show(struct device *dev, 542a980e046SJonathan Cameron struct device_attribute *attr, 543a980e046SJonathan Cameron char *buf) 544a980e046SJonathan Cameron { 54515097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 546ff3f7e04SAlexandru Ardelean 54783ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%d\n", buffer->scan_timestamp); 548a980e046SJonathan Cameron } 549a980e046SJonathan Cameron 550a980e046SJonathan Cameron static ssize_t iio_scan_el_ts_store(struct device *dev, 551a980e046SJonathan Cameron struct device_attribute *attr, 552a980e046SJonathan Cameron const char *buf, 553a980e046SJonathan Cameron size_t len) 554a980e046SJonathan Cameron { 555a980e046SJonathan Cameron int ret; 556e53f5ac5SLars-Peter Clausen struct iio_dev *indio_dev = dev_to_iio_dev(dev); 55715097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 558a980e046SJonathan Cameron bool state; 559a980e046SJonathan Cameron 56074f582ecSLars-Peter Clausen ret = kstrtobool(buf, &state); 561a980e046SJonathan Cameron if (ret < 0) 562a980e046SJonathan Cameron return ret; 563a980e046SJonathan Cameron 564a980e046SJonathan Cameron mutex_lock(&indio_dev->mlock); 565ff3f7e04SAlexandru Ardelean if (iio_buffer_is_active(buffer)) { 566a980e046SJonathan Cameron ret = -EBUSY; 567a980e046SJonathan Cameron goto error_ret; 568a980e046SJonathan Cameron } 569ff3f7e04SAlexandru Ardelean buffer->scan_timestamp = state; 570a980e046SJonathan Cameron error_ret: 571a980e046SJonathan Cameron mutex_unlock(&indio_dev->mlock); 572a980e046SJonathan Cameron 573a980e046SJonathan Cameron return ret ? ret : len; 574a980e046SJonathan Cameron } 575a980e046SJonathan Cameron 576a980e046SJonathan Cameron static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev, 577ff3f7e04SAlexandru Ardelean struct iio_buffer *buffer, 578a980e046SJonathan Cameron const struct iio_chan_spec *chan) 579a980e046SJonathan Cameron { 580a980e046SJonathan Cameron int ret, attrcount = 0; 581a980e046SJonathan Cameron 582a980e046SJonathan Cameron ret = __iio_add_chan_devattr("index", 583a980e046SJonathan Cameron chan, 584a980e046SJonathan Cameron &iio_show_scan_index, 585a980e046SJonathan Cameron NULL, 586a980e046SJonathan Cameron 0, 5873704432fSJonathan Cameron IIO_SEPARATE, 588a980e046SJonathan Cameron &indio_dev->dev, 5893e3d11b2SAlexandru Ardelean buffer, 59015097c7aSAlexandru Ardelean &buffer->buffer_attr_list); 591a980e046SJonathan Cameron if (ret) 59292825ff9SHartmut Knaack return ret; 593a980e046SJonathan Cameron attrcount++; 594a980e046SJonathan Cameron ret = __iio_add_chan_devattr("type", 595a980e046SJonathan Cameron chan, 596a980e046SJonathan Cameron &iio_show_fixed_type, 597a980e046SJonathan Cameron NULL, 598a980e046SJonathan Cameron 0, 599a980e046SJonathan Cameron 0, 600a980e046SJonathan Cameron &indio_dev->dev, 6013e3d11b2SAlexandru Ardelean buffer, 60215097c7aSAlexandru Ardelean &buffer->buffer_attr_list); 603a980e046SJonathan Cameron if (ret) 60492825ff9SHartmut Knaack return ret; 605a980e046SJonathan Cameron attrcount++; 606a980e046SJonathan Cameron if (chan->type != IIO_TIMESTAMP) 607a980e046SJonathan Cameron ret = __iio_add_chan_devattr("en", 608a980e046SJonathan Cameron chan, 609a980e046SJonathan Cameron &iio_scan_el_show, 610a980e046SJonathan Cameron &iio_scan_el_store, 611a980e046SJonathan Cameron chan->scan_index, 612a980e046SJonathan Cameron 0, 613a980e046SJonathan Cameron &indio_dev->dev, 6143e3d11b2SAlexandru Ardelean buffer, 61515097c7aSAlexandru Ardelean &buffer->buffer_attr_list); 616a980e046SJonathan Cameron else 617a980e046SJonathan Cameron ret = __iio_add_chan_devattr("en", 618a980e046SJonathan Cameron chan, 619a980e046SJonathan Cameron &iio_scan_el_ts_show, 620a980e046SJonathan Cameron &iio_scan_el_ts_store, 621a980e046SJonathan Cameron chan->scan_index, 622a980e046SJonathan Cameron 0, 623a980e046SJonathan Cameron &indio_dev->dev, 6243e3d11b2SAlexandru Ardelean buffer, 62515097c7aSAlexandru Ardelean &buffer->buffer_attr_list); 6269572588cSPeter Meerwald if (ret) 62792825ff9SHartmut Knaack return ret; 628a980e046SJonathan Cameron attrcount++; 629a980e046SJonathan Cameron ret = attrcount; 630a980e046SJonathan Cameron return ret; 631a980e046SJonathan Cameron } 632a980e046SJonathan Cameron 6339cf0b618SJoe Simmons-Talbott static ssize_t length_show(struct device *dev, struct device_attribute *attr, 634a980e046SJonathan Cameron char *buf) 635a980e046SJonathan Cameron { 63615097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 637a980e046SJonathan Cameron 63883ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%d\n", buffer->length); 639a980e046SJonathan Cameron } 640a980e046SJonathan Cameron 6419cf0b618SJoe Simmons-Talbott static ssize_t length_store(struct device *dev, struct device_attribute *attr, 64208e7e0adSLars-Peter Clausen const char *buf, size_t len) 643a980e046SJonathan Cameron { 644e53f5ac5SLars-Peter Clausen struct iio_dev *indio_dev = dev_to_iio_dev(dev); 64515097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 646948ad205SLars-Peter Clausen unsigned int val; 647948ad205SLars-Peter Clausen int ret; 648a980e046SJonathan Cameron 649948ad205SLars-Peter Clausen ret = kstrtouint(buf, 10, &val); 650a980e046SJonathan Cameron if (ret) 651a980e046SJonathan Cameron return ret; 652a980e046SJonathan Cameron 65337495660SLars-Peter Clausen if (val == buffer->length) 654a980e046SJonathan Cameron return len; 655a980e046SJonathan Cameron 656a980e046SJonathan Cameron mutex_lock(&indio_dev->mlock); 657ff3f7e04SAlexandru Ardelean if (iio_buffer_is_active(buffer)) { 658a980e046SJonathan Cameron ret = -EBUSY; 659a980e046SJonathan Cameron } else { 660a980e046SJonathan Cameron buffer->access->set_length(buffer, val); 661a980e046SJonathan Cameron ret = 0; 662a980e046SJonathan Cameron } 66337d34556SJosselin Costanzi if (ret) 66437d34556SJosselin Costanzi goto out; 66537d34556SJosselin Costanzi if (buffer->length && buffer->length < buffer->watermark) 66637d34556SJosselin Costanzi buffer->watermark = buffer->length; 66737d34556SJosselin Costanzi out: 668a980e046SJonathan Cameron mutex_unlock(&indio_dev->mlock); 669a980e046SJonathan Cameron 670a980e046SJonathan Cameron return ret ? ret : len; 671a980e046SJonathan Cameron } 672a980e046SJonathan Cameron 6739cf0b618SJoe Simmons-Talbott static ssize_t enable_show(struct device *dev, struct device_attribute *attr, 674a980e046SJonathan Cameron char *buf) 675a980e046SJonathan Cameron { 67615097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 677ff3f7e04SAlexandru Ardelean 67883ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%d\n", iio_buffer_is_active(buffer)); 679a980e046SJonathan Cameron } 680a980e046SJonathan Cameron 681182b4905SLars-Peter Clausen static unsigned int iio_storage_bytes_for_si(struct iio_dev *indio_dev, 682182b4905SLars-Peter Clausen unsigned int scan_index) 683182b4905SLars-Peter Clausen { 684182b4905SLars-Peter Clausen const struct iio_chan_spec *ch; 685182b4905SLars-Peter Clausen unsigned int bytes; 686182b4905SLars-Peter Clausen 687182b4905SLars-Peter Clausen ch = iio_find_channel_from_si(indio_dev, scan_index); 688182b4905SLars-Peter Clausen bytes = ch->scan_type.storagebits / 8; 689182b4905SLars-Peter Clausen if (ch->scan_type.repeat > 1) 690182b4905SLars-Peter Clausen bytes *= ch->scan_type.repeat; 691182b4905SLars-Peter Clausen return bytes; 692182b4905SLars-Peter Clausen } 693182b4905SLars-Peter Clausen 694182b4905SLars-Peter Clausen static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev) 695182b4905SLars-Peter Clausen { 69662f4f36cSJonathan Cameron struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 69762f4f36cSJonathan Cameron 698182b4905SLars-Peter Clausen return iio_storage_bytes_for_si(indio_dev, 69962f4f36cSJonathan Cameron iio_dev_opaque->scan_index_timestamp); 700182b4905SLars-Peter Clausen } 701182b4905SLars-Peter Clausen 702183f4173SPeter Meerwald static int iio_compute_scan_bytes(struct iio_dev *indio_dev, 703183f4173SPeter Meerwald const unsigned long *mask, bool timestamp) 704a980e046SJonathan Cameron { 705*abeba59fSJoe Simmons-Talbott unsigned int bytes = 0; 706883f6165SLars Möllendorf int length, i, largest = 0; 707a980e046SJonathan Cameron 708a980e046SJonathan Cameron /* How much space will the demuxed element take? */ 709a980e046SJonathan Cameron for_each_set_bit(i, mask, 710a980e046SJonathan Cameron indio_dev->masklength) { 711182b4905SLars-Peter Clausen length = iio_storage_bytes_for_si(indio_dev, i); 712a980e046SJonathan Cameron bytes = ALIGN(bytes, length); 713a980e046SJonathan Cameron bytes += length; 714883f6165SLars Möllendorf largest = max(largest, length); 715a980e046SJonathan Cameron } 716182b4905SLars-Peter Clausen 717a980e046SJonathan Cameron if (timestamp) { 718182b4905SLars-Peter Clausen length = iio_storage_bytes_for_timestamp(indio_dev); 719a980e046SJonathan Cameron bytes = ALIGN(bytes, length); 720a980e046SJonathan Cameron bytes += length; 721883f6165SLars Möllendorf largest = max(largest, length); 722a980e046SJonathan Cameron } 723883f6165SLars Möllendorf 724883f6165SLars Möllendorf bytes = ALIGN(bytes, largest); 725a980e046SJonathan Cameron return bytes; 726a980e046SJonathan Cameron } 727a980e046SJonathan Cameron 7289e69c935SLars-Peter Clausen static void iio_buffer_activate(struct iio_dev *indio_dev, 7299e69c935SLars-Peter Clausen struct iio_buffer *buffer) 7309e69c935SLars-Peter Clausen { 7316a8c6b26SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 7326a8c6b26SAlexandru Ardelean 7339e69c935SLars-Peter Clausen iio_buffer_get(buffer); 7346a8c6b26SAlexandru Ardelean list_add(&buffer->buffer_list, &iio_dev_opaque->buffer_list); 7359e69c935SLars-Peter Clausen } 7369e69c935SLars-Peter Clausen 7379e69c935SLars-Peter Clausen static void iio_buffer_deactivate(struct iio_buffer *buffer) 7389e69c935SLars-Peter Clausen { 7399e69c935SLars-Peter Clausen list_del_init(&buffer->buffer_list); 74037d34556SJosselin Costanzi wake_up_interruptible(&buffer->pollq); 7419e69c935SLars-Peter Clausen iio_buffer_put(buffer); 7429e69c935SLars-Peter Clausen } 7439e69c935SLars-Peter Clausen 7441250186aSLars-Peter Clausen static void iio_buffer_deactivate_all(struct iio_dev *indio_dev) 7451250186aSLars-Peter Clausen { 7466a8c6b26SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 7471250186aSLars-Peter Clausen struct iio_buffer *buffer, *_buffer; 7481250186aSLars-Peter Clausen 7491250186aSLars-Peter Clausen list_for_each_entry_safe(buffer, _buffer, 7506a8c6b26SAlexandru Ardelean &iio_dev_opaque->buffer_list, buffer_list) 7511250186aSLars-Peter Clausen iio_buffer_deactivate(buffer); 7521250186aSLars-Peter Clausen } 7531250186aSLars-Peter Clausen 754e18a2ad4SLars-Peter Clausen static int iio_buffer_enable(struct iio_buffer *buffer, 755e18a2ad4SLars-Peter Clausen struct iio_dev *indio_dev) 756e18a2ad4SLars-Peter Clausen { 757e18a2ad4SLars-Peter Clausen if (!buffer->access->enable) 758e18a2ad4SLars-Peter Clausen return 0; 759e18a2ad4SLars-Peter Clausen return buffer->access->enable(buffer, indio_dev); 760e18a2ad4SLars-Peter Clausen } 761e18a2ad4SLars-Peter Clausen 762e18a2ad4SLars-Peter Clausen static int iio_buffer_disable(struct iio_buffer *buffer, 763e18a2ad4SLars-Peter Clausen struct iio_dev *indio_dev) 764e18a2ad4SLars-Peter Clausen { 765e18a2ad4SLars-Peter Clausen if (!buffer->access->disable) 766e18a2ad4SLars-Peter Clausen return 0; 767e18a2ad4SLars-Peter Clausen return buffer->access->disable(buffer, indio_dev); 768e18a2ad4SLars-Peter Clausen } 769e18a2ad4SLars-Peter Clausen 7708e050996SLars-Peter Clausen static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev, 7718e050996SLars-Peter Clausen struct iio_buffer *buffer) 7728e050996SLars-Peter Clausen { 7738e050996SLars-Peter Clausen unsigned int bytes; 7748e050996SLars-Peter Clausen 7758e050996SLars-Peter Clausen if (!buffer->access->set_bytes_per_datum) 7768e050996SLars-Peter Clausen return; 7778e050996SLars-Peter Clausen 7788e050996SLars-Peter Clausen bytes = iio_compute_scan_bytes(indio_dev, buffer->scan_mask, 7798e050996SLars-Peter Clausen buffer->scan_timestamp); 7808e050996SLars-Peter Clausen 7818e050996SLars-Peter Clausen buffer->access->set_bytes_per_datum(buffer, bytes); 7828e050996SLars-Peter Clausen } 7838e050996SLars-Peter Clausen 784fcc1b2f5SLars-Peter Clausen static int iio_buffer_request_update(struct iio_dev *indio_dev, 785fcc1b2f5SLars-Peter Clausen struct iio_buffer *buffer) 786fcc1b2f5SLars-Peter Clausen { 787fcc1b2f5SLars-Peter Clausen int ret; 788fcc1b2f5SLars-Peter Clausen 789fcc1b2f5SLars-Peter Clausen iio_buffer_update_bytes_per_datum(indio_dev, buffer); 790fcc1b2f5SLars-Peter Clausen if (buffer->access->request_update) { 791fcc1b2f5SLars-Peter Clausen ret = buffer->access->request_update(buffer); 792fcc1b2f5SLars-Peter Clausen if (ret) { 793fcc1b2f5SLars-Peter Clausen dev_dbg(&indio_dev->dev, 794fcc1b2f5SLars-Peter Clausen "Buffer not started: buffer parameter update failed (%d)\n", 795fcc1b2f5SLars-Peter Clausen ret); 796fcc1b2f5SLars-Peter Clausen return ret; 797fcc1b2f5SLars-Peter Clausen } 798fcc1b2f5SLars-Peter Clausen } 799fcc1b2f5SLars-Peter Clausen 800fcc1b2f5SLars-Peter Clausen return 0; 801fcc1b2f5SLars-Peter Clausen } 802fcc1b2f5SLars-Peter Clausen 803248be5aaSLars-Peter Clausen static void iio_free_scan_mask(struct iio_dev *indio_dev, 804248be5aaSLars-Peter Clausen const unsigned long *mask) 805248be5aaSLars-Peter Clausen { 806248be5aaSLars-Peter Clausen /* If the mask is dynamically allocated free it, otherwise do nothing */ 807248be5aaSLars-Peter Clausen if (!indio_dev->available_scan_masks) 8083862828aSAndy Shevchenko bitmap_free(mask); 809248be5aaSLars-Peter Clausen } 810248be5aaSLars-Peter Clausen 8116e509c4dSLars-Peter Clausen struct iio_device_config { 8126e509c4dSLars-Peter Clausen unsigned int mode; 813f0566c0cSLars-Peter Clausen unsigned int watermark; 8146e509c4dSLars-Peter Clausen const unsigned long *scan_mask; 8156e509c4dSLars-Peter Clausen unsigned int scan_bytes; 8166e509c4dSLars-Peter Clausen bool scan_timestamp; 8176e509c4dSLars-Peter Clausen }; 8186e509c4dSLars-Peter Clausen 8196e509c4dSLars-Peter Clausen static int iio_verify_update(struct iio_dev *indio_dev, 8206e509c4dSLars-Peter Clausen struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer, 8216e509c4dSLars-Peter Clausen struct iio_device_config *config) 8226e509c4dSLars-Peter Clausen { 8236a8c6b26SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 8246e509c4dSLars-Peter Clausen unsigned long *compound_mask; 8256e509c4dSLars-Peter Clausen const unsigned long *scan_mask; 8261e1ec286SLars-Peter Clausen bool strict_scanmask = false; 8276e509c4dSLars-Peter Clausen struct iio_buffer *buffer; 8286e509c4dSLars-Peter Clausen bool scan_timestamp; 829225d59adSLars-Peter Clausen unsigned int modes; 8306e509c4dSLars-Peter Clausen 831b7329249SLars-Peter Clausen if (insert_buffer && 832b7329249SLars-Peter Clausen bitmap_empty(insert_buffer->scan_mask, indio_dev->masklength)) { 833b7329249SLars-Peter Clausen dev_dbg(&indio_dev->dev, 834b7329249SLars-Peter Clausen "At least one scan element must be enabled first\n"); 835b7329249SLars-Peter Clausen return -EINVAL; 836b7329249SLars-Peter Clausen } 837b7329249SLars-Peter Clausen 8386e509c4dSLars-Peter Clausen memset(config, 0, sizeof(*config)); 8391bef2c1dSIrina Tirdea config->watermark = ~0; 8406e509c4dSLars-Peter Clausen 8416e509c4dSLars-Peter Clausen /* 8426e509c4dSLars-Peter Clausen * If there is just one buffer and we are removing it there is nothing 8436e509c4dSLars-Peter Clausen * to verify. 8446e509c4dSLars-Peter Clausen */ 8456e509c4dSLars-Peter Clausen if (remove_buffer && !insert_buffer && 8466a8c6b26SAlexandru Ardelean list_is_singular(&iio_dev_opaque->buffer_list)) 8476e509c4dSLars-Peter Clausen return 0; 8486e509c4dSLars-Peter Clausen 849225d59adSLars-Peter Clausen modes = indio_dev->modes; 850225d59adSLars-Peter Clausen 8516a8c6b26SAlexandru Ardelean list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { 852225d59adSLars-Peter Clausen if (buffer == remove_buffer) 853225d59adSLars-Peter Clausen continue; 854225d59adSLars-Peter Clausen modes &= buffer->access->modes; 855f0566c0cSLars-Peter Clausen config->watermark = min(config->watermark, buffer->watermark); 856225d59adSLars-Peter Clausen } 857225d59adSLars-Peter Clausen 858f0566c0cSLars-Peter Clausen if (insert_buffer) { 859225d59adSLars-Peter Clausen modes &= insert_buffer->access->modes; 860f0566c0cSLars-Peter Clausen config->watermark = min(config->watermark, 861f0566c0cSLars-Peter Clausen insert_buffer->watermark); 862f0566c0cSLars-Peter Clausen } 863225d59adSLars-Peter Clausen 8646e509c4dSLars-Peter Clausen /* Definitely possible for devices to support both of these. */ 865225d59adSLars-Peter Clausen if ((modes & INDIO_BUFFER_TRIGGERED) && indio_dev->trig) { 8666e509c4dSLars-Peter Clausen config->mode = INDIO_BUFFER_TRIGGERED; 867225d59adSLars-Peter Clausen } else if (modes & INDIO_BUFFER_HARDWARE) { 8681e1ec286SLars-Peter Clausen /* 8691e1ec286SLars-Peter Clausen * Keep things simple for now and only allow a single buffer to 8701e1ec286SLars-Peter Clausen * be connected in hardware mode. 8711e1ec286SLars-Peter Clausen */ 8726a8c6b26SAlexandru Ardelean if (insert_buffer && !list_empty(&iio_dev_opaque->buffer_list)) 8731e1ec286SLars-Peter Clausen return -EINVAL; 8746e509c4dSLars-Peter Clausen config->mode = INDIO_BUFFER_HARDWARE; 8751e1ec286SLars-Peter Clausen strict_scanmask = true; 876225d59adSLars-Peter Clausen } else if (modes & INDIO_BUFFER_SOFTWARE) { 8776e509c4dSLars-Peter Clausen config->mode = INDIO_BUFFER_SOFTWARE; 8786e509c4dSLars-Peter Clausen } else { 8796e509c4dSLars-Peter Clausen /* Can only occur on first buffer */ 8806e509c4dSLars-Peter Clausen if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) 8816e509c4dSLars-Peter Clausen dev_dbg(&indio_dev->dev, "Buffer not started: no trigger\n"); 8826e509c4dSLars-Peter Clausen return -EINVAL; 8836e509c4dSLars-Peter Clausen } 8846e509c4dSLars-Peter Clausen 8856e509c4dSLars-Peter Clausen /* What scan mask do we actually have? */ 8863862828aSAndy Shevchenko compound_mask = bitmap_zalloc(indio_dev->masklength, GFP_KERNEL); 8876e509c4dSLars-Peter Clausen if (compound_mask == NULL) 8886e509c4dSLars-Peter Clausen return -ENOMEM; 8896e509c4dSLars-Peter Clausen 8906e509c4dSLars-Peter Clausen scan_timestamp = false; 8916e509c4dSLars-Peter Clausen 8926a8c6b26SAlexandru Ardelean list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { 8936e509c4dSLars-Peter Clausen if (buffer == remove_buffer) 8946e509c4dSLars-Peter Clausen continue; 8956e509c4dSLars-Peter Clausen bitmap_or(compound_mask, compound_mask, buffer->scan_mask, 8966e509c4dSLars-Peter Clausen indio_dev->masklength); 8976e509c4dSLars-Peter Clausen scan_timestamp |= buffer->scan_timestamp; 8986e509c4dSLars-Peter Clausen } 8996e509c4dSLars-Peter Clausen 9006e509c4dSLars-Peter Clausen if (insert_buffer) { 9016e509c4dSLars-Peter Clausen bitmap_or(compound_mask, compound_mask, 9026e509c4dSLars-Peter Clausen insert_buffer->scan_mask, indio_dev->masklength); 9036e509c4dSLars-Peter Clausen scan_timestamp |= insert_buffer->scan_timestamp; 9046e509c4dSLars-Peter Clausen } 9056e509c4dSLars-Peter Clausen 9066e509c4dSLars-Peter Clausen if (indio_dev->available_scan_masks) { 9076e509c4dSLars-Peter Clausen scan_mask = iio_scan_mask_match(indio_dev->available_scan_masks, 9086e509c4dSLars-Peter Clausen indio_dev->masklength, 9091e1ec286SLars-Peter Clausen compound_mask, 9101e1ec286SLars-Peter Clausen strict_scanmask); 9113862828aSAndy Shevchenko bitmap_free(compound_mask); 9126e509c4dSLars-Peter Clausen if (scan_mask == NULL) 9136e509c4dSLars-Peter Clausen return -EINVAL; 9146e509c4dSLars-Peter Clausen } else { 9156e509c4dSLars-Peter Clausen scan_mask = compound_mask; 9166e509c4dSLars-Peter Clausen } 9176e509c4dSLars-Peter Clausen 9186e509c4dSLars-Peter Clausen config->scan_bytes = iio_compute_scan_bytes(indio_dev, 9196e509c4dSLars-Peter Clausen scan_mask, scan_timestamp); 9206e509c4dSLars-Peter Clausen config->scan_mask = scan_mask; 9216e509c4dSLars-Peter Clausen config->scan_timestamp = scan_timestamp; 9226e509c4dSLars-Peter Clausen 9236e509c4dSLars-Peter Clausen return 0; 9246e509c4dSLars-Peter Clausen } 9256e509c4dSLars-Peter Clausen 92678c9981fSJonathan Cameron /** 92778c9981fSJonathan Cameron * struct iio_demux_table - table describing demux memcpy ops 92878c9981fSJonathan Cameron * @from: index to copy from 92978c9981fSJonathan Cameron * @to: index to copy to 93078c9981fSJonathan Cameron * @length: how many bytes to copy 93178c9981fSJonathan Cameron * @l: list head used for management 93278c9981fSJonathan Cameron */ 93378c9981fSJonathan Cameron struct iio_demux_table { 934*abeba59fSJoe Simmons-Talbott unsigned int from; 935*abeba59fSJoe Simmons-Talbott unsigned int to; 936*abeba59fSJoe Simmons-Talbott unsigned int length; 93778c9981fSJonathan Cameron struct list_head l; 93878c9981fSJonathan Cameron }; 93978c9981fSJonathan Cameron 94078c9981fSJonathan Cameron static void iio_buffer_demux_free(struct iio_buffer *buffer) 94178c9981fSJonathan Cameron { 94278c9981fSJonathan Cameron struct iio_demux_table *p, *q; 94378c9981fSJonathan Cameron list_for_each_entry_safe(p, q, &buffer->demux_list, l) { 94478c9981fSJonathan Cameron list_del(&p->l); 94578c9981fSJonathan Cameron kfree(p); 94678c9981fSJonathan Cameron } 94778c9981fSJonathan Cameron } 94878c9981fSJonathan Cameron 94978c9981fSJonathan Cameron static int iio_buffer_add_demux(struct iio_buffer *buffer, 95078c9981fSJonathan Cameron struct iio_demux_table **p, unsigned int in_loc, unsigned int out_loc, 95178c9981fSJonathan Cameron unsigned int length) 95278c9981fSJonathan Cameron { 95378c9981fSJonathan Cameron 95478c9981fSJonathan Cameron if (*p && (*p)->from + (*p)->length == in_loc && 95578c9981fSJonathan Cameron (*p)->to + (*p)->length == out_loc) { 95678c9981fSJonathan Cameron (*p)->length += length; 95778c9981fSJonathan Cameron } else { 95878c9981fSJonathan Cameron *p = kmalloc(sizeof(**p), GFP_KERNEL); 95978c9981fSJonathan Cameron if (*p == NULL) 96078c9981fSJonathan Cameron return -ENOMEM; 96178c9981fSJonathan Cameron (*p)->from = in_loc; 96278c9981fSJonathan Cameron (*p)->to = out_loc; 96378c9981fSJonathan Cameron (*p)->length = length; 96478c9981fSJonathan Cameron list_add_tail(&(*p)->l, &buffer->demux_list); 96578c9981fSJonathan Cameron } 96678c9981fSJonathan Cameron 96778c9981fSJonathan Cameron return 0; 96878c9981fSJonathan Cameron } 96978c9981fSJonathan Cameron 97078c9981fSJonathan Cameron static int iio_buffer_update_demux(struct iio_dev *indio_dev, 97178c9981fSJonathan Cameron struct iio_buffer *buffer) 97278c9981fSJonathan Cameron { 97378c9981fSJonathan Cameron int ret, in_ind = -1, out_ind, length; 974*abeba59fSJoe Simmons-Talbott unsigned int in_loc = 0, out_loc = 0; 97578c9981fSJonathan Cameron struct iio_demux_table *p = NULL; 97678c9981fSJonathan Cameron 97778c9981fSJonathan Cameron /* Clear out any old demux */ 97878c9981fSJonathan Cameron iio_buffer_demux_free(buffer); 97978c9981fSJonathan Cameron kfree(buffer->demux_bounce); 98078c9981fSJonathan Cameron buffer->demux_bounce = NULL; 98178c9981fSJonathan Cameron 98278c9981fSJonathan Cameron /* First work out which scan mode we will actually have */ 98378c9981fSJonathan Cameron if (bitmap_equal(indio_dev->active_scan_mask, 98478c9981fSJonathan Cameron buffer->scan_mask, 98578c9981fSJonathan Cameron indio_dev->masklength)) 98678c9981fSJonathan Cameron return 0; 98778c9981fSJonathan Cameron 98878c9981fSJonathan Cameron /* Now we have the two masks, work from least sig and build up sizes */ 98978c9981fSJonathan Cameron for_each_set_bit(out_ind, 99078c9981fSJonathan Cameron buffer->scan_mask, 99178c9981fSJonathan Cameron indio_dev->masklength) { 99278c9981fSJonathan Cameron in_ind = find_next_bit(indio_dev->active_scan_mask, 99378c9981fSJonathan Cameron indio_dev->masklength, 99478c9981fSJonathan Cameron in_ind + 1); 99578c9981fSJonathan Cameron while (in_ind != out_ind) { 99678c9981fSJonathan Cameron length = iio_storage_bytes_for_si(indio_dev, in_ind); 99778c9981fSJonathan Cameron /* Make sure we are aligned */ 99878c9981fSJonathan Cameron in_loc = roundup(in_loc, length) + length; 99919ef7b70SNuno Sá in_ind = find_next_bit(indio_dev->active_scan_mask, 100019ef7b70SNuno Sá indio_dev->masklength, 100119ef7b70SNuno Sá in_ind + 1); 100278c9981fSJonathan Cameron } 100378c9981fSJonathan Cameron length = iio_storage_bytes_for_si(indio_dev, in_ind); 100478c9981fSJonathan Cameron out_loc = roundup(out_loc, length); 100578c9981fSJonathan Cameron in_loc = roundup(in_loc, length); 100678c9981fSJonathan Cameron ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length); 100778c9981fSJonathan Cameron if (ret) 100878c9981fSJonathan Cameron goto error_clear_mux_table; 100978c9981fSJonathan Cameron out_loc += length; 101078c9981fSJonathan Cameron in_loc += length; 101178c9981fSJonathan Cameron } 101278c9981fSJonathan Cameron /* Relies on scan_timestamp being last */ 101378c9981fSJonathan Cameron if (buffer->scan_timestamp) { 101478c9981fSJonathan Cameron length = iio_storage_bytes_for_timestamp(indio_dev); 101578c9981fSJonathan Cameron out_loc = roundup(out_loc, length); 101678c9981fSJonathan Cameron in_loc = roundup(in_loc, length); 101778c9981fSJonathan Cameron ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length); 101878c9981fSJonathan Cameron if (ret) 101978c9981fSJonathan Cameron goto error_clear_mux_table; 102078c9981fSJonathan Cameron out_loc += length; 102178c9981fSJonathan Cameron } 102278c9981fSJonathan Cameron buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL); 102378c9981fSJonathan Cameron if (buffer->demux_bounce == NULL) { 102478c9981fSJonathan Cameron ret = -ENOMEM; 102578c9981fSJonathan Cameron goto error_clear_mux_table; 102678c9981fSJonathan Cameron } 102778c9981fSJonathan Cameron return 0; 102878c9981fSJonathan Cameron 102978c9981fSJonathan Cameron error_clear_mux_table: 103078c9981fSJonathan Cameron iio_buffer_demux_free(buffer); 103178c9981fSJonathan Cameron 103278c9981fSJonathan Cameron return ret; 103378c9981fSJonathan Cameron } 103478c9981fSJonathan Cameron 103578c9981fSJonathan Cameron static int iio_update_demux(struct iio_dev *indio_dev) 103678c9981fSJonathan Cameron { 10376a8c6b26SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 103878c9981fSJonathan Cameron struct iio_buffer *buffer; 103978c9981fSJonathan Cameron int ret; 104078c9981fSJonathan Cameron 10416a8c6b26SAlexandru Ardelean list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { 104278c9981fSJonathan Cameron ret = iio_buffer_update_demux(indio_dev, buffer); 104378c9981fSJonathan Cameron if (ret < 0) 104478c9981fSJonathan Cameron goto error_clear_mux_table; 104578c9981fSJonathan Cameron } 104678c9981fSJonathan Cameron return 0; 104778c9981fSJonathan Cameron 104878c9981fSJonathan Cameron error_clear_mux_table: 10496a8c6b26SAlexandru Ardelean list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) 105078c9981fSJonathan Cameron iio_buffer_demux_free(buffer); 105178c9981fSJonathan Cameron 105278c9981fSJonathan Cameron return ret; 105378c9981fSJonathan Cameron } 105478c9981fSJonathan Cameron 1055623d74e3SLars-Peter Clausen static int iio_enable_buffers(struct iio_dev *indio_dev, 1056623d74e3SLars-Peter Clausen struct iio_device_config *config) 1057623d74e3SLars-Peter Clausen { 10586a8c6b26SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1059c22e60c3SJakob Koschel struct iio_buffer *buffer, *tmp = NULL; 1060623d74e3SLars-Peter Clausen int ret; 1061623d74e3SLars-Peter Clausen 1062623d74e3SLars-Peter Clausen indio_dev->active_scan_mask = config->scan_mask; 1063623d74e3SLars-Peter Clausen indio_dev->scan_timestamp = config->scan_timestamp; 1064623d74e3SLars-Peter Clausen indio_dev->scan_bytes = config->scan_bytes; 106551570c9dSMiquel Raynal iio_dev_opaque->currentmode = config->mode; 1066623d74e3SLars-Peter Clausen 1067623d74e3SLars-Peter Clausen iio_update_demux(indio_dev); 1068623d74e3SLars-Peter Clausen 1069623d74e3SLars-Peter Clausen /* Wind up again */ 1070623d74e3SLars-Peter Clausen if (indio_dev->setup_ops->preenable) { 1071623d74e3SLars-Peter Clausen ret = indio_dev->setup_ops->preenable(indio_dev); 1072623d74e3SLars-Peter Clausen if (ret) { 1073623d74e3SLars-Peter Clausen dev_dbg(&indio_dev->dev, 1074623d74e3SLars-Peter Clausen "Buffer not started: buffer preenable failed (%d)\n", ret); 1075623d74e3SLars-Peter Clausen goto err_undo_config; 1076623d74e3SLars-Peter Clausen } 1077623d74e3SLars-Peter Clausen } 1078623d74e3SLars-Peter Clausen 1079623d74e3SLars-Peter Clausen if (indio_dev->info->update_scan_mode) { 1080623d74e3SLars-Peter Clausen ret = indio_dev->info 1081623d74e3SLars-Peter Clausen ->update_scan_mode(indio_dev, 1082623d74e3SLars-Peter Clausen indio_dev->active_scan_mask); 1083623d74e3SLars-Peter Clausen if (ret < 0) { 1084623d74e3SLars-Peter Clausen dev_dbg(&indio_dev->dev, 1085623d74e3SLars-Peter Clausen "Buffer not started: update scan mode failed (%d)\n", 1086623d74e3SLars-Peter Clausen ret); 1087623d74e3SLars-Peter Clausen goto err_run_postdisable; 1088623d74e3SLars-Peter Clausen } 1089623d74e3SLars-Peter Clausen } 1090623d74e3SLars-Peter Clausen 1091f0566c0cSLars-Peter Clausen if (indio_dev->info->hwfifo_set_watermark) 1092f0566c0cSLars-Peter Clausen indio_dev->info->hwfifo_set_watermark(indio_dev, 1093f0566c0cSLars-Peter Clausen config->watermark); 1094f0566c0cSLars-Peter Clausen 10956a8c6b26SAlexandru Ardelean list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { 1096e18a2ad4SLars-Peter Clausen ret = iio_buffer_enable(buffer, indio_dev); 1097c22e60c3SJakob Koschel if (ret) { 1098c22e60c3SJakob Koschel tmp = buffer; 1099e18a2ad4SLars-Peter Clausen goto err_disable_buffers; 1100e18a2ad4SLars-Peter Clausen } 1101c22e60c3SJakob Koschel } 1102e18a2ad4SLars-Peter Clausen 110351570c9dSMiquel Raynal if (iio_dev_opaque->currentmode == INDIO_BUFFER_TRIGGERED) { 1104f11d59d8SLars-Peter Clausen ret = iio_trigger_attach_poll_func(indio_dev->trig, 1105f11d59d8SLars-Peter Clausen indio_dev->pollfunc); 1106f11d59d8SLars-Peter Clausen if (ret) 1107f11d59d8SLars-Peter Clausen goto err_disable_buffers; 1108f11d59d8SLars-Peter Clausen } 1109f11d59d8SLars-Peter Clausen 111062a30a29SAlexandru Ardelean if (indio_dev->setup_ops->postenable) { 111162a30a29SAlexandru Ardelean ret = indio_dev->setup_ops->postenable(indio_dev); 111262a30a29SAlexandru Ardelean if (ret) { 111362a30a29SAlexandru Ardelean dev_dbg(&indio_dev->dev, 111462a30a29SAlexandru Ardelean "Buffer not started: postenable failed (%d)\n", ret); 111562a30a29SAlexandru Ardelean goto err_detach_pollfunc; 111662a30a29SAlexandru Ardelean } 111762a30a29SAlexandru Ardelean } 111862a30a29SAlexandru Ardelean 1119623d74e3SLars-Peter Clausen return 0; 1120623d74e3SLars-Peter Clausen 112162a30a29SAlexandru Ardelean err_detach_pollfunc: 112251570c9dSMiquel Raynal if (iio_dev_opaque->currentmode == INDIO_BUFFER_TRIGGERED) { 112362a30a29SAlexandru Ardelean iio_trigger_detach_poll_func(indio_dev->trig, 112462a30a29SAlexandru Ardelean indio_dev->pollfunc); 112562a30a29SAlexandru Ardelean } 1126e18a2ad4SLars-Peter Clausen err_disable_buffers: 1127c22e60c3SJakob Koschel buffer = list_prepare_entry(tmp, &iio_dev_opaque->buffer_list, buffer_list); 11286a8c6b26SAlexandru Ardelean list_for_each_entry_continue_reverse(buffer, &iio_dev_opaque->buffer_list, 1129e18a2ad4SLars-Peter Clausen buffer_list) 1130e18a2ad4SLars-Peter Clausen iio_buffer_disable(buffer, indio_dev); 1131623d74e3SLars-Peter Clausen err_run_postdisable: 1132623d74e3SLars-Peter Clausen if (indio_dev->setup_ops->postdisable) 1133623d74e3SLars-Peter Clausen indio_dev->setup_ops->postdisable(indio_dev); 1134623d74e3SLars-Peter Clausen err_undo_config: 113551570c9dSMiquel Raynal iio_dev_opaque->currentmode = INDIO_DIRECT_MODE; 1136623d74e3SLars-Peter Clausen indio_dev->active_scan_mask = NULL; 1137623d74e3SLars-Peter Clausen 1138623d74e3SLars-Peter Clausen return ret; 1139623d74e3SLars-Peter Clausen } 1140623d74e3SLars-Peter Clausen 1141623d74e3SLars-Peter Clausen static int iio_disable_buffers(struct iio_dev *indio_dev) 1142623d74e3SLars-Peter Clausen { 11436a8c6b26SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1144e18a2ad4SLars-Peter Clausen struct iio_buffer *buffer; 11451250186aSLars-Peter Clausen int ret = 0; 11461250186aSLars-Peter Clausen int ret2; 1147623d74e3SLars-Peter Clausen 1148623d74e3SLars-Peter Clausen /* Wind down existing buffers - iff there are any */ 11496a8c6b26SAlexandru Ardelean if (list_empty(&iio_dev_opaque->buffer_list)) 1150623d74e3SLars-Peter Clausen return 0; 1151623d74e3SLars-Peter Clausen 11521250186aSLars-Peter Clausen /* 11531250186aSLars-Peter Clausen * If things go wrong at some step in disable we still need to continue 11541250186aSLars-Peter Clausen * to perform the other steps, otherwise we leave the device in a 11551250186aSLars-Peter Clausen * inconsistent state. We return the error code for the first error we 11561250186aSLars-Peter Clausen * encountered. 11571250186aSLars-Peter Clausen */ 11581250186aSLars-Peter Clausen 1159623d74e3SLars-Peter Clausen if (indio_dev->setup_ops->predisable) { 11601250186aSLars-Peter Clausen ret2 = indio_dev->setup_ops->predisable(indio_dev); 11611250186aSLars-Peter Clausen if (ret2 && !ret) 11621250186aSLars-Peter Clausen ret = ret2; 1163623d74e3SLars-Peter Clausen } 1164623d74e3SLars-Peter Clausen 116551570c9dSMiquel Raynal if (iio_dev_opaque->currentmode == INDIO_BUFFER_TRIGGERED) { 116662a30a29SAlexandru Ardelean iio_trigger_detach_poll_func(indio_dev->trig, 116762a30a29SAlexandru Ardelean indio_dev->pollfunc); 116862a30a29SAlexandru Ardelean } 116962a30a29SAlexandru Ardelean 11706a8c6b26SAlexandru Ardelean list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { 1171e18a2ad4SLars-Peter Clausen ret2 = iio_buffer_disable(buffer, indio_dev); 1172e18a2ad4SLars-Peter Clausen if (ret2 && !ret) 1173e18a2ad4SLars-Peter Clausen ret = ret2; 1174e18a2ad4SLars-Peter Clausen } 1175e18a2ad4SLars-Peter Clausen 1176623d74e3SLars-Peter Clausen if (indio_dev->setup_ops->postdisable) { 11771250186aSLars-Peter Clausen ret2 = indio_dev->setup_ops->postdisable(indio_dev); 11781250186aSLars-Peter Clausen if (ret2 && !ret) 11791250186aSLars-Peter Clausen ret = ret2; 1180623d74e3SLars-Peter Clausen } 1181623d74e3SLars-Peter Clausen 11821250186aSLars-Peter Clausen iio_free_scan_mask(indio_dev, indio_dev->active_scan_mask); 11831250186aSLars-Peter Clausen indio_dev->active_scan_mask = NULL; 118451570c9dSMiquel Raynal iio_dev_opaque->currentmode = INDIO_DIRECT_MODE; 11851250186aSLars-Peter Clausen 11861250186aSLars-Peter Clausen return ret; 1187623d74e3SLars-Peter Clausen } 1188623d74e3SLars-Peter Clausen 1189a9519456SLars-Peter Clausen static int __iio_update_buffers(struct iio_dev *indio_dev, 119084b36ce5SJonathan Cameron struct iio_buffer *insert_buffer, 119184b36ce5SJonathan Cameron struct iio_buffer *remove_buffer) 1192a980e046SJonathan Cameron { 11936a8c6b26SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 11946e509c4dSLars-Peter Clausen struct iio_device_config new_config; 11951250186aSLars-Peter Clausen int ret; 11966e509c4dSLars-Peter Clausen 11976e509c4dSLars-Peter Clausen ret = iio_verify_update(indio_dev, insert_buffer, remove_buffer, 11986e509c4dSLars-Peter Clausen &new_config); 11996e509c4dSLars-Peter Clausen if (ret) 12006e509c4dSLars-Peter Clausen return ret; 1201a980e046SJonathan Cameron 1202fcc1b2f5SLars-Peter Clausen if (insert_buffer) { 1203fcc1b2f5SLars-Peter Clausen ret = iio_buffer_request_update(indio_dev, insert_buffer); 1204fcc1b2f5SLars-Peter Clausen if (ret) 12056e509c4dSLars-Peter Clausen goto err_free_config; 1206fcc1b2f5SLars-Peter Clausen } 1207fcc1b2f5SLars-Peter Clausen 1208623d74e3SLars-Peter Clausen ret = iio_disable_buffers(indio_dev); 12091250186aSLars-Peter Clausen if (ret) 12101250186aSLars-Peter Clausen goto err_deactivate_all; 1211623d74e3SLars-Peter Clausen 121284b36ce5SJonathan Cameron if (remove_buffer) 12139e69c935SLars-Peter Clausen iio_buffer_deactivate(remove_buffer); 121484b36ce5SJonathan Cameron if (insert_buffer) 12159e69c935SLars-Peter Clausen iio_buffer_activate(indio_dev, insert_buffer); 121684b36ce5SJonathan Cameron 121784b36ce5SJonathan Cameron /* If no buffers in list, we are done */ 12186a8c6b26SAlexandru Ardelean if (list_empty(&iio_dev_opaque->buffer_list)) 121984b36ce5SJonathan Cameron return 0; 1220a980e046SJonathan Cameron 1221623d74e3SLars-Peter Clausen ret = iio_enable_buffers(indio_dev, &new_config); 12221250186aSLars-Peter Clausen if (ret) 12231250186aSLars-Peter Clausen goto err_deactivate_all; 1224623d74e3SLars-Peter Clausen 1225623d74e3SLars-Peter Clausen return 0; 12266e509c4dSLars-Peter Clausen 12271250186aSLars-Peter Clausen err_deactivate_all: 12281250186aSLars-Peter Clausen /* 12291250186aSLars-Peter Clausen * We've already verified that the config is valid earlier. If things go 12301250186aSLars-Peter Clausen * wrong in either enable or disable the most likely reason is an IO 12311250186aSLars-Peter Clausen * error from the device. In this case there is no good recovery 12321250186aSLars-Peter Clausen * strategy. Just make sure to disable everything and leave the device 12331250186aSLars-Peter Clausen * in a sane state. With a bit of luck the device might come back to 12341250186aSLars-Peter Clausen * life again later and userspace can try again. 12351250186aSLars-Peter Clausen */ 12361250186aSLars-Peter Clausen iio_buffer_deactivate_all(indio_dev); 12371250186aSLars-Peter Clausen 12386e509c4dSLars-Peter Clausen err_free_config: 12396e509c4dSLars-Peter Clausen iio_free_scan_mask(indio_dev, new_config.scan_mask); 12406e509c4dSLars-Peter Clausen return ret; 124184b36ce5SJonathan Cameron } 1242a9519456SLars-Peter Clausen 1243a9519456SLars-Peter Clausen int iio_update_buffers(struct iio_dev *indio_dev, 1244a9519456SLars-Peter Clausen struct iio_buffer *insert_buffer, 1245a9519456SLars-Peter Clausen struct iio_buffer *remove_buffer) 1246a9519456SLars-Peter Clausen { 1247b804e2b7SJonathan Cameron struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1248a9519456SLars-Peter Clausen int ret; 1249a9519456SLars-Peter Clausen 12503909fab5SLars-Peter Clausen if (insert_buffer == remove_buffer) 12513909fab5SLars-Peter Clausen return 0; 12523909fab5SLars-Peter Clausen 12539eeee3b0SMihail Chindris if (insert_buffer && 12549eeee3b0SMihail Chindris (insert_buffer->direction == IIO_BUFFER_DIRECTION_OUT)) 12559eeee3b0SMihail Chindris return -EINVAL; 12569eeee3b0SMihail Chindris 1257b804e2b7SJonathan Cameron mutex_lock(&iio_dev_opaque->info_exist_lock); 1258a9519456SLars-Peter Clausen mutex_lock(&indio_dev->mlock); 1259a9519456SLars-Peter Clausen 12603909fab5SLars-Peter Clausen if (insert_buffer && iio_buffer_is_active(insert_buffer)) 12613909fab5SLars-Peter Clausen insert_buffer = NULL; 12623909fab5SLars-Peter Clausen 12633909fab5SLars-Peter Clausen if (remove_buffer && !iio_buffer_is_active(remove_buffer)) 12643909fab5SLars-Peter Clausen remove_buffer = NULL; 12653909fab5SLars-Peter Clausen 12663909fab5SLars-Peter Clausen if (!insert_buffer && !remove_buffer) { 12673909fab5SLars-Peter Clausen ret = 0; 12683909fab5SLars-Peter Clausen goto out_unlock; 12693909fab5SLars-Peter Clausen } 12703909fab5SLars-Peter Clausen 1271a9519456SLars-Peter Clausen if (indio_dev->info == NULL) { 1272a9519456SLars-Peter Clausen ret = -ENODEV; 1273a9519456SLars-Peter Clausen goto out_unlock; 1274a9519456SLars-Peter Clausen } 1275a9519456SLars-Peter Clausen 1276a9519456SLars-Peter Clausen ret = __iio_update_buffers(indio_dev, insert_buffer, remove_buffer); 1277a9519456SLars-Peter Clausen 1278a9519456SLars-Peter Clausen out_unlock: 1279a9519456SLars-Peter Clausen mutex_unlock(&indio_dev->mlock); 1280b804e2b7SJonathan Cameron mutex_unlock(&iio_dev_opaque->info_exist_lock); 1281a9519456SLars-Peter Clausen 1282a9519456SLars-Peter Clausen return ret; 1283a9519456SLars-Peter Clausen } 128484b36ce5SJonathan Cameron EXPORT_SYMBOL_GPL(iio_update_buffers); 128584b36ce5SJonathan Cameron 1286623d74e3SLars-Peter Clausen void iio_disable_all_buffers(struct iio_dev *indio_dev) 1287623d74e3SLars-Peter Clausen { 1288623d74e3SLars-Peter Clausen iio_disable_buffers(indio_dev); 12891250186aSLars-Peter Clausen iio_buffer_deactivate_all(indio_dev); 1290623d74e3SLars-Peter Clausen } 1291623d74e3SLars-Peter Clausen 12929cf0b618SJoe Simmons-Talbott static ssize_t enable_store(struct device *dev, struct device_attribute *attr, 12939cf0b618SJoe Simmons-Talbott const char *buf, size_t len) 129484b36ce5SJonathan Cameron { 129584b36ce5SJonathan Cameron int ret; 129684b36ce5SJonathan Cameron bool requested_state; 129784b36ce5SJonathan Cameron struct iio_dev *indio_dev = dev_to_iio_dev(dev); 129815097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 129984b36ce5SJonathan Cameron bool inlist; 130084b36ce5SJonathan Cameron 130174f582ecSLars-Peter Clausen ret = kstrtobool(buf, &requested_state); 130284b36ce5SJonathan Cameron if (ret < 0) 130384b36ce5SJonathan Cameron return ret; 130484b36ce5SJonathan Cameron 130584b36ce5SJonathan Cameron mutex_lock(&indio_dev->mlock); 130684b36ce5SJonathan Cameron 130784b36ce5SJonathan Cameron /* Find out if it is in the list */ 1308ff3f7e04SAlexandru Ardelean inlist = iio_buffer_is_active(buffer); 130984b36ce5SJonathan Cameron /* Already in desired state */ 131084b36ce5SJonathan Cameron if (inlist == requested_state) 131184b36ce5SJonathan Cameron goto done; 131284b36ce5SJonathan Cameron 131384b36ce5SJonathan Cameron if (requested_state) 1314ff3f7e04SAlexandru Ardelean ret = __iio_update_buffers(indio_dev, buffer, NULL); 131584b36ce5SJonathan Cameron else 1316ff3f7e04SAlexandru Ardelean ret = __iio_update_buffers(indio_dev, NULL, buffer); 131784b36ce5SJonathan Cameron 131884b36ce5SJonathan Cameron done: 131984b36ce5SJonathan Cameron mutex_unlock(&indio_dev->mlock); 132084b36ce5SJonathan Cameron return (ret < 0) ? ret : len; 132184b36ce5SJonathan Cameron } 132284b36ce5SJonathan Cameron 13239cf0b618SJoe Simmons-Talbott static ssize_t watermark_show(struct device *dev, struct device_attribute *attr, 132437d34556SJosselin Costanzi char *buf) 132537d34556SJosselin Costanzi { 132615097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 132737d34556SJosselin Costanzi 132883ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%u\n", buffer->watermark); 132937d34556SJosselin Costanzi } 133037d34556SJosselin Costanzi 13319cf0b618SJoe Simmons-Talbott static ssize_t watermark_store(struct device *dev, 133237d34556SJosselin Costanzi struct device_attribute *attr, 13339cf0b618SJoe Simmons-Talbott const char *buf, size_t len) 133437d34556SJosselin Costanzi { 133537d34556SJosselin Costanzi struct iio_dev *indio_dev = dev_to_iio_dev(dev); 133615097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 133737d34556SJosselin Costanzi unsigned int val; 133837d34556SJosselin Costanzi int ret; 133937d34556SJosselin Costanzi 134037d34556SJosselin Costanzi ret = kstrtouint(buf, 10, &val); 134137d34556SJosselin Costanzi if (ret) 134237d34556SJosselin Costanzi return ret; 134337d34556SJosselin Costanzi if (!val) 134437d34556SJosselin Costanzi return -EINVAL; 134537d34556SJosselin Costanzi 134637d34556SJosselin Costanzi mutex_lock(&indio_dev->mlock); 134737d34556SJosselin Costanzi 134837d34556SJosselin Costanzi if (val > buffer->length) { 134937d34556SJosselin Costanzi ret = -EINVAL; 135037d34556SJosselin Costanzi goto out; 135137d34556SJosselin Costanzi } 135237d34556SJosselin Costanzi 1353ff3f7e04SAlexandru Ardelean if (iio_buffer_is_active(buffer)) { 135437d34556SJosselin Costanzi ret = -EBUSY; 135537d34556SJosselin Costanzi goto out; 135637d34556SJosselin Costanzi } 135737d34556SJosselin Costanzi 135837d34556SJosselin Costanzi buffer->watermark = val; 135937d34556SJosselin Costanzi out: 136037d34556SJosselin Costanzi mutex_unlock(&indio_dev->mlock); 136137d34556SJosselin Costanzi 136237d34556SJosselin Costanzi return ret ? ret : len; 136337d34556SJosselin Costanzi } 136437d34556SJosselin Costanzi 13659cf0b618SJoe Simmons-Talbott static ssize_t data_available_show(struct device *dev, 13669cf0b618SJoe Simmons-Talbott struct device_attribute *attr, char *buf) 1367350f6c75SMatt Fornero { 136815097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 1369350f6c75SMatt Fornero 137083ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%zu\n", iio_buffer_data_available(buffer)); 1371350f6c75SMatt Fornero } 1372350f6c75SMatt Fornero 13739eeee3b0SMihail Chindris static ssize_t direction_show(struct device *dev, 13749eeee3b0SMihail Chindris struct device_attribute *attr, 13759eeee3b0SMihail Chindris char *buf) 13769eeee3b0SMihail Chindris { 13779eeee3b0SMihail Chindris struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 13789eeee3b0SMihail Chindris 13799eeee3b0SMihail Chindris switch (buffer->direction) { 13809eeee3b0SMihail Chindris case IIO_BUFFER_DIRECTION_IN: 1381c3154defSLars-Peter Clausen return sysfs_emit(buf, "in\n"); 13829eeee3b0SMihail Chindris case IIO_BUFFER_DIRECTION_OUT: 1383c3154defSLars-Peter Clausen return sysfs_emit(buf, "out\n"); 13849eeee3b0SMihail Chindris default: 13859eeee3b0SMihail Chindris return -EINVAL; 13869eeee3b0SMihail Chindris } 13879eeee3b0SMihail Chindris } 13889eeee3b0SMihail Chindris 13899cf0b618SJoe Simmons-Talbott static DEVICE_ATTR_RW(length); 13909cf0b618SJoe Simmons-Talbott static struct device_attribute dev_attr_length_ro = __ATTR_RO(length); 13919cf0b618SJoe Simmons-Talbott static DEVICE_ATTR_RW(enable); 13929cf0b618SJoe Simmons-Talbott static DEVICE_ATTR_RW(watermark); 13939cf0b618SJoe Simmons-Talbott static struct device_attribute dev_attr_watermark_ro = __ATTR_RO(watermark); 13949cf0b618SJoe Simmons-Talbott static DEVICE_ATTR_RO(data_available); 13959eeee3b0SMihail Chindris static DEVICE_ATTR_RO(direction); 139608e7e0adSLars-Peter Clausen 13979eeee3b0SMihail Chindris /* 13989eeee3b0SMihail Chindris * When adding new attributes here, put the at the end, at least until 13999eeee3b0SMihail Chindris * the code that handles the length/length_ro & watermark/watermark_ro 14009eeee3b0SMihail Chindris * assignments gets cleaned up. Otherwise these can create some weird 14019eeee3b0SMihail Chindris * duplicate attributes errors under some setups. 14029eeee3b0SMihail Chindris */ 14036da9b382SOctavian Purdila static struct attribute *iio_buffer_attrs[] = { 14046da9b382SOctavian Purdila &dev_attr_length.attr, 14056da9b382SOctavian Purdila &dev_attr_enable.attr, 140637d34556SJosselin Costanzi &dev_attr_watermark.attr, 1407350f6c75SMatt Fornero &dev_attr_data_available.attr, 14089eeee3b0SMihail Chindris &dev_attr_direction.attr, 14096da9b382SOctavian Purdila }; 14106da9b382SOctavian Purdila 141115097c7aSAlexandru Ardelean #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) 141215097c7aSAlexandru Ardelean 141315097c7aSAlexandru Ardelean static struct attribute *iio_buffer_wrap_attr(struct iio_buffer *buffer, 141415097c7aSAlexandru Ardelean struct attribute *attr) 141515097c7aSAlexandru Ardelean { 141615097c7aSAlexandru Ardelean struct device_attribute *dattr = to_dev_attr(attr); 141715097c7aSAlexandru Ardelean struct iio_dev_attr *iio_attr; 141815097c7aSAlexandru Ardelean 141915097c7aSAlexandru Ardelean iio_attr = kzalloc(sizeof(*iio_attr), GFP_KERNEL); 142015097c7aSAlexandru Ardelean if (!iio_attr) 142115097c7aSAlexandru Ardelean return NULL; 142215097c7aSAlexandru Ardelean 142315097c7aSAlexandru Ardelean iio_attr->buffer = buffer; 142415097c7aSAlexandru Ardelean memcpy(&iio_attr->dev_attr, dattr, sizeof(iio_attr->dev_attr)); 142515097c7aSAlexandru Ardelean iio_attr->dev_attr.attr.name = kstrdup_const(attr->name, GFP_KERNEL); 14262c0ad3f0SYang Yingliang if (!iio_attr->dev_attr.attr.name) { 14272c0ad3f0SYang Yingliang kfree(iio_attr); 14282c0ad3f0SYang Yingliang return NULL; 14292c0ad3f0SYang Yingliang } 14302c0ad3f0SYang Yingliang 1431ca3e7d52SAlexandru Ardelean sysfs_attr_init(&iio_attr->dev_attr.attr); 143215097c7aSAlexandru Ardelean 143315097c7aSAlexandru Ardelean list_add(&iio_attr->l, &buffer->buffer_attr_list); 143415097c7aSAlexandru Ardelean 143515097c7aSAlexandru Ardelean return &iio_attr->dev_attr.attr; 143615097c7aSAlexandru Ardelean } 143715097c7aSAlexandru Ardelean 1438d9a62574SAlexandru Ardelean static int iio_buffer_register_legacy_sysfs_groups(struct iio_dev *indio_dev, 1439d9a62574SAlexandru Ardelean struct attribute **buffer_attrs, 1440d9a62574SAlexandru Ardelean int buffer_attrcount, 1441d9a62574SAlexandru Ardelean int scan_el_attrcount) 1442d9a62574SAlexandru Ardelean { 1443d9a62574SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1444d9a62574SAlexandru Ardelean struct attribute_group *group; 1445d9a62574SAlexandru Ardelean struct attribute **attrs; 1446d9a62574SAlexandru Ardelean int ret; 1447d9a62574SAlexandru Ardelean 1448d9a62574SAlexandru Ardelean attrs = kcalloc(buffer_attrcount + 1, sizeof(*attrs), GFP_KERNEL); 1449d9a62574SAlexandru Ardelean if (!attrs) 1450d9a62574SAlexandru Ardelean return -ENOMEM; 1451d9a62574SAlexandru Ardelean 1452d9a62574SAlexandru Ardelean memcpy(attrs, buffer_attrs, buffer_attrcount * sizeof(*attrs)); 1453d9a62574SAlexandru Ardelean 1454d9a62574SAlexandru Ardelean group = &iio_dev_opaque->legacy_buffer_group; 1455d9a62574SAlexandru Ardelean group->attrs = attrs; 1456d9a62574SAlexandru Ardelean group->name = "buffer"; 1457d9a62574SAlexandru Ardelean 1458d9a62574SAlexandru Ardelean ret = iio_device_register_sysfs_group(indio_dev, group); 1459d9a62574SAlexandru Ardelean if (ret) 1460d9a62574SAlexandru Ardelean goto error_free_buffer_attrs; 1461d9a62574SAlexandru Ardelean 1462d9a62574SAlexandru Ardelean attrs = kcalloc(scan_el_attrcount + 1, sizeof(*attrs), GFP_KERNEL); 1463d9a62574SAlexandru Ardelean if (!attrs) { 1464d9a62574SAlexandru Ardelean ret = -ENOMEM; 1465d9a62574SAlexandru Ardelean goto error_free_buffer_attrs; 1466d9a62574SAlexandru Ardelean } 1467d9a62574SAlexandru Ardelean 1468d9a62574SAlexandru Ardelean memcpy(attrs, &buffer_attrs[buffer_attrcount], 1469d9a62574SAlexandru Ardelean scan_el_attrcount * sizeof(*attrs)); 1470d9a62574SAlexandru Ardelean 1471d9a62574SAlexandru Ardelean group = &iio_dev_opaque->legacy_scan_el_group; 1472d9a62574SAlexandru Ardelean group->attrs = attrs; 1473d9a62574SAlexandru Ardelean group->name = "scan_elements"; 1474d9a62574SAlexandru Ardelean 1475d9a62574SAlexandru Ardelean ret = iio_device_register_sysfs_group(indio_dev, group); 1476d9a62574SAlexandru Ardelean if (ret) 1477d9a62574SAlexandru Ardelean goto error_free_scan_el_attrs; 1478d9a62574SAlexandru Ardelean 1479d9a62574SAlexandru Ardelean return 0; 1480d9a62574SAlexandru Ardelean 1481d9a62574SAlexandru Ardelean error_free_scan_el_attrs: 1482d9a62574SAlexandru Ardelean kfree(iio_dev_opaque->legacy_scan_el_group.attrs); 1483604faf9aSYang Yingliang error_free_buffer_attrs: 1484604faf9aSYang Yingliang kfree(iio_dev_opaque->legacy_buffer_group.attrs); 1485d9a62574SAlexandru Ardelean 1486d9a62574SAlexandru Ardelean return ret; 1487d9a62574SAlexandru Ardelean } 1488d9a62574SAlexandru Ardelean 1489d9a62574SAlexandru Ardelean static void iio_buffer_unregister_legacy_sysfs_groups(struct iio_dev *indio_dev) 1490d9a62574SAlexandru Ardelean { 1491d9a62574SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1492d9a62574SAlexandru Ardelean 1493d9a62574SAlexandru Ardelean kfree(iio_dev_opaque->legacy_buffer_group.attrs); 1494d9a62574SAlexandru Ardelean kfree(iio_dev_opaque->legacy_scan_el_group.attrs); 1495d9a62574SAlexandru Ardelean } 1496d9a62574SAlexandru Ardelean 1497f73f7f4dSAlexandru Ardelean static int iio_buffer_chrdev_release(struct inode *inode, struct file *filep) 1498f73f7f4dSAlexandru Ardelean { 1499f73f7f4dSAlexandru Ardelean struct iio_dev_buffer_pair *ib = filep->private_data; 1500f73f7f4dSAlexandru Ardelean struct iio_dev *indio_dev = ib->indio_dev; 1501f73f7f4dSAlexandru Ardelean struct iio_buffer *buffer = ib->buffer; 1502f73f7f4dSAlexandru Ardelean 1503f73f7f4dSAlexandru Ardelean wake_up(&buffer->pollq); 1504f73f7f4dSAlexandru Ardelean 1505f73f7f4dSAlexandru Ardelean kfree(ib); 1506f73f7f4dSAlexandru Ardelean clear_bit(IIO_BUSY_BIT_POS, &buffer->flags); 1507f73f7f4dSAlexandru Ardelean iio_device_put(indio_dev); 1508f73f7f4dSAlexandru Ardelean 1509f73f7f4dSAlexandru Ardelean return 0; 1510f73f7f4dSAlexandru Ardelean } 1511f73f7f4dSAlexandru Ardelean 1512f73f7f4dSAlexandru Ardelean static const struct file_operations iio_buffer_chrdev_fileops = { 1513f73f7f4dSAlexandru Ardelean .owner = THIS_MODULE, 1514f73f7f4dSAlexandru Ardelean .llseek = noop_llseek, 1515f73f7f4dSAlexandru Ardelean .read = iio_buffer_read, 15169eeee3b0SMihail Chindris .write = iio_buffer_write, 1517f73f7f4dSAlexandru Ardelean .poll = iio_buffer_poll, 1518f73f7f4dSAlexandru Ardelean .release = iio_buffer_chrdev_release, 1519f73f7f4dSAlexandru Ardelean }; 1520f73f7f4dSAlexandru Ardelean 1521f73f7f4dSAlexandru Ardelean static long iio_device_buffer_getfd(struct iio_dev *indio_dev, unsigned long arg) 1522f73f7f4dSAlexandru Ardelean { 1523f73f7f4dSAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1524f73f7f4dSAlexandru Ardelean int __user *ival = (int __user *)arg; 1525f73f7f4dSAlexandru Ardelean struct iio_dev_buffer_pair *ib; 1526f73f7f4dSAlexandru Ardelean struct iio_buffer *buffer; 1527f73f7f4dSAlexandru Ardelean int fd, idx, ret; 1528f73f7f4dSAlexandru Ardelean 1529f73f7f4dSAlexandru Ardelean if (copy_from_user(&idx, ival, sizeof(idx))) 1530f73f7f4dSAlexandru Ardelean return -EFAULT; 1531f73f7f4dSAlexandru Ardelean 1532f73f7f4dSAlexandru Ardelean if (idx >= iio_dev_opaque->attached_buffers_cnt) 1533f73f7f4dSAlexandru Ardelean return -ENODEV; 1534f73f7f4dSAlexandru Ardelean 1535f73f7f4dSAlexandru Ardelean iio_device_get(indio_dev); 1536f73f7f4dSAlexandru Ardelean 1537f73f7f4dSAlexandru Ardelean buffer = iio_dev_opaque->attached_buffers[idx]; 1538f73f7f4dSAlexandru Ardelean 1539f73f7f4dSAlexandru Ardelean if (test_and_set_bit(IIO_BUSY_BIT_POS, &buffer->flags)) { 1540f73f7f4dSAlexandru Ardelean ret = -EBUSY; 1541f73f7f4dSAlexandru Ardelean goto error_iio_dev_put; 1542f73f7f4dSAlexandru Ardelean } 1543f73f7f4dSAlexandru Ardelean 1544f73f7f4dSAlexandru Ardelean ib = kzalloc(sizeof(*ib), GFP_KERNEL); 1545f73f7f4dSAlexandru Ardelean if (!ib) { 1546f73f7f4dSAlexandru Ardelean ret = -ENOMEM; 1547f73f7f4dSAlexandru Ardelean goto error_clear_busy_bit; 1548f73f7f4dSAlexandru Ardelean } 1549f73f7f4dSAlexandru Ardelean 1550f73f7f4dSAlexandru Ardelean ib->indio_dev = indio_dev; 1551f73f7f4dSAlexandru Ardelean ib->buffer = buffer; 1552f73f7f4dSAlexandru Ardelean 1553f73f7f4dSAlexandru Ardelean fd = anon_inode_getfd("iio:buffer", &iio_buffer_chrdev_fileops, 1554f73f7f4dSAlexandru Ardelean ib, O_RDWR | O_CLOEXEC); 1555f73f7f4dSAlexandru Ardelean if (fd < 0) { 1556f73f7f4dSAlexandru Ardelean ret = fd; 1557f73f7f4dSAlexandru Ardelean goto error_free_ib; 1558f73f7f4dSAlexandru Ardelean } 1559f73f7f4dSAlexandru Ardelean 1560f73f7f4dSAlexandru Ardelean if (copy_to_user(ival, &fd, sizeof(fd))) { 1561c72ea205SMathias Krause /* 1562c72ea205SMathias Krause * "Leak" the fd, as there's not much we can do about this 1563c72ea205SMathias Krause * anyway. 'fd' might have been closed already, as 1564c72ea205SMathias Krause * anon_inode_getfd() called fd_install() on it, which made 1565c72ea205SMathias Krause * it reachable by userland. 1566c72ea205SMathias Krause * 1567c72ea205SMathias Krause * Instead of allowing a malicious user to play tricks with 1568c72ea205SMathias Krause * us, rely on the process exit path to do any necessary 1569c72ea205SMathias Krause * cleanup, as in releasing the file, if still needed. 1570c72ea205SMathias Krause */ 1571c72ea205SMathias Krause return -EFAULT; 1572f73f7f4dSAlexandru Ardelean } 1573f73f7f4dSAlexandru Ardelean 15744c822244SAlexandru Ardelean return 0; 1575f73f7f4dSAlexandru Ardelean 1576f73f7f4dSAlexandru Ardelean error_free_ib: 1577f73f7f4dSAlexandru Ardelean kfree(ib); 1578f73f7f4dSAlexandru Ardelean error_clear_busy_bit: 1579f73f7f4dSAlexandru Ardelean clear_bit(IIO_BUSY_BIT_POS, &buffer->flags); 1580f73f7f4dSAlexandru Ardelean error_iio_dev_put: 1581f73f7f4dSAlexandru Ardelean iio_device_put(indio_dev); 1582f73f7f4dSAlexandru Ardelean return ret; 1583f73f7f4dSAlexandru Ardelean } 1584f73f7f4dSAlexandru Ardelean 1585f73f7f4dSAlexandru Ardelean static long iio_device_buffer_ioctl(struct iio_dev *indio_dev, struct file *filp, 1586f73f7f4dSAlexandru Ardelean unsigned int cmd, unsigned long arg) 1587f73f7f4dSAlexandru Ardelean { 1588f73f7f4dSAlexandru Ardelean switch (cmd) { 1589f73f7f4dSAlexandru Ardelean case IIO_BUFFER_GET_FD_IOCTL: 1590f73f7f4dSAlexandru Ardelean return iio_device_buffer_getfd(indio_dev, arg); 1591f73f7f4dSAlexandru Ardelean default: 1592f73f7f4dSAlexandru Ardelean return IIO_IOCTL_UNHANDLED; 1593f73f7f4dSAlexandru Ardelean } 1594f73f7f4dSAlexandru Ardelean } 1595f73f7f4dSAlexandru Ardelean 1596e16e0a77SAlexandru Ardelean static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, 1597d9a62574SAlexandru Ardelean struct iio_dev *indio_dev, 1598d9a62574SAlexandru Ardelean int index) 1599d967cb6bSLars-Peter Clausen { 160062f4f36cSJonathan Cameron struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1601d967cb6bSLars-Peter Clausen struct iio_dev_attr *p; 1602d967cb6bSLars-Peter Clausen struct attribute **attr; 1603e2b4d7acSAlexandru Ardelean int ret, i, attrn, scan_el_attrcount, buffer_attrcount; 1604d967cb6bSLars-Peter Clausen const struct iio_chan_spec *channels; 1605d967cb6bSLars-Peter Clausen 1606e2b4d7acSAlexandru Ardelean buffer_attrcount = 0; 160708e7e0adSLars-Peter Clausen if (buffer->attrs) { 1608e2b4d7acSAlexandru Ardelean while (buffer->attrs[buffer_attrcount] != NULL) 1609e2b4d7acSAlexandru Ardelean buffer_attrcount++; 161008e7e0adSLars-Peter Clausen } 161108e7e0adSLars-Peter Clausen 1612e2b4d7acSAlexandru Ardelean scan_el_attrcount = 0; 161315097c7aSAlexandru Ardelean INIT_LIST_HEAD(&buffer->buffer_attr_list); 1614d967cb6bSLars-Peter Clausen channels = indio_dev->channels; 1615d967cb6bSLars-Peter Clausen if (channels) { 1616d967cb6bSLars-Peter Clausen /* new magic */ 1617d967cb6bSLars-Peter Clausen for (i = 0; i < indio_dev->num_channels; i++) { 1618d967cb6bSLars-Peter Clausen if (channels[i].scan_index < 0) 1619d967cb6bSLars-Peter Clausen continue; 1620d967cb6bSLars-Peter Clausen 1621fd542c5eSMarek Vasut /* Verify that sample bits fit into storage */ 1622fd542c5eSMarek Vasut if (channels[i].scan_type.storagebits < 1623fd542c5eSMarek Vasut channels[i].scan_type.realbits + 1624fd542c5eSMarek Vasut channels[i].scan_type.shift) { 1625fd542c5eSMarek Vasut dev_err(&indio_dev->dev, 1626fd542c5eSMarek Vasut "Channel %d storagebits (%d) < shifted realbits (%d + %d)\n", 1627fd542c5eSMarek Vasut i, channels[i].scan_type.storagebits, 1628fd542c5eSMarek Vasut channels[i].scan_type.realbits, 1629fd542c5eSMarek Vasut channels[i].scan_type.shift); 1630fd542c5eSMarek Vasut ret = -EINVAL; 1631fd542c5eSMarek Vasut goto error_cleanup_dynamic; 1632fd542c5eSMarek Vasut } 1633fd542c5eSMarek Vasut 1634ff3f7e04SAlexandru Ardelean ret = iio_buffer_add_channel_sysfs(indio_dev, buffer, 1635d967cb6bSLars-Peter Clausen &channels[i]); 1636d967cb6bSLars-Peter Clausen if (ret < 0) 1637d967cb6bSLars-Peter Clausen goto error_cleanup_dynamic; 1638e2b4d7acSAlexandru Ardelean scan_el_attrcount += ret; 1639d967cb6bSLars-Peter Clausen if (channels[i].type == IIO_TIMESTAMP) 164062f4f36cSJonathan Cameron iio_dev_opaque->scan_index_timestamp = 1641d967cb6bSLars-Peter Clausen channels[i].scan_index; 1642d967cb6bSLars-Peter Clausen } 1643d967cb6bSLars-Peter Clausen if (indio_dev->masklength && buffer->scan_mask == NULL) { 16443862828aSAndy Shevchenko buffer->scan_mask = bitmap_zalloc(indio_dev->masklength, 1645d967cb6bSLars-Peter Clausen GFP_KERNEL); 1646d967cb6bSLars-Peter Clausen if (buffer->scan_mask == NULL) { 1647d967cb6bSLars-Peter Clausen ret = -ENOMEM; 1648d967cb6bSLars-Peter Clausen goto error_cleanup_dynamic; 1649d967cb6bSLars-Peter Clausen } 1650d967cb6bSLars-Peter Clausen } 1651d967cb6bSLars-Peter Clausen } 1652d967cb6bSLars-Peter Clausen 1653d9a62574SAlexandru Ardelean attrn = buffer_attrcount + scan_el_attrcount + ARRAY_SIZE(iio_buffer_attrs); 1654d9a62574SAlexandru Ardelean attr = kcalloc(attrn + 1, sizeof(*attr), GFP_KERNEL); 1655e2b4d7acSAlexandru Ardelean if (!attr) { 1656e2b4d7acSAlexandru Ardelean ret = -ENOMEM; 1657e2b4d7acSAlexandru Ardelean goto error_free_scan_mask; 1658e2b4d7acSAlexandru Ardelean } 1659e2b4d7acSAlexandru Ardelean 1660e2b4d7acSAlexandru Ardelean memcpy(attr, iio_buffer_attrs, sizeof(iio_buffer_attrs)); 1661e2b4d7acSAlexandru Ardelean if (!buffer->access->set_length) 1662e2b4d7acSAlexandru Ardelean attr[0] = &dev_attr_length_ro.attr; 1663e2b4d7acSAlexandru Ardelean 1664e2b4d7acSAlexandru Ardelean if (buffer->access->flags & INDIO_BUFFER_FLAG_FIXED_WATERMARK) 1665e2b4d7acSAlexandru Ardelean attr[2] = &dev_attr_watermark_ro.attr; 1666e2b4d7acSAlexandru Ardelean 1667e2b4d7acSAlexandru Ardelean if (buffer->attrs) 1668e2b4d7acSAlexandru Ardelean memcpy(&attr[ARRAY_SIZE(iio_buffer_attrs)], buffer->attrs, 1669e2b4d7acSAlexandru Ardelean sizeof(struct attribute *) * buffer_attrcount); 1670e2b4d7acSAlexandru Ardelean 1671e2b4d7acSAlexandru Ardelean buffer_attrcount += ARRAY_SIZE(iio_buffer_attrs); 16729a2ff800SYang Yingliang buffer->buffer_group.attrs = attr; 1673e2b4d7acSAlexandru Ardelean 167415097c7aSAlexandru Ardelean for (i = 0; i < buffer_attrcount; i++) { 167515097c7aSAlexandru Ardelean struct attribute *wrapped; 1676d9a62574SAlexandru Ardelean 167715097c7aSAlexandru Ardelean wrapped = iio_buffer_wrap_attr(buffer, attr[i]); 167815097c7aSAlexandru Ardelean if (!wrapped) { 167915097c7aSAlexandru Ardelean ret = -ENOMEM; 16809a2ff800SYang Yingliang goto error_free_buffer_attrs; 168115097c7aSAlexandru Ardelean } 168215097c7aSAlexandru Ardelean attr[i] = wrapped; 168315097c7aSAlexandru Ardelean } 168415097c7aSAlexandru Ardelean 168515097c7aSAlexandru Ardelean attrn = 0; 168615097c7aSAlexandru Ardelean list_for_each_entry(p, &buffer->buffer_attr_list, l) 1687d9a62574SAlexandru Ardelean attr[attrn++] = &p->dev_attr.attr; 1688d9a62574SAlexandru Ardelean 1689d9a62574SAlexandru Ardelean buffer->buffer_group.name = kasprintf(GFP_KERNEL, "buffer%d", index); 1690d9a62574SAlexandru Ardelean if (!buffer->buffer_group.name) { 1691d9a62574SAlexandru Ardelean ret = -ENOMEM; 1692d9a62574SAlexandru Ardelean goto error_free_buffer_attrs; 1693d9a62574SAlexandru Ardelean } 1694d9a62574SAlexandru Ardelean 1695e2b4d7acSAlexandru Ardelean ret = iio_device_register_sysfs_group(indio_dev, &buffer->buffer_group); 1696e2b4d7acSAlexandru Ardelean if (ret) 1697d9a62574SAlexandru Ardelean goto error_free_buffer_attr_group_name; 1698e2b4d7acSAlexandru Ardelean 1699d9a62574SAlexandru Ardelean /* we only need to register the legacy groups for the first buffer */ 1700d9a62574SAlexandru Ardelean if (index > 0) 1701d9a62574SAlexandru Ardelean return 0; 1702d967cb6bSLars-Peter Clausen 1703d9a62574SAlexandru Ardelean ret = iio_buffer_register_legacy_sysfs_groups(indio_dev, attr, 1704d9a62574SAlexandru Ardelean buffer_attrcount, 1705d9a62574SAlexandru Ardelean scan_el_attrcount); 170632f17172SAlexandru Ardelean if (ret) 1707d9a62574SAlexandru Ardelean goto error_free_buffer_attr_group_name; 1708d967cb6bSLars-Peter Clausen 1709d967cb6bSLars-Peter Clausen return 0; 1710d967cb6bSLars-Peter Clausen 1711d9a62574SAlexandru Ardelean error_free_buffer_attr_group_name: 1712d9a62574SAlexandru Ardelean kfree(buffer->buffer_group.name); 1713e2b4d7acSAlexandru Ardelean error_free_buffer_attrs: 1714e2b4d7acSAlexandru Ardelean kfree(buffer->buffer_group.attrs); 1715d967cb6bSLars-Peter Clausen error_free_scan_mask: 17163862828aSAndy Shevchenko bitmap_free(buffer->scan_mask); 1717d967cb6bSLars-Peter Clausen error_cleanup_dynamic: 171815097c7aSAlexandru Ardelean iio_free_chan_devattr_list(&buffer->buffer_attr_list); 1719d967cb6bSLars-Peter Clausen 1720d967cb6bSLars-Peter Clausen return ret; 1721d967cb6bSLars-Peter Clausen } 1722d967cb6bSLars-Peter Clausen 1723486a2508SYang Yingliang static void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer, 1724486a2508SYang Yingliang struct iio_dev *indio_dev, 1725486a2508SYang Yingliang int index) 17260224af85SAlexandru Ardelean { 1727486a2508SYang Yingliang if (index == 0) 1728486a2508SYang Yingliang iio_buffer_unregister_legacy_sysfs_groups(indio_dev); 17290224af85SAlexandru Ardelean bitmap_free(buffer->scan_mask); 17300224af85SAlexandru Ardelean kfree(buffer->buffer_group.name); 17310224af85SAlexandru Ardelean kfree(buffer->buffer_group.attrs); 17320224af85SAlexandru Ardelean iio_free_chan_devattr_list(&buffer->buffer_attr_list); 17330224af85SAlexandru Ardelean } 17340224af85SAlexandru Ardelean 1735ee708e6bSAlexandru Ardelean int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev) 1736e16e0a77SAlexandru Ardelean { 1737ee708e6bSAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1738e16e0a77SAlexandru Ardelean const struct iio_chan_spec *channels; 1739ee708e6bSAlexandru Ardelean struct iio_buffer *buffer; 1740e5cc9840SAndy Shevchenko int ret, i, idx; 1741f73f7f4dSAlexandru Ardelean size_t sz; 1742e16e0a77SAlexandru Ardelean 1743e16e0a77SAlexandru Ardelean channels = indio_dev->channels; 1744e16e0a77SAlexandru Ardelean if (channels) { 1745e16e0a77SAlexandru Ardelean int ml = indio_dev->masklength; 1746e16e0a77SAlexandru Ardelean 1747e16e0a77SAlexandru Ardelean for (i = 0; i < indio_dev->num_channels; i++) 1748e16e0a77SAlexandru Ardelean ml = max(ml, channels[i].scan_index + 1); 1749e16e0a77SAlexandru Ardelean indio_dev->masklength = ml; 1750e16e0a77SAlexandru Ardelean } 1751e16e0a77SAlexandru Ardelean 1752ee708e6bSAlexandru Ardelean if (!iio_dev_opaque->attached_buffers_cnt) 1753e16e0a77SAlexandru Ardelean return 0; 1754e16e0a77SAlexandru Ardelean 1755e5cc9840SAndy Shevchenko for (idx = 0; idx < iio_dev_opaque->attached_buffers_cnt; idx++) { 1756e5cc9840SAndy Shevchenko buffer = iio_dev_opaque->attached_buffers[idx]; 1757e5cc9840SAndy Shevchenko ret = __iio_buffer_alloc_sysfs_and_mask(buffer, indio_dev, idx); 1758e5cc9840SAndy Shevchenko if (ret) 1759ee708e6bSAlexandru Ardelean goto error_unwind_sysfs_and_mask; 1760ee708e6bSAlexandru Ardelean } 1761f73f7f4dSAlexandru Ardelean 1762f73f7f4dSAlexandru Ardelean sz = sizeof(*(iio_dev_opaque->buffer_ioctl_handler)); 1763f73f7f4dSAlexandru Ardelean iio_dev_opaque->buffer_ioctl_handler = kzalloc(sz, GFP_KERNEL); 1764f73f7f4dSAlexandru Ardelean if (!iio_dev_opaque->buffer_ioctl_handler) { 1765f73f7f4dSAlexandru Ardelean ret = -ENOMEM; 1766f73f7f4dSAlexandru Ardelean goto error_unwind_sysfs_and_mask; 1767f73f7f4dSAlexandru Ardelean } 1768f73f7f4dSAlexandru Ardelean 1769f73f7f4dSAlexandru Ardelean iio_dev_opaque->buffer_ioctl_handler->ioctl = iio_device_buffer_ioctl; 1770f73f7f4dSAlexandru Ardelean iio_device_ioctl_handler_register(indio_dev, 1771f73f7f4dSAlexandru Ardelean iio_dev_opaque->buffer_ioctl_handler); 1772e16e0a77SAlexandru Ardelean 1773ee708e6bSAlexandru Ardelean return 0; 1774ff3f7e04SAlexandru Ardelean 1775ee708e6bSAlexandru Ardelean error_unwind_sysfs_and_mask: 1776e5cc9840SAndy Shevchenko while (idx--) { 1777e5cc9840SAndy Shevchenko buffer = iio_dev_opaque->attached_buffers[idx]; 1778e5cc9840SAndy Shevchenko __iio_buffer_free_sysfs_and_mask(buffer, indio_dev, idx); 1779ee708e6bSAlexandru Ardelean } 1780ee708e6bSAlexandru Ardelean return ret; 1781ee708e6bSAlexandru Ardelean } 1782ee708e6bSAlexandru Ardelean 1783ee708e6bSAlexandru Ardelean void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev) 1784ee708e6bSAlexandru Ardelean { 1785ee708e6bSAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1786ee708e6bSAlexandru Ardelean struct iio_buffer *buffer; 1787ee708e6bSAlexandru Ardelean int i; 1788ee708e6bSAlexandru Ardelean 1789ee708e6bSAlexandru Ardelean if (!iio_dev_opaque->attached_buffers_cnt) 1790d967cb6bSLars-Peter Clausen return; 1791d967cb6bSLars-Peter Clausen 1792f73f7f4dSAlexandru Ardelean iio_device_ioctl_handler_unregister(iio_dev_opaque->buffer_ioctl_handler); 1793f73f7f4dSAlexandru Ardelean kfree(iio_dev_opaque->buffer_ioctl_handler); 1794f73f7f4dSAlexandru Ardelean 1795ee708e6bSAlexandru Ardelean for (i = iio_dev_opaque->attached_buffers_cnt - 1; i >= 0; i--) { 1796ee708e6bSAlexandru Ardelean buffer = iio_dev_opaque->attached_buffers[i]; 1797486a2508SYang Yingliang __iio_buffer_free_sysfs_and_mask(buffer, indio_dev, i); 1798d967cb6bSLars-Peter Clausen } 1799ee708e6bSAlexandru Ardelean } 1800ee708e6bSAlexandru Ardelean 1801a980e046SJonathan Cameron /** 180281636632SLars-Peter Clausen * iio_validate_scan_mask_onehot() - Validates that exactly one channel is selected 180381636632SLars-Peter Clausen * @indio_dev: the iio device 180481636632SLars-Peter Clausen * @mask: scan mask to be checked 180581636632SLars-Peter Clausen * 180681636632SLars-Peter Clausen * Return true if exactly one bit is set in the scan mask, false otherwise. It 180781636632SLars-Peter Clausen * can be used for devices where only one channel can be active for sampling at 180881636632SLars-Peter Clausen * a time. 180981636632SLars-Peter Clausen */ 181081636632SLars-Peter Clausen bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev, 181181636632SLars-Peter Clausen const unsigned long *mask) 181281636632SLars-Peter Clausen { 181381636632SLars-Peter Clausen return bitmap_weight(mask, indio_dev->masklength) == 1; 181481636632SLars-Peter Clausen } 181581636632SLars-Peter Clausen EXPORT_SYMBOL_GPL(iio_validate_scan_mask_onehot); 181681636632SLars-Peter Clausen 18175d65d920SLars-Peter Clausen static const void *iio_demux(struct iio_buffer *buffer, 18185d65d920SLars-Peter Clausen const void *datain) 1819a980e046SJonathan Cameron { 1820a980e046SJonathan Cameron struct iio_demux_table *t; 1821a980e046SJonathan Cameron 1822a980e046SJonathan Cameron if (list_empty(&buffer->demux_list)) 1823a980e046SJonathan Cameron return datain; 1824a980e046SJonathan Cameron list_for_each_entry(t, &buffer->demux_list, l) 1825a980e046SJonathan Cameron memcpy(buffer->demux_bounce + t->to, 1826a980e046SJonathan Cameron datain + t->from, t->length); 1827a980e046SJonathan Cameron 1828a980e046SJonathan Cameron return buffer->demux_bounce; 1829a980e046SJonathan Cameron } 1830a980e046SJonathan Cameron 18315d65d920SLars-Peter Clausen static int iio_push_to_buffer(struct iio_buffer *buffer, const void *data) 1832a980e046SJonathan Cameron { 18335d65d920SLars-Peter Clausen const void *dataout = iio_demux(buffer, data); 183437d34556SJosselin Costanzi int ret; 1835a980e046SJonathan Cameron 183637d34556SJosselin Costanzi ret = buffer->access->store_to(buffer, dataout); 183737d34556SJosselin Costanzi if (ret) 183837d34556SJosselin Costanzi return ret; 183937d34556SJosselin Costanzi 184037d34556SJosselin Costanzi /* 184137d34556SJosselin Costanzi * We can't just test for watermark to decide if we wake the poll queue 184237d34556SJosselin Costanzi * because read may request less samples than the watermark. 184337d34556SJosselin Costanzi */ 1844a9a08845SLinus Torvalds wake_up_interruptible_poll(&buffer->pollq, EPOLLIN | EPOLLRDNORM); 184537d34556SJosselin Costanzi return 0; 1846a980e046SJonathan Cameron } 1847a980e046SJonathan Cameron 1848315a19ecSJonathan Cameron /** 1849315a19ecSJonathan Cameron * iio_push_to_buffers() - push to a registered buffer. 1850315a19ecSJonathan Cameron * @indio_dev: iio_dev structure for device. 1851315a19ecSJonathan Cameron * @data: Full scan. 1852315a19ecSJonathan Cameron */ 18535d65d920SLars-Peter Clausen int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data) 185484b36ce5SJonathan Cameron { 18556a8c6b26SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 185684b36ce5SJonathan Cameron int ret; 185784b36ce5SJonathan Cameron struct iio_buffer *buf; 185884b36ce5SJonathan Cameron 18596a8c6b26SAlexandru Ardelean list_for_each_entry(buf, &iio_dev_opaque->buffer_list, buffer_list) { 186084b36ce5SJonathan Cameron ret = iio_push_to_buffer(buf, data); 186184b36ce5SJonathan Cameron if (ret < 0) 186284b36ce5SJonathan Cameron return ret; 186384b36ce5SJonathan Cameron } 186484b36ce5SJonathan Cameron 186584b36ce5SJonathan Cameron return 0; 186684b36ce5SJonathan Cameron } 186784b36ce5SJonathan Cameron EXPORT_SYMBOL_GPL(iio_push_to_buffers); 186884b36ce5SJonathan Cameron 18699e69c935SLars-Peter Clausen /** 187095ec3fdfSJonathan Cameron * iio_push_to_buffers_with_ts_unaligned() - push to registered buffer, 187195ec3fdfSJonathan Cameron * no alignment or space requirements. 187295ec3fdfSJonathan Cameron * @indio_dev: iio_dev structure for device. 187395ec3fdfSJonathan Cameron * @data: channel data excluding the timestamp. 187495ec3fdfSJonathan Cameron * @data_sz: size of data. 187595ec3fdfSJonathan Cameron * @timestamp: timestamp for the sample data. 187695ec3fdfSJonathan Cameron * 187795ec3fdfSJonathan Cameron * This special variant of iio_push_to_buffers_with_timestamp() does 187895ec3fdfSJonathan Cameron * not require space for the timestamp, or 8 byte alignment of data. 187995ec3fdfSJonathan Cameron * It does however require an allocation on first call and additional 188095ec3fdfSJonathan Cameron * copies on all calls, so should be avoided if possible. 188195ec3fdfSJonathan Cameron */ 188295ec3fdfSJonathan Cameron int iio_push_to_buffers_with_ts_unaligned(struct iio_dev *indio_dev, 188395ec3fdfSJonathan Cameron const void *data, 188495ec3fdfSJonathan Cameron size_t data_sz, 188595ec3fdfSJonathan Cameron int64_t timestamp) 188695ec3fdfSJonathan Cameron { 188795ec3fdfSJonathan Cameron struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 188895ec3fdfSJonathan Cameron 188995ec3fdfSJonathan Cameron /* 189095ec3fdfSJonathan Cameron * Conservative estimate - we can always safely copy the minimum 189195ec3fdfSJonathan Cameron * of either the data provided or the length of the destination buffer. 189295ec3fdfSJonathan Cameron * This relaxed limit allows the calling drivers to be lax about 189395ec3fdfSJonathan Cameron * tracking the size of the data they are pushing, at the cost of 189495ec3fdfSJonathan Cameron * unnecessary copying of padding. 189595ec3fdfSJonathan Cameron */ 189695ec3fdfSJonathan Cameron data_sz = min_t(size_t, indio_dev->scan_bytes, data_sz); 189795ec3fdfSJonathan Cameron if (iio_dev_opaque->bounce_buffer_size != indio_dev->scan_bytes) { 189895ec3fdfSJonathan Cameron void *bb; 189995ec3fdfSJonathan Cameron 190095ec3fdfSJonathan Cameron bb = devm_krealloc(&indio_dev->dev, 190195ec3fdfSJonathan Cameron iio_dev_opaque->bounce_buffer, 190295ec3fdfSJonathan Cameron indio_dev->scan_bytes, GFP_KERNEL); 190395ec3fdfSJonathan Cameron if (!bb) 190495ec3fdfSJonathan Cameron return -ENOMEM; 190595ec3fdfSJonathan Cameron iio_dev_opaque->bounce_buffer = bb; 190695ec3fdfSJonathan Cameron iio_dev_opaque->bounce_buffer_size = indio_dev->scan_bytes; 190795ec3fdfSJonathan Cameron } 190895ec3fdfSJonathan Cameron memcpy(iio_dev_opaque->bounce_buffer, data, data_sz); 190995ec3fdfSJonathan Cameron return iio_push_to_buffers_with_timestamp(indio_dev, 191095ec3fdfSJonathan Cameron iio_dev_opaque->bounce_buffer, 191195ec3fdfSJonathan Cameron timestamp); 191295ec3fdfSJonathan Cameron } 191395ec3fdfSJonathan Cameron EXPORT_SYMBOL_GPL(iio_push_to_buffers_with_ts_unaligned); 191495ec3fdfSJonathan Cameron 191595ec3fdfSJonathan Cameron /** 19169e69c935SLars-Peter Clausen * iio_buffer_release() - Free a buffer's resources 19179e69c935SLars-Peter Clausen * @ref: Pointer to the kref embedded in the iio_buffer struct 19189e69c935SLars-Peter Clausen * 19199e69c935SLars-Peter Clausen * This function is called when the last reference to the buffer has been 19209e69c935SLars-Peter Clausen * dropped. It will typically free all resources allocated by the buffer. Do not 19219e69c935SLars-Peter Clausen * call this function manually, always use iio_buffer_put() when done using a 19229e69c935SLars-Peter Clausen * buffer. 19239e69c935SLars-Peter Clausen */ 19249e69c935SLars-Peter Clausen static void iio_buffer_release(struct kref *ref) 19259e69c935SLars-Peter Clausen { 19269e69c935SLars-Peter Clausen struct iio_buffer *buffer = container_of(ref, struct iio_buffer, ref); 19279e69c935SLars-Peter Clausen 19289e69c935SLars-Peter Clausen buffer->access->release(buffer); 19299e69c935SLars-Peter Clausen } 19309e69c935SLars-Peter Clausen 19319e69c935SLars-Peter Clausen /** 19329e69c935SLars-Peter Clausen * iio_buffer_get() - Grab a reference to the buffer 19339e69c935SLars-Peter Clausen * @buffer: The buffer to grab a reference for, may be NULL 19349e69c935SLars-Peter Clausen * 19359e69c935SLars-Peter Clausen * Returns the pointer to the buffer that was passed into the function. 19369e69c935SLars-Peter Clausen */ 19379e69c935SLars-Peter Clausen struct iio_buffer *iio_buffer_get(struct iio_buffer *buffer) 19389e69c935SLars-Peter Clausen { 19399e69c935SLars-Peter Clausen if (buffer) 19409e69c935SLars-Peter Clausen kref_get(&buffer->ref); 19419e69c935SLars-Peter Clausen 19429e69c935SLars-Peter Clausen return buffer; 19439e69c935SLars-Peter Clausen } 19449e69c935SLars-Peter Clausen EXPORT_SYMBOL_GPL(iio_buffer_get); 19459e69c935SLars-Peter Clausen 19469e69c935SLars-Peter Clausen /** 19479e69c935SLars-Peter Clausen * iio_buffer_put() - Release the reference to the buffer 19489e69c935SLars-Peter Clausen * @buffer: The buffer to release the reference for, may be NULL 19499e69c935SLars-Peter Clausen */ 19509e69c935SLars-Peter Clausen void iio_buffer_put(struct iio_buffer *buffer) 19519e69c935SLars-Peter Clausen { 19529e69c935SLars-Peter Clausen if (buffer) 19539e69c935SLars-Peter Clausen kref_put(&buffer->ref, iio_buffer_release); 19549e69c935SLars-Peter Clausen } 19559e69c935SLars-Peter Clausen EXPORT_SYMBOL_GPL(iio_buffer_put); 19562b827ad5SJonathan Cameron 19572b827ad5SJonathan Cameron /** 19582b827ad5SJonathan Cameron * iio_device_attach_buffer - Attach a buffer to a IIO device 19592b827ad5SJonathan Cameron * @indio_dev: The device the buffer should be attached to 19602b827ad5SJonathan Cameron * @buffer: The buffer to attach to the device 19612b827ad5SJonathan Cameron * 1962ee708e6bSAlexandru Ardelean * Return 0 if successful, negative if error. 1963ee708e6bSAlexandru Ardelean * 19642b827ad5SJonathan Cameron * This function attaches a buffer to a IIO device. The buffer stays attached to 1965ee708e6bSAlexandru Ardelean * the device until the device is freed. For legacy reasons, the first attached 1966ee708e6bSAlexandru Ardelean * buffer will also be assigned to 'indio_dev->buffer'. 1967218bc53dSAlexandru Ardelean * The array allocated here, will be free'd via the iio_device_detach_buffers() 1968218bc53dSAlexandru Ardelean * call which is handled by the iio_device_free(). 19692b827ad5SJonathan Cameron */ 1970ee708e6bSAlexandru Ardelean int iio_device_attach_buffer(struct iio_dev *indio_dev, 19712b827ad5SJonathan Cameron struct iio_buffer *buffer) 19722b827ad5SJonathan Cameron { 1973ee708e6bSAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1974ee708e6bSAlexandru Ardelean struct iio_buffer **new, **old = iio_dev_opaque->attached_buffers; 1975ee708e6bSAlexandru Ardelean unsigned int cnt = iio_dev_opaque->attached_buffers_cnt; 1976ee708e6bSAlexandru Ardelean 1977ee708e6bSAlexandru Ardelean cnt++; 1978ee708e6bSAlexandru Ardelean 1979ee708e6bSAlexandru Ardelean new = krealloc(old, sizeof(*new) * cnt, GFP_KERNEL); 1980ee708e6bSAlexandru Ardelean if (!new) 1981ee708e6bSAlexandru Ardelean return -ENOMEM; 1982ee708e6bSAlexandru Ardelean iio_dev_opaque->attached_buffers = new; 1983ee708e6bSAlexandru Ardelean 1984ee708e6bSAlexandru Ardelean buffer = iio_buffer_get(buffer); 1985ee708e6bSAlexandru Ardelean 1986ee708e6bSAlexandru Ardelean /* first buffer is legacy; attach it to the IIO device directly */ 1987ee708e6bSAlexandru Ardelean if (!indio_dev->buffer) 1988ee708e6bSAlexandru Ardelean indio_dev->buffer = buffer; 1989ee708e6bSAlexandru Ardelean 1990ee708e6bSAlexandru Ardelean iio_dev_opaque->attached_buffers[cnt - 1] = buffer; 1991ee708e6bSAlexandru Ardelean iio_dev_opaque->attached_buffers_cnt = cnt; 1992ee708e6bSAlexandru Ardelean 1993ee708e6bSAlexandru Ardelean return 0; 19942b827ad5SJonathan Cameron } 19952b827ad5SJonathan Cameron EXPORT_SYMBOL_GPL(iio_device_attach_buffer); 1996