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