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 123*9eeee3b0SMihail Chindris if (rb->direction != IIO_BUFFER_DIRECTION_IN) 124*9eeee3b0SMihail Chindris return -EPERM; 125*9eeee3b0SMihail 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 167*9eeee3b0SMihail Chindris static size_t iio_buffer_space_available(struct iio_buffer *buf) 168*9eeee3b0SMihail Chindris { 169*9eeee3b0SMihail Chindris if (buf->access->space_available) 170*9eeee3b0SMihail Chindris return buf->access->space_available(buf); 171*9eeee3b0SMihail Chindris 172*9eeee3b0SMihail Chindris return SIZE_MAX; 173*9eeee3b0SMihail Chindris } 174*9eeee3b0SMihail Chindris 175*9eeee3b0SMihail Chindris static ssize_t iio_buffer_write(struct file *filp, const char __user *buf, 176*9eeee3b0SMihail Chindris size_t n, loff_t *f_ps) 177*9eeee3b0SMihail Chindris { 178*9eeee3b0SMihail Chindris struct iio_dev_buffer_pair *ib = filp->private_data; 179*9eeee3b0SMihail Chindris struct iio_buffer *rb = ib->buffer; 180*9eeee3b0SMihail Chindris struct iio_dev *indio_dev = ib->indio_dev; 181*9eeee3b0SMihail Chindris DEFINE_WAIT_FUNC(wait, woken_wake_function); 182*9eeee3b0SMihail Chindris int ret; 183*9eeee3b0SMihail Chindris size_t written; 184*9eeee3b0SMihail Chindris 185*9eeee3b0SMihail Chindris if (!indio_dev->info) 186*9eeee3b0SMihail Chindris return -ENODEV; 187*9eeee3b0SMihail Chindris 188*9eeee3b0SMihail Chindris if (!rb || !rb->access->write) 189*9eeee3b0SMihail Chindris return -EINVAL; 190*9eeee3b0SMihail Chindris 191*9eeee3b0SMihail Chindris if (rb->direction != IIO_BUFFER_DIRECTION_OUT) 192*9eeee3b0SMihail Chindris return -EPERM; 193*9eeee3b0SMihail Chindris 194*9eeee3b0SMihail Chindris written = 0; 195*9eeee3b0SMihail Chindris add_wait_queue(&rb->pollq, &wait); 196*9eeee3b0SMihail Chindris do { 197*9eeee3b0SMihail Chindris if (indio_dev->info == NULL) 198*9eeee3b0SMihail Chindris return -ENODEV; 199*9eeee3b0SMihail Chindris 200*9eeee3b0SMihail Chindris if (!iio_buffer_space_available(rb)) { 201*9eeee3b0SMihail Chindris if (signal_pending(current)) { 202*9eeee3b0SMihail Chindris ret = -ERESTARTSYS; 203*9eeee3b0SMihail Chindris break; 204*9eeee3b0SMihail Chindris } 205*9eeee3b0SMihail Chindris 206*9eeee3b0SMihail Chindris wait_woken(&wait, TASK_INTERRUPTIBLE, 207*9eeee3b0SMihail Chindris MAX_SCHEDULE_TIMEOUT); 208*9eeee3b0SMihail Chindris continue; 209*9eeee3b0SMihail Chindris } 210*9eeee3b0SMihail Chindris 211*9eeee3b0SMihail Chindris ret = rb->access->write(rb, n - written, buf + written); 212*9eeee3b0SMihail Chindris if (ret == 0 && (filp->f_flags & O_NONBLOCK)) 213*9eeee3b0SMihail Chindris ret = -EAGAIN; 214*9eeee3b0SMihail Chindris 215*9eeee3b0SMihail Chindris if (ret > 0) { 216*9eeee3b0SMihail Chindris written += ret; 217*9eeee3b0SMihail Chindris if (written != n && !(filp->f_flags & O_NONBLOCK)) 218*9eeee3b0SMihail Chindris continue; 219*9eeee3b0SMihail Chindris } 220*9eeee3b0SMihail Chindris } while (ret == 0); 221*9eeee3b0SMihail Chindris remove_wait_queue(&rb->pollq, &wait); 222*9eeee3b0SMihail Chindris 223*9eeee3b0SMihail Chindris return ret < 0 ? ret : n; 224*9eeee3b0SMihail Chindris } 225*9eeee3b0SMihail Chindris 226a980e046SJonathan Cameron /** 227a980e046SJonathan Cameron * iio_buffer_poll() - poll the buffer to find out if it has data 2280123635aSCristina Opriceana * @filp: File structure pointer for device access 2290123635aSCristina Opriceana * @wait: Poll table structure pointer for which the driver adds 2300123635aSCristina Opriceana * a wait queue 2310123635aSCristina Opriceana * 232a9a08845SLinus Torvalds * Return: (EPOLLIN | EPOLLRDNORM) if data is available for reading 2330123635aSCristina Opriceana * or 0 for other cases 234a980e046SJonathan Cameron */ 235f73f7f4dSAlexandru Ardelean static __poll_t iio_buffer_poll(struct file *filp, 236a980e046SJonathan Cameron struct poll_table_struct *wait) 237a980e046SJonathan Cameron { 238be24dcb1SAlexandru Ardelean struct iio_dev_buffer_pair *ib = filp->private_data; 239be24dcb1SAlexandru Ardelean struct iio_buffer *rb = ib->buffer; 240be24dcb1SAlexandru Ardelean struct iio_dev *indio_dev = ib->indio_dev; 241a980e046SJonathan Cameron 2424cd140bdSStefan Windfeldt-Prytz if (!indio_dev->info || rb == NULL) 2431bdc0293SCristina Opriceana return 0; 244f18e7a06SLars-Peter Clausen 245a980e046SJonathan Cameron poll_wait(filp, &rb->pollq, wait); 246*9eeee3b0SMihail Chindris 247*9eeee3b0SMihail Chindris switch (rb->direction) { 248*9eeee3b0SMihail Chindris case IIO_BUFFER_DIRECTION_IN: 249f4f4673bSOctavian Purdila if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0)) 250a9a08845SLinus Torvalds return EPOLLIN | EPOLLRDNORM; 251*9eeee3b0SMihail Chindris break; 252*9eeee3b0SMihail Chindris case IIO_BUFFER_DIRECTION_OUT: 253*9eeee3b0SMihail Chindris if (iio_buffer_space_available(rb)) 254*9eeee3b0SMihail Chindris return EPOLLOUT | EPOLLWRNORM; 255*9eeee3b0SMihail Chindris break; 256*9eeee3b0SMihail Chindris } 257*9eeee3b0SMihail Chindris 258a980e046SJonathan Cameron return 0; 259a980e046SJonathan Cameron } 260a980e046SJonathan Cameron 261f73f7f4dSAlexandru Ardelean ssize_t iio_buffer_read_wrapper(struct file *filp, char __user *buf, 262f73f7f4dSAlexandru Ardelean size_t n, loff_t *f_ps) 263f73f7f4dSAlexandru Ardelean { 264f73f7f4dSAlexandru Ardelean struct iio_dev_buffer_pair *ib = filp->private_data; 265f73f7f4dSAlexandru Ardelean struct iio_buffer *rb = ib->buffer; 266f73f7f4dSAlexandru Ardelean 267f73f7f4dSAlexandru Ardelean /* check if buffer was opened through new API */ 268f73f7f4dSAlexandru Ardelean if (test_bit(IIO_BUSY_BIT_POS, &rb->flags)) 269f73f7f4dSAlexandru Ardelean return -EBUSY; 270f73f7f4dSAlexandru Ardelean 271f73f7f4dSAlexandru Ardelean return iio_buffer_read(filp, buf, n, f_ps); 272f73f7f4dSAlexandru Ardelean } 273f73f7f4dSAlexandru Ardelean 274*9eeee3b0SMihail Chindris ssize_t iio_buffer_write_wrapper(struct file *filp, const char __user *buf, 275*9eeee3b0SMihail Chindris size_t n, loff_t *f_ps) 276*9eeee3b0SMihail Chindris { 277*9eeee3b0SMihail Chindris struct iio_dev_buffer_pair *ib = filp->private_data; 278*9eeee3b0SMihail Chindris struct iio_buffer *rb = ib->buffer; 279*9eeee3b0SMihail Chindris 280*9eeee3b0SMihail Chindris /* check if buffer was opened through new API */ 281*9eeee3b0SMihail Chindris if (test_bit(IIO_BUSY_BIT_POS, &rb->flags)) 282*9eeee3b0SMihail Chindris return -EBUSY; 283*9eeee3b0SMihail Chindris 284*9eeee3b0SMihail Chindris return iio_buffer_write(filp, buf, n, f_ps); 285*9eeee3b0SMihail Chindris } 286*9eeee3b0SMihail Chindris 287f73f7f4dSAlexandru Ardelean __poll_t iio_buffer_poll_wrapper(struct file *filp, 288f73f7f4dSAlexandru Ardelean struct poll_table_struct *wait) 289f73f7f4dSAlexandru Ardelean { 290f73f7f4dSAlexandru Ardelean struct iio_dev_buffer_pair *ib = filp->private_data; 291f73f7f4dSAlexandru Ardelean struct iio_buffer *rb = ib->buffer; 292f73f7f4dSAlexandru Ardelean 293f73f7f4dSAlexandru Ardelean /* check if buffer was opened through new API */ 294f73f7f4dSAlexandru Ardelean if (test_bit(IIO_BUSY_BIT_POS, &rb->flags)) 295f73f7f4dSAlexandru Ardelean return 0; 296f73f7f4dSAlexandru Ardelean 297f73f7f4dSAlexandru Ardelean return iio_buffer_poll(filp, wait); 298f73f7f4dSAlexandru Ardelean } 299f73f7f4dSAlexandru Ardelean 300d2f0a48fSLars-Peter Clausen /** 301d2f0a48fSLars-Peter Clausen * iio_buffer_wakeup_poll - Wakes up the buffer waitqueue 302d2f0a48fSLars-Peter Clausen * @indio_dev: The IIO device 303d2f0a48fSLars-Peter Clausen * 304d2f0a48fSLars-Peter Clausen * Wakes up the event waitqueue used for poll(). Should usually 305d2f0a48fSLars-Peter Clausen * be called when the device is unregistered. 306d2f0a48fSLars-Peter Clausen */ 307d2f0a48fSLars-Peter Clausen void iio_buffer_wakeup_poll(struct iio_dev *indio_dev) 308d2f0a48fSLars-Peter Clausen { 309ee708e6bSAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 310ee708e6bSAlexandru Ardelean struct iio_buffer *buffer; 311ee708e6bSAlexandru Ardelean unsigned int i; 312ff3f7e04SAlexandru Ardelean 313ee708e6bSAlexandru Ardelean for (i = 0; i < iio_dev_opaque->attached_buffers_cnt; i++) { 314ee708e6bSAlexandru Ardelean buffer = iio_dev_opaque->attached_buffers[i]; 315ff3f7e04SAlexandru Ardelean wake_up(&buffer->pollq); 316d2f0a48fSLars-Peter Clausen } 317ee708e6bSAlexandru Ardelean } 318d2f0a48fSLars-Peter Clausen 319*9eeee3b0SMihail Chindris int iio_pop_from_buffer(struct iio_buffer *buffer, void *data) 320*9eeee3b0SMihail Chindris { 321*9eeee3b0SMihail Chindris if (!buffer || !buffer->access || !buffer->access->remove_from) 322*9eeee3b0SMihail Chindris return -EINVAL; 323*9eeee3b0SMihail Chindris 324*9eeee3b0SMihail Chindris return buffer->access->remove_from(buffer, data); 325*9eeee3b0SMihail Chindris } 326*9eeee3b0SMihail Chindris EXPORT_SYMBOL_GPL(iio_pop_from_buffer); 327*9eeee3b0SMihail Chindris 328a980e046SJonathan Cameron void iio_buffer_init(struct iio_buffer *buffer) 329a980e046SJonathan Cameron { 330a980e046SJonathan Cameron INIT_LIST_HEAD(&buffer->demux_list); 331705ee2c9SLars-Peter Clausen INIT_LIST_HEAD(&buffer->buffer_list); 332a980e046SJonathan Cameron init_waitqueue_head(&buffer->pollq); 3339e69c935SLars-Peter Clausen kref_init(&buffer->ref); 3344a605357SLars-Peter Clausen if (!buffer->watermark) 33537d34556SJosselin Costanzi buffer->watermark = 1; 336a980e046SJonathan Cameron } 337a980e046SJonathan Cameron EXPORT_SYMBOL(iio_buffer_init); 338a980e046SJonathan Cameron 339218bc53dSAlexandru Ardelean void iio_device_detach_buffers(struct iio_dev *indio_dev) 340ee708e6bSAlexandru Ardelean { 341ee708e6bSAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 342ee708e6bSAlexandru Ardelean struct iio_buffer *buffer; 343ee708e6bSAlexandru Ardelean unsigned int i; 344ee708e6bSAlexandru Ardelean 345ee708e6bSAlexandru Ardelean for (i = 0; i < iio_dev_opaque->attached_buffers_cnt; i++) { 346ee708e6bSAlexandru Ardelean buffer = iio_dev_opaque->attached_buffers[i]; 347ee708e6bSAlexandru Ardelean iio_buffer_put(buffer); 348ee708e6bSAlexandru Ardelean } 349218bc53dSAlexandru Ardelean 350218bc53dSAlexandru Ardelean kfree(iio_dev_opaque->attached_buffers); 351ee708e6bSAlexandru Ardelean } 352ee708e6bSAlexandru Ardelean 353a980e046SJonathan Cameron static ssize_t iio_show_scan_index(struct device *dev, 354a980e046SJonathan Cameron struct device_attribute *attr, 355a980e046SJonathan Cameron char *buf) 356a980e046SJonathan Cameron { 35783ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%u\n", to_iio_dev_attr(attr)->c->scan_index); 358a980e046SJonathan Cameron } 359a980e046SJonathan Cameron 360a980e046SJonathan Cameron static ssize_t iio_show_fixed_type(struct device *dev, 361a980e046SJonathan Cameron struct device_attribute *attr, 362a980e046SJonathan Cameron char *buf) 363a980e046SJonathan Cameron { 364a980e046SJonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 365a980e046SJonathan Cameron u8 type = this_attr->c->scan_type.endianness; 366a980e046SJonathan Cameron 367a980e046SJonathan Cameron if (type == IIO_CPU) { 368a980e046SJonathan Cameron #ifdef __LITTLE_ENDIAN 369a980e046SJonathan Cameron type = IIO_LE; 370a980e046SJonathan Cameron #else 371a980e046SJonathan Cameron type = IIO_BE; 372a980e046SJonathan Cameron #endif 373a980e046SJonathan Cameron } 3740ee8546aSSrinivas Pandruvada if (this_attr->c->scan_type.repeat > 1) 37583ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%s:%c%d/%dX%d>>%u\n", 3760ee8546aSSrinivas Pandruvada iio_endian_prefix[type], 3770ee8546aSSrinivas Pandruvada this_attr->c->scan_type.sign, 3780ee8546aSSrinivas Pandruvada this_attr->c->scan_type.realbits, 3790ee8546aSSrinivas Pandruvada this_attr->c->scan_type.storagebits, 3800ee8546aSSrinivas Pandruvada this_attr->c->scan_type.repeat, 3810ee8546aSSrinivas Pandruvada this_attr->c->scan_type.shift); 3820ee8546aSSrinivas Pandruvada else 38383ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%s:%c%d/%d>>%u\n", 384a980e046SJonathan Cameron iio_endian_prefix[type], 385a980e046SJonathan Cameron this_attr->c->scan_type.sign, 386a980e046SJonathan Cameron this_attr->c->scan_type.realbits, 387a980e046SJonathan Cameron this_attr->c->scan_type.storagebits, 388a980e046SJonathan Cameron this_attr->c->scan_type.shift); 389a980e046SJonathan Cameron } 390a980e046SJonathan Cameron 391a980e046SJonathan Cameron static ssize_t iio_scan_el_show(struct device *dev, 392a980e046SJonathan Cameron struct device_attribute *attr, 393a980e046SJonathan Cameron char *buf) 394a980e046SJonathan Cameron { 395a980e046SJonathan Cameron int ret; 39615097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 397a980e046SJonathan Cameron 3982076a20fSAlec Berg /* Ensure ret is 0 or 1. */ 3992076a20fSAlec Berg ret = !!test_bit(to_iio_dev_attr(attr)->address, 400ff3f7e04SAlexandru Ardelean buffer->scan_mask); 401a980e046SJonathan Cameron 40283ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%d\n", ret); 403a980e046SJonathan Cameron } 404a980e046SJonathan Cameron 405217a5cf0SLars-Peter Clausen /* Note NULL used as error indicator as it doesn't make sense. */ 406217a5cf0SLars-Peter Clausen static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks, 407217a5cf0SLars-Peter Clausen unsigned int masklength, 4081e1ec286SLars-Peter Clausen const unsigned long *mask, 4091e1ec286SLars-Peter Clausen bool strict) 410217a5cf0SLars-Peter Clausen { 411217a5cf0SLars-Peter Clausen if (bitmap_empty(mask, masklength)) 412217a5cf0SLars-Peter Clausen return NULL; 413217a5cf0SLars-Peter Clausen while (*av_masks) { 4141e1ec286SLars-Peter Clausen if (strict) { 4151e1ec286SLars-Peter Clausen if (bitmap_equal(mask, av_masks, masklength)) 4161e1ec286SLars-Peter Clausen return av_masks; 4171e1ec286SLars-Peter Clausen } else { 418217a5cf0SLars-Peter Clausen if (bitmap_subset(mask, av_masks, masklength)) 419217a5cf0SLars-Peter Clausen return av_masks; 4201e1ec286SLars-Peter Clausen } 421217a5cf0SLars-Peter Clausen av_masks += BITS_TO_LONGS(masklength); 422217a5cf0SLars-Peter Clausen } 423217a5cf0SLars-Peter Clausen return NULL; 424217a5cf0SLars-Peter Clausen } 425217a5cf0SLars-Peter Clausen 426217a5cf0SLars-Peter Clausen static bool iio_validate_scan_mask(struct iio_dev *indio_dev, 427217a5cf0SLars-Peter Clausen const unsigned long *mask) 428217a5cf0SLars-Peter Clausen { 429217a5cf0SLars-Peter Clausen if (!indio_dev->setup_ops->validate_scan_mask) 430217a5cf0SLars-Peter Clausen return true; 431217a5cf0SLars-Peter Clausen 432217a5cf0SLars-Peter Clausen return indio_dev->setup_ops->validate_scan_mask(indio_dev, mask); 433217a5cf0SLars-Peter Clausen } 434217a5cf0SLars-Peter Clausen 435217a5cf0SLars-Peter Clausen /** 436217a5cf0SLars-Peter Clausen * iio_scan_mask_set() - set particular bit in the scan mask 437217a5cf0SLars-Peter Clausen * @indio_dev: the iio device 438217a5cf0SLars-Peter Clausen * @buffer: the buffer whose scan mask we are interested in 439217a5cf0SLars-Peter Clausen * @bit: the bit to be set. 440217a5cf0SLars-Peter Clausen * 441217a5cf0SLars-Peter Clausen * Note that at this point we have no way of knowing what other 442217a5cf0SLars-Peter Clausen * buffers might request, hence this code only verifies that the 443217a5cf0SLars-Peter Clausen * individual buffers request is plausible. 444217a5cf0SLars-Peter Clausen */ 445217a5cf0SLars-Peter Clausen static int iio_scan_mask_set(struct iio_dev *indio_dev, 446217a5cf0SLars-Peter Clausen struct iio_buffer *buffer, int bit) 447217a5cf0SLars-Peter Clausen { 448217a5cf0SLars-Peter Clausen const unsigned long *mask; 449217a5cf0SLars-Peter Clausen unsigned long *trialmask; 450217a5cf0SLars-Peter Clausen 451d21fed06SChristophe JAILLET if (!indio_dev->masklength) { 452d21fed06SChristophe JAILLET WARN(1, "Trying to set scanmask prior to registering buffer\n"); 453d21fed06SChristophe JAILLET return -EINVAL; 454d21fed06SChristophe JAILLET } 455d21fed06SChristophe JAILLET 45645851650SChristophe JAILLET trialmask = bitmap_alloc(indio_dev->masklength, GFP_KERNEL); 45745851650SChristophe JAILLET if (!trialmask) 458217a5cf0SLars-Peter Clausen return -ENOMEM; 459217a5cf0SLars-Peter Clausen bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength); 460217a5cf0SLars-Peter Clausen set_bit(bit, trialmask); 461217a5cf0SLars-Peter Clausen 462217a5cf0SLars-Peter Clausen if (!iio_validate_scan_mask(indio_dev, trialmask)) 463217a5cf0SLars-Peter Clausen goto err_invalid_mask; 464217a5cf0SLars-Peter Clausen 465217a5cf0SLars-Peter Clausen if (indio_dev->available_scan_masks) { 466217a5cf0SLars-Peter Clausen mask = iio_scan_mask_match(indio_dev->available_scan_masks, 467217a5cf0SLars-Peter Clausen indio_dev->masklength, 4681e1ec286SLars-Peter Clausen trialmask, false); 469217a5cf0SLars-Peter Clausen if (!mask) 470217a5cf0SLars-Peter Clausen goto err_invalid_mask; 471217a5cf0SLars-Peter Clausen } 472217a5cf0SLars-Peter Clausen bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength); 473217a5cf0SLars-Peter Clausen 4743862828aSAndy Shevchenko bitmap_free(trialmask); 475217a5cf0SLars-Peter Clausen 476217a5cf0SLars-Peter Clausen return 0; 477217a5cf0SLars-Peter Clausen 478217a5cf0SLars-Peter Clausen err_invalid_mask: 4793862828aSAndy Shevchenko bitmap_free(trialmask); 480217a5cf0SLars-Peter Clausen return -EINVAL; 481217a5cf0SLars-Peter Clausen } 482217a5cf0SLars-Peter Clausen 483a980e046SJonathan Cameron static int iio_scan_mask_clear(struct iio_buffer *buffer, int bit) 484a980e046SJonathan Cameron { 485a980e046SJonathan Cameron clear_bit(bit, buffer->scan_mask); 486a980e046SJonathan Cameron return 0; 487a980e046SJonathan Cameron } 488a980e046SJonathan Cameron 489c2bf8d5fSJonathan Cameron static int iio_scan_mask_query(struct iio_dev *indio_dev, 490c2bf8d5fSJonathan Cameron struct iio_buffer *buffer, int bit) 491c2bf8d5fSJonathan Cameron { 492c2bf8d5fSJonathan Cameron if (bit > indio_dev->masklength) 493c2bf8d5fSJonathan Cameron return -EINVAL; 494c2bf8d5fSJonathan Cameron 495c2bf8d5fSJonathan Cameron if (!buffer->scan_mask) 496c2bf8d5fSJonathan Cameron return 0; 497c2bf8d5fSJonathan Cameron 498c2bf8d5fSJonathan Cameron /* Ensure return value is 0 or 1. */ 499c2bf8d5fSJonathan Cameron return !!test_bit(bit, buffer->scan_mask); 500c2bf8d5fSJonathan Cameron }; 501c2bf8d5fSJonathan Cameron 502a980e046SJonathan Cameron static ssize_t iio_scan_el_store(struct device *dev, 503a980e046SJonathan Cameron struct device_attribute *attr, 504a980e046SJonathan Cameron const char *buf, 505a980e046SJonathan Cameron size_t len) 506a980e046SJonathan Cameron { 507a980e046SJonathan Cameron int ret; 508a980e046SJonathan Cameron bool state; 509e53f5ac5SLars-Peter Clausen struct iio_dev *indio_dev = dev_to_iio_dev(dev); 510a980e046SJonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 51115097c7aSAlexandru Ardelean struct iio_buffer *buffer = this_attr->buffer; 512a980e046SJonathan Cameron 513a980e046SJonathan Cameron ret = strtobool(buf, &state); 514a980e046SJonathan Cameron if (ret < 0) 515a980e046SJonathan Cameron return ret; 516a980e046SJonathan Cameron mutex_lock(&indio_dev->mlock); 517ff3f7e04SAlexandru Ardelean if (iio_buffer_is_active(buffer)) { 518a980e046SJonathan Cameron ret = -EBUSY; 519a980e046SJonathan Cameron goto error_ret; 520a980e046SJonathan Cameron } 521a980e046SJonathan Cameron ret = iio_scan_mask_query(indio_dev, buffer, this_attr->address); 522a980e046SJonathan Cameron if (ret < 0) 523a980e046SJonathan Cameron goto error_ret; 524a980e046SJonathan Cameron if (!state && ret) { 525a980e046SJonathan Cameron ret = iio_scan_mask_clear(buffer, this_attr->address); 526a980e046SJonathan Cameron if (ret) 527a980e046SJonathan Cameron goto error_ret; 528a980e046SJonathan Cameron } else if (state && !ret) { 529a980e046SJonathan Cameron ret = iio_scan_mask_set(indio_dev, buffer, this_attr->address); 530a980e046SJonathan Cameron if (ret) 531a980e046SJonathan Cameron goto error_ret; 532a980e046SJonathan Cameron } 533a980e046SJonathan Cameron 534a980e046SJonathan Cameron error_ret: 535a980e046SJonathan Cameron mutex_unlock(&indio_dev->mlock); 536a980e046SJonathan Cameron 537a980e046SJonathan Cameron return ret < 0 ? ret : len; 538a980e046SJonathan Cameron 539a980e046SJonathan Cameron } 540a980e046SJonathan Cameron 541a980e046SJonathan Cameron static ssize_t iio_scan_el_ts_show(struct device *dev, 542a980e046SJonathan Cameron struct device_attribute *attr, 543a980e046SJonathan Cameron char *buf) 544a980e046SJonathan Cameron { 54515097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 546ff3f7e04SAlexandru Ardelean 54783ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%d\n", buffer->scan_timestamp); 548a980e046SJonathan Cameron } 549a980e046SJonathan Cameron 550a980e046SJonathan Cameron static ssize_t iio_scan_el_ts_store(struct device *dev, 551a980e046SJonathan Cameron struct device_attribute *attr, 552a980e046SJonathan Cameron const char *buf, 553a980e046SJonathan Cameron size_t len) 554a980e046SJonathan Cameron { 555a980e046SJonathan Cameron int ret; 556e53f5ac5SLars-Peter Clausen struct iio_dev *indio_dev = dev_to_iio_dev(dev); 55715097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 558a980e046SJonathan Cameron bool state; 559a980e046SJonathan Cameron 560a980e046SJonathan Cameron ret = strtobool(buf, &state); 561a980e046SJonathan Cameron if (ret < 0) 562a980e046SJonathan Cameron return ret; 563a980e046SJonathan Cameron 564a980e046SJonathan Cameron mutex_lock(&indio_dev->mlock); 565ff3f7e04SAlexandru Ardelean if (iio_buffer_is_active(buffer)) { 566a980e046SJonathan Cameron ret = -EBUSY; 567a980e046SJonathan Cameron goto error_ret; 568a980e046SJonathan Cameron } 569ff3f7e04SAlexandru Ardelean buffer->scan_timestamp = state; 570a980e046SJonathan Cameron error_ret: 571a980e046SJonathan Cameron mutex_unlock(&indio_dev->mlock); 572a980e046SJonathan Cameron 573a980e046SJonathan Cameron return ret ? ret : len; 574a980e046SJonathan Cameron } 575a980e046SJonathan Cameron 576a980e046SJonathan Cameron static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev, 577ff3f7e04SAlexandru Ardelean struct iio_buffer *buffer, 578a980e046SJonathan Cameron const struct iio_chan_spec *chan) 579a980e046SJonathan Cameron { 580a980e046SJonathan Cameron int ret, attrcount = 0; 581a980e046SJonathan Cameron 582a980e046SJonathan Cameron ret = __iio_add_chan_devattr("index", 583a980e046SJonathan Cameron chan, 584a980e046SJonathan Cameron &iio_show_scan_index, 585a980e046SJonathan Cameron NULL, 586a980e046SJonathan Cameron 0, 5873704432fSJonathan Cameron IIO_SEPARATE, 588a980e046SJonathan Cameron &indio_dev->dev, 5893e3d11b2SAlexandru Ardelean buffer, 59015097c7aSAlexandru Ardelean &buffer->buffer_attr_list); 591a980e046SJonathan Cameron if (ret) 59292825ff9SHartmut Knaack return ret; 593a980e046SJonathan Cameron attrcount++; 594a980e046SJonathan Cameron ret = __iio_add_chan_devattr("type", 595a980e046SJonathan Cameron chan, 596a980e046SJonathan Cameron &iio_show_fixed_type, 597a980e046SJonathan Cameron NULL, 598a980e046SJonathan Cameron 0, 599a980e046SJonathan Cameron 0, 600a980e046SJonathan Cameron &indio_dev->dev, 6013e3d11b2SAlexandru Ardelean buffer, 60215097c7aSAlexandru Ardelean &buffer->buffer_attr_list); 603a980e046SJonathan Cameron if (ret) 60492825ff9SHartmut Knaack return ret; 605a980e046SJonathan Cameron attrcount++; 606a980e046SJonathan Cameron if (chan->type != IIO_TIMESTAMP) 607a980e046SJonathan Cameron ret = __iio_add_chan_devattr("en", 608a980e046SJonathan Cameron chan, 609a980e046SJonathan Cameron &iio_scan_el_show, 610a980e046SJonathan Cameron &iio_scan_el_store, 611a980e046SJonathan Cameron chan->scan_index, 612a980e046SJonathan Cameron 0, 613a980e046SJonathan Cameron &indio_dev->dev, 6143e3d11b2SAlexandru Ardelean buffer, 61515097c7aSAlexandru Ardelean &buffer->buffer_attr_list); 616a980e046SJonathan Cameron else 617a980e046SJonathan Cameron ret = __iio_add_chan_devattr("en", 618a980e046SJonathan Cameron chan, 619a980e046SJonathan Cameron &iio_scan_el_ts_show, 620a980e046SJonathan Cameron &iio_scan_el_ts_store, 621a980e046SJonathan Cameron chan->scan_index, 622a980e046SJonathan Cameron 0, 623a980e046SJonathan Cameron &indio_dev->dev, 6243e3d11b2SAlexandru Ardelean buffer, 62515097c7aSAlexandru Ardelean &buffer->buffer_attr_list); 6269572588cSPeter Meerwald if (ret) 62792825ff9SHartmut Knaack return ret; 628a980e046SJonathan Cameron attrcount++; 629a980e046SJonathan Cameron ret = attrcount; 630a980e046SJonathan Cameron return ret; 631a980e046SJonathan Cameron } 632a980e046SJonathan Cameron 63308e7e0adSLars-Peter Clausen static ssize_t iio_buffer_read_length(struct device *dev, 634a980e046SJonathan Cameron struct device_attribute *attr, 635a980e046SJonathan Cameron char *buf) 636a980e046SJonathan Cameron { 63715097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 638a980e046SJonathan Cameron 63983ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%d\n", buffer->length); 640a980e046SJonathan Cameron } 641a980e046SJonathan Cameron 64208e7e0adSLars-Peter Clausen static ssize_t iio_buffer_write_length(struct device *dev, 643a980e046SJonathan Cameron struct device_attribute *attr, 64408e7e0adSLars-Peter Clausen const char *buf, size_t len) 645a980e046SJonathan Cameron { 646e53f5ac5SLars-Peter Clausen struct iio_dev *indio_dev = dev_to_iio_dev(dev); 64715097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 648948ad205SLars-Peter Clausen unsigned int val; 649948ad205SLars-Peter Clausen int ret; 650a980e046SJonathan Cameron 651948ad205SLars-Peter Clausen ret = kstrtouint(buf, 10, &val); 652a980e046SJonathan Cameron if (ret) 653a980e046SJonathan Cameron return ret; 654a980e046SJonathan Cameron 65537495660SLars-Peter Clausen if (val == buffer->length) 656a980e046SJonathan Cameron return len; 657a980e046SJonathan Cameron 658a980e046SJonathan Cameron mutex_lock(&indio_dev->mlock); 659ff3f7e04SAlexandru Ardelean if (iio_buffer_is_active(buffer)) { 660a980e046SJonathan Cameron ret = -EBUSY; 661a980e046SJonathan Cameron } else { 662a980e046SJonathan Cameron buffer->access->set_length(buffer, val); 663a980e046SJonathan Cameron ret = 0; 664a980e046SJonathan Cameron } 66537d34556SJosselin Costanzi if (ret) 66637d34556SJosselin Costanzi goto out; 66737d34556SJosselin Costanzi if (buffer->length && buffer->length < buffer->watermark) 66837d34556SJosselin Costanzi buffer->watermark = buffer->length; 66937d34556SJosselin Costanzi out: 670a980e046SJonathan Cameron mutex_unlock(&indio_dev->mlock); 671a980e046SJonathan Cameron 672a980e046SJonathan Cameron return ret ? ret : len; 673a980e046SJonathan Cameron } 674a980e046SJonathan Cameron 67508e7e0adSLars-Peter Clausen static ssize_t iio_buffer_show_enable(struct device *dev, 676a980e046SJonathan Cameron struct device_attribute *attr, 677a980e046SJonathan Cameron char *buf) 678a980e046SJonathan Cameron { 67915097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 680ff3f7e04SAlexandru Ardelean 68183ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%d\n", iio_buffer_is_active(buffer)); 682a980e046SJonathan Cameron } 683a980e046SJonathan Cameron 684182b4905SLars-Peter Clausen static unsigned int iio_storage_bytes_for_si(struct iio_dev *indio_dev, 685182b4905SLars-Peter Clausen unsigned int scan_index) 686182b4905SLars-Peter Clausen { 687182b4905SLars-Peter Clausen const struct iio_chan_spec *ch; 688182b4905SLars-Peter Clausen unsigned int bytes; 689182b4905SLars-Peter Clausen 690182b4905SLars-Peter Clausen ch = iio_find_channel_from_si(indio_dev, scan_index); 691182b4905SLars-Peter Clausen bytes = ch->scan_type.storagebits / 8; 692182b4905SLars-Peter Clausen if (ch->scan_type.repeat > 1) 693182b4905SLars-Peter Clausen bytes *= ch->scan_type.repeat; 694182b4905SLars-Peter Clausen return bytes; 695182b4905SLars-Peter Clausen } 696182b4905SLars-Peter Clausen 697182b4905SLars-Peter Clausen static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev) 698182b4905SLars-Peter Clausen { 69962f4f36cSJonathan Cameron struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 70062f4f36cSJonathan Cameron 701182b4905SLars-Peter Clausen return iio_storage_bytes_for_si(indio_dev, 70262f4f36cSJonathan Cameron iio_dev_opaque->scan_index_timestamp); 703182b4905SLars-Peter Clausen } 704182b4905SLars-Peter Clausen 705183f4173SPeter Meerwald static int iio_compute_scan_bytes(struct iio_dev *indio_dev, 706183f4173SPeter Meerwald const unsigned long *mask, bool timestamp) 707a980e046SJonathan Cameron { 708a980e046SJonathan Cameron unsigned bytes = 0; 709883f6165SLars Möllendorf int length, i, largest = 0; 710a980e046SJonathan Cameron 711a980e046SJonathan Cameron /* How much space will the demuxed element take? */ 712a980e046SJonathan Cameron for_each_set_bit(i, mask, 713a980e046SJonathan Cameron indio_dev->masklength) { 714182b4905SLars-Peter Clausen length = iio_storage_bytes_for_si(indio_dev, i); 715a980e046SJonathan Cameron bytes = ALIGN(bytes, length); 716a980e046SJonathan Cameron bytes += length; 717883f6165SLars Möllendorf largest = max(largest, length); 718a980e046SJonathan Cameron } 719182b4905SLars-Peter Clausen 720a980e046SJonathan Cameron if (timestamp) { 721182b4905SLars-Peter Clausen length = iio_storage_bytes_for_timestamp(indio_dev); 722a980e046SJonathan Cameron bytes = ALIGN(bytes, length); 723a980e046SJonathan Cameron bytes += length; 724883f6165SLars Möllendorf largest = max(largest, length); 725a980e046SJonathan Cameron } 726883f6165SLars Möllendorf 727883f6165SLars Möllendorf bytes = ALIGN(bytes, largest); 728a980e046SJonathan Cameron return bytes; 729a980e046SJonathan Cameron } 730a980e046SJonathan Cameron 7319e69c935SLars-Peter Clausen static void iio_buffer_activate(struct iio_dev *indio_dev, 7329e69c935SLars-Peter Clausen struct iio_buffer *buffer) 7339e69c935SLars-Peter Clausen { 7346a8c6b26SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 7356a8c6b26SAlexandru Ardelean 7369e69c935SLars-Peter Clausen iio_buffer_get(buffer); 7376a8c6b26SAlexandru Ardelean list_add(&buffer->buffer_list, &iio_dev_opaque->buffer_list); 7389e69c935SLars-Peter Clausen } 7399e69c935SLars-Peter Clausen 7409e69c935SLars-Peter Clausen static void iio_buffer_deactivate(struct iio_buffer *buffer) 7419e69c935SLars-Peter Clausen { 7429e69c935SLars-Peter Clausen list_del_init(&buffer->buffer_list); 74337d34556SJosselin Costanzi wake_up_interruptible(&buffer->pollq); 7449e69c935SLars-Peter Clausen iio_buffer_put(buffer); 7459e69c935SLars-Peter Clausen } 7469e69c935SLars-Peter Clausen 7471250186aSLars-Peter Clausen static void iio_buffer_deactivate_all(struct iio_dev *indio_dev) 7481250186aSLars-Peter Clausen { 7496a8c6b26SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 7501250186aSLars-Peter Clausen struct iio_buffer *buffer, *_buffer; 7511250186aSLars-Peter Clausen 7521250186aSLars-Peter Clausen list_for_each_entry_safe(buffer, _buffer, 7536a8c6b26SAlexandru Ardelean &iio_dev_opaque->buffer_list, buffer_list) 7541250186aSLars-Peter Clausen iio_buffer_deactivate(buffer); 7551250186aSLars-Peter Clausen } 7561250186aSLars-Peter Clausen 757e18a2ad4SLars-Peter Clausen static int iio_buffer_enable(struct iio_buffer *buffer, 758e18a2ad4SLars-Peter Clausen struct iio_dev *indio_dev) 759e18a2ad4SLars-Peter Clausen { 760e18a2ad4SLars-Peter Clausen if (!buffer->access->enable) 761e18a2ad4SLars-Peter Clausen return 0; 762e18a2ad4SLars-Peter Clausen return buffer->access->enable(buffer, indio_dev); 763e18a2ad4SLars-Peter Clausen } 764e18a2ad4SLars-Peter Clausen 765e18a2ad4SLars-Peter Clausen static int iio_buffer_disable(struct iio_buffer *buffer, 766e18a2ad4SLars-Peter Clausen struct iio_dev *indio_dev) 767e18a2ad4SLars-Peter Clausen { 768e18a2ad4SLars-Peter Clausen if (!buffer->access->disable) 769e18a2ad4SLars-Peter Clausen return 0; 770e18a2ad4SLars-Peter Clausen return buffer->access->disable(buffer, indio_dev); 771e18a2ad4SLars-Peter Clausen } 772e18a2ad4SLars-Peter Clausen 7738e050996SLars-Peter Clausen static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev, 7748e050996SLars-Peter Clausen struct iio_buffer *buffer) 7758e050996SLars-Peter Clausen { 7768e050996SLars-Peter Clausen unsigned int bytes; 7778e050996SLars-Peter Clausen 7788e050996SLars-Peter Clausen if (!buffer->access->set_bytes_per_datum) 7798e050996SLars-Peter Clausen return; 7808e050996SLars-Peter Clausen 7818e050996SLars-Peter Clausen bytes = iio_compute_scan_bytes(indio_dev, buffer->scan_mask, 7828e050996SLars-Peter Clausen buffer->scan_timestamp); 7838e050996SLars-Peter Clausen 7848e050996SLars-Peter Clausen buffer->access->set_bytes_per_datum(buffer, bytes); 7858e050996SLars-Peter Clausen } 7868e050996SLars-Peter Clausen 787fcc1b2f5SLars-Peter Clausen static int iio_buffer_request_update(struct iio_dev *indio_dev, 788fcc1b2f5SLars-Peter Clausen struct iio_buffer *buffer) 789fcc1b2f5SLars-Peter Clausen { 790fcc1b2f5SLars-Peter Clausen int ret; 791fcc1b2f5SLars-Peter Clausen 792fcc1b2f5SLars-Peter Clausen iio_buffer_update_bytes_per_datum(indio_dev, buffer); 793fcc1b2f5SLars-Peter Clausen if (buffer->access->request_update) { 794fcc1b2f5SLars-Peter Clausen ret = buffer->access->request_update(buffer); 795fcc1b2f5SLars-Peter Clausen if (ret) { 796fcc1b2f5SLars-Peter Clausen dev_dbg(&indio_dev->dev, 797fcc1b2f5SLars-Peter Clausen "Buffer not started: buffer parameter update failed (%d)\n", 798fcc1b2f5SLars-Peter Clausen ret); 799fcc1b2f5SLars-Peter Clausen return ret; 800fcc1b2f5SLars-Peter Clausen } 801fcc1b2f5SLars-Peter Clausen } 802fcc1b2f5SLars-Peter Clausen 803fcc1b2f5SLars-Peter Clausen return 0; 804fcc1b2f5SLars-Peter Clausen } 805fcc1b2f5SLars-Peter Clausen 806248be5aaSLars-Peter Clausen static void iio_free_scan_mask(struct iio_dev *indio_dev, 807248be5aaSLars-Peter Clausen const unsigned long *mask) 808248be5aaSLars-Peter Clausen { 809248be5aaSLars-Peter Clausen /* If the mask is dynamically allocated free it, otherwise do nothing */ 810248be5aaSLars-Peter Clausen if (!indio_dev->available_scan_masks) 8113862828aSAndy Shevchenko bitmap_free(mask); 812248be5aaSLars-Peter Clausen } 813248be5aaSLars-Peter Clausen 8146e509c4dSLars-Peter Clausen struct iio_device_config { 8156e509c4dSLars-Peter Clausen unsigned int mode; 816f0566c0cSLars-Peter Clausen unsigned int watermark; 8176e509c4dSLars-Peter Clausen const unsigned long *scan_mask; 8186e509c4dSLars-Peter Clausen unsigned int scan_bytes; 8196e509c4dSLars-Peter Clausen bool scan_timestamp; 8206e509c4dSLars-Peter Clausen }; 8216e509c4dSLars-Peter Clausen 8226e509c4dSLars-Peter Clausen static int iio_verify_update(struct iio_dev *indio_dev, 8236e509c4dSLars-Peter Clausen struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer, 8246e509c4dSLars-Peter Clausen struct iio_device_config *config) 8256e509c4dSLars-Peter Clausen { 8266a8c6b26SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 8276e509c4dSLars-Peter Clausen unsigned long *compound_mask; 8286e509c4dSLars-Peter Clausen const unsigned long *scan_mask; 8291e1ec286SLars-Peter Clausen bool strict_scanmask = false; 8306e509c4dSLars-Peter Clausen struct iio_buffer *buffer; 8316e509c4dSLars-Peter Clausen bool scan_timestamp; 832225d59adSLars-Peter Clausen unsigned int modes; 8336e509c4dSLars-Peter Clausen 834b7329249SLars-Peter Clausen if (insert_buffer && 835b7329249SLars-Peter Clausen bitmap_empty(insert_buffer->scan_mask, indio_dev->masklength)) { 836b7329249SLars-Peter Clausen dev_dbg(&indio_dev->dev, 837b7329249SLars-Peter Clausen "At least one scan element must be enabled first\n"); 838b7329249SLars-Peter Clausen return -EINVAL; 839b7329249SLars-Peter Clausen } 840b7329249SLars-Peter Clausen 8416e509c4dSLars-Peter Clausen memset(config, 0, sizeof(*config)); 8421bef2c1dSIrina Tirdea config->watermark = ~0; 8436e509c4dSLars-Peter Clausen 8446e509c4dSLars-Peter Clausen /* 8456e509c4dSLars-Peter Clausen * If there is just one buffer and we are removing it there is nothing 8466e509c4dSLars-Peter Clausen * to verify. 8476e509c4dSLars-Peter Clausen */ 8486e509c4dSLars-Peter Clausen if (remove_buffer && !insert_buffer && 8496a8c6b26SAlexandru Ardelean list_is_singular(&iio_dev_opaque->buffer_list)) 8506e509c4dSLars-Peter Clausen return 0; 8516e509c4dSLars-Peter Clausen 852225d59adSLars-Peter Clausen modes = indio_dev->modes; 853225d59adSLars-Peter Clausen 8546a8c6b26SAlexandru Ardelean list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { 855225d59adSLars-Peter Clausen if (buffer == remove_buffer) 856225d59adSLars-Peter Clausen continue; 857225d59adSLars-Peter Clausen modes &= buffer->access->modes; 858f0566c0cSLars-Peter Clausen config->watermark = min(config->watermark, buffer->watermark); 859225d59adSLars-Peter Clausen } 860225d59adSLars-Peter Clausen 861f0566c0cSLars-Peter Clausen if (insert_buffer) { 862225d59adSLars-Peter Clausen modes &= insert_buffer->access->modes; 863f0566c0cSLars-Peter Clausen config->watermark = min(config->watermark, 864f0566c0cSLars-Peter Clausen insert_buffer->watermark); 865f0566c0cSLars-Peter Clausen } 866225d59adSLars-Peter Clausen 8676e509c4dSLars-Peter Clausen /* Definitely possible for devices to support both of these. */ 868225d59adSLars-Peter Clausen if ((modes & INDIO_BUFFER_TRIGGERED) && indio_dev->trig) { 8696e509c4dSLars-Peter Clausen config->mode = INDIO_BUFFER_TRIGGERED; 870225d59adSLars-Peter Clausen } else if (modes & INDIO_BUFFER_HARDWARE) { 8711e1ec286SLars-Peter Clausen /* 8721e1ec286SLars-Peter Clausen * Keep things simple for now and only allow a single buffer to 8731e1ec286SLars-Peter Clausen * be connected in hardware mode. 8741e1ec286SLars-Peter Clausen */ 8756a8c6b26SAlexandru Ardelean if (insert_buffer && !list_empty(&iio_dev_opaque->buffer_list)) 8761e1ec286SLars-Peter Clausen return -EINVAL; 8776e509c4dSLars-Peter Clausen config->mode = INDIO_BUFFER_HARDWARE; 8781e1ec286SLars-Peter Clausen strict_scanmask = true; 879225d59adSLars-Peter Clausen } else if (modes & INDIO_BUFFER_SOFTWARE) { 8806e509c4dSLars-Peter Clausen config->mode = INDIO_BUFFER_SOFTWARE; 8816e509c4dSLars-Peter Clausen } else { 8826e509c4dSLars-Peter Clausen /* Can only occur on first buffer */ 8836e509c4dSLars-Peter Clausen if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) 8846e509c4dSLars-Peter Clausen dev_dbg(&indio_dev->dev, "Buffer not started: no trigger\n"); 8856e509c4dSLars-Peter Clausen return -EINVAL; 8866e509c4dSLars-Peter Clausen } 8876e509c4dSLars-Peter Clausen 8886e509c4dSLars-Peter Clausen /* What scan mask do we actually have? */ 8893862828aSAndy Shevchenko compound_mask = bitmap_zalloc(indio_dev->masklength, GFP_KERNEL); 8906e509c4dSLars-Peter Clausen if (compound_mask == NULL) 8916e509c4dSLars-Peter Clausen return -ENOMEM; 8926e509c4dSLars-Peter Clausen 8936e509c4dSLars-Peter Clausen scan_timestamp = false; 8946e509c4dSLars-Peter Clausen 8956a8c6b26SAlexandru Ardelean list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { 8966e509c4dSLars-Peter Clausen if (buffer == remove_buffer) 8976e509c4dSLars-Peter Clausen continue; 8986e509c4dSLars-Peter Clausen bitmap_or(compound_mask, compound_mask, buffer->scan_mask, 8996e509c4dSLars-Peter Clausen indio_dev->masklength); 9006e509c4dSLars-Peter Clausen scan_timestamp |= buffer->scan_timestamp; 9016e509c4dSLars-Peter Clausen } 9026e509c4dSLars-Peter Clausen 9036e509c4dSLars-Peter Clausen if (insert_buffer) { 9046e509c4dSLars-Peter Clausen bitmap_or(compound_mask, compound_mask, 9056e509c4dSLars-Peter Clausen insert_buffer->scan_mask, indio_dev->masklength); 9066e509c4dSLars-Peter Clausen scan_timestamp |= insert_buffer->scan_timestamp; 9076e509c4dSLars-Peter Clausen } 9086e509c4dSLars-Peter Clausen 9096e509c4dSLars-Peter Clausen if (indio_dev->available_scan_masks) { 9106e509c4dSLars-Peter Clausen scan_mask = iio_scan_mask_match(indio_dev->available_scan_masks, 9116e509c4dSLars-Peter Clausen indio_dev->masklength, 9121e1ec286SLars-Peter Clausen compound_mask, 9131e1ec286SLars-Peter Clausen strict_scanmask); 9143862828aSAndy Shevchenko bitmap_free(compound_mask); 9156e509c4dSLars-Peter Clausen if (scan_mask == NULL) 9166e509c4dSLars-Peter Clausen return -EINVAL; 9176e509c4dSLars-Peter Clausen } else { 9186e509c4dSLars-Peter Clausen scan_mask = compound_mask; 9196e509c4dSLars-Peter Clausen } 9206e509c4dSLars-Peter Clausen 9216e509c4dSLars-Peter Clausen config->scan_bytes = iio_compute_scan_bytes(indio_dev, 9226e509c4dSLars-Peter Clausen scan_mask, scan_timestamp); 9236e509c4dSLars-Peter Clausen config->scan_mask = scan_mask; 9246e509c4dSLars-Peter Clausen config->scan_timestamp = scan_timestamp; 9256e509c4dSLars-Peter Clausen 9266e509c4dSLars-Peter Clausen return 0; 9276e509c4dSLars-Peter Clausen } 9286e509c4dSLars-Peter Clausen 92978c9981fSJonathan Cameron /** 93078c9981fSJonathan Cameron * struct iio_demux_table - table describing demux memcpy ops 93178c9981fSJonathan Cameron * @from: index to copy from 93278c9981fSJonathan Cameron * @to: index to copy to 93378c9981fSJonathan Cameron * @length: how many bytes to copy 93478c9981fSJonathan Cameron * @l: list head used for management 93578c9981fSJonathan Cameron */ 93678c9981fSJonathan Cameron struct iio_demux_table { 93778c9981fSJonathan Cameron unsigned from; 93878c9981fSJonathan Cameron unsigned to; 93978c9981fSJonathan Cameron unsigned length; 94078c9981fSJonathan Cameron struct list_head l; 94178c9981fSJonathan Cameron }; 94278c9981fSJonathan Cameron 94378c9981fSJonathan Cameron static void iio_buffer_demux_free(struct iio_buffer *buffer) 94478c9981fSJonathan Cameron { 94578c9981fSJonathan Cameron struct iio_demux_table *p, *q; 94678c9981fSJonathan Cameron list_for_each_entry_safe(p, q, &buffer->demux_list, l) { 94778c9981fSJonathan Cameron list_del(&p->l); 94878c9981fSJonathan Cameron kfree(p); 94978c9981fSJonathan Cameron } 95078c9981fSJonathan Cameron } 95178c9981fSJonathan Cameron 95278c9981fSJonathan Cameron static int iio_buffer_add_demux(struct iio_buffer *buffer, 95378c9981fSJonathan Cameron struct iio_demux_table **p, unsigned int in_loc, unsigned int out_loc, 95478c9981fSJonathan Cameron unsigned int length) 95578c9981fSJonathan Cameron { 95678c9981fSJonathan Cameron 95778c9981fSJonathan Cameron if (*p && (*p)->from + (*p)->length == in_loc && 95878c9981fSJonathan Cameron (*p)->to + (*p)->length == out_loc) { 95978c9981fSJonathan Cameron (*p)->length += length; 96078c9981fSJonathan Cameron } else { 96178c9981fSJonathan Cameron *p = kmalloc(sizeof(**p), GFP_KERNEL); 96278c9981fSJonathan Cameron if (*p == NULL) 96378c9981fSJonathan Cameron return -ENOMEM; 96478c9981fSJonathan Cameron (*p)->from = in_loc; 96578c9981fSJonathan Cameron (*p)->to = out_loc; 96678c9981fSJonathan Cameron (*p)->length = length; 96778c9981fSJonathan Cameron list_add_tail(&(*p)->l, &buffer->demux_list); 96878c9981fSJonathan Cameron } 96978c9981fSJonathan Cameron 97078c9981fSJonathan Cameron return 0; 97178c9981fSJonathan Cameron } 97278c9981fSJonathan Cameron 97378c9981fSJonathan Cameron static int iio_buffer_update_demux(struct iio_dev *indio_dev, 97478c9981fSJonathan Cameron struct iio_buffer *buffer) 97578c9981fSJonathan Cameron { 97678c9981fSJonathan Cameron int ret, in_ind = -1, out_ind, length; 97778c9981fSJonathan Cameron unsigned in_loc = 0, out_loc = 0; 97878c9981fSJonathan Cameron struct iio_demux_table *p = NULL; 97978c9981fSJonathan Cameron 98078c9981fSJonathan Cameron /* Clear out any old demux */ 98178c9981fSJonathan Cameron iio_buffer_demux_free(buffer); 98278c9981fSJonathan Cameron kfree(buffer->demux_bounce); 98378c9981fSJonathan Cameron buffer->demux_bounce = NULL; 98478c9981fSJonathan Cameron 98578c9981fSJonathan Cameron /* First work out which scan mode we will actually have */ 98678c9981fSJonathan Cameron if (bitmap_equal(indio_dev->active_scan_mask, 98778c9981fSJonathan Cameron buffer->scan_mask, 98878c9981fSJonathan Cameron indio_dev->masklength)) 98978c9981fSJonathan Cameron return 0; 99078c9981fSJonathan Cameron 99178c9981fSJonathan Cameron /* Now we have the two masks, work from least sig and build up sizes */ 99278c9981fSJonathan Cameron for_each_set_bit(out_ind, 99378c9981fSJonathan Cameron buffer->scan_mask, 99478c9981fSJonathan Cameron indio_dev->masklength) { 99578c9981fSJonathan Cameron in_ind = find_next_bit(indio_dev->active_scan_mask, 99678c9981fSJonathan Cameron indio_dev->masklength, 99778c9981fSJonathan Cameron in_ind + 1); 99878c9981fSJonathan Cameron while (in_ind != out_ind) { 99978c9981fSJonathan Cameron length = iio_storage_bytes_for_si(indio_dev, in_ind); 100078c9981fSJonathan Cameron /* Make sure we are aligned */ 100178c9981fSJonathan Cameron in_loc = roundup(in_loc, length) + length; 100219ef7b70SNuno Sá in_ind = find_next_bit(indio_dev->active_scan_mask, 100319ef7b70SNuno Sá indio_dev->masklength, 100419ef7b70SNuno Sá in_ind + 1); 100578c9981fSJonathan Cameron } 100678c9981fSJonathan Cameron length = iio_storage_bytes_for_si(indio_dev, in_ind); 100778c9981fSJonathan Cameron out_loc = roundup(out_loc, length); 100878c9981fSJonathan Cameron in_loc = roundup(in_loc, length); 100978c9981fSJonathan Cameron ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length); 101078c9981fSJonathan Cameron if (ret) 101178c9981fSJonathan Cameron goto error_clear_mux_table; 101278c9981fSJonathan Cameron out_loc += length; 101378c9981fSJonathan Cameron in_loc += length; 101478c9981fSJonathan Cameron } 101578c9981fSJonathan Cameron /* Relies on scan_timestamp being last */ 101678c9981fSJonathan Cameron if (buffer->scan_timestamp) { 101778c9981fSJonathan Cameron length = iio_storage_bytes_for_timestamp(indio_dev); 101878c9981fSJonathan Cameron out_loc = roundup(out_loc, length); 101978c9981fSJonathan Cameron in_loc = roundup(in_loc, length); 102078c9981fSJonathan Cameron ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length); 102178c9981fSJonathan Cameron if (ret) 102278c9981fSJonathan Cameron goto error_clear_mux_table; 102378c9981fSJonathan Cameron out_loc += length; 102478c9981fSJonathan Cameron } 102578c9981fSJonathan Cameron buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL); 102678c9981fSJonathan Cameron if (buffer->demux_bounce == NULL) { 102778c9981fSJonathan Cameron ret = -ENOMEM; 102878c9981fSJonathan Cameron goto error_clear_mux_table; 102978c9981fSJonathan Cameron } 103078c9981fSJonathan Cameron return 0; 103178c9981fSJonathan Cameron 103278c9981fSJonathan Cameron error_clear_mux_table: 103378c9981fSJonathan Cameron iio_buffer_demux_free(buffer); 103478c9981fSJonathan Cameron 103578c9981fSJonathan Cameron return ret; 103678c9981fSJonathan Cameron } 103778c9981fSJonathan Cameron 103878c9981fSJonathan Cameron static int iio_update_demux(struct iio_dev *indio_dev) 103978c9981fSJonathan Cameron { 10406a8c6b26SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 104178c9981fSJonathan Cameron struct iio_buffer *buffer; 104278c9981fSJonathan Cameron int ret; 104378c9981fSJonathan Cameron 10446a8c6b26SAlexandru Ardelean list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { 104578c9981fSJonathan Cameron ret = iio_buffer_update_demux(indio_dev, buffer); 104678c9981fSJonathan Cameron if (ret < 0) 104778c9981fSJonathan Cameron goto error_clear_mux_table; 104878c9981fSJonathan Cameron } 104978c9981fSJonathan Cameron return 0; 105078c9981fSJonathan Cameron 105178c9981fSJonathan Cameron error_clear_mux_table: 10526a8c6b26SAlexandru Ardelean list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) 105378c9981fSJonathan Cameron iio_buffer_demux_free(buffer); 105478c9981fSJonathan Cameron 105578c9981fSJonathan Cameron return ret; 105678c9981fSJonathan Cameron } 105778c9981fSJonathan Cameron 1058623d74e3SLars-Peter Clausen static int iio_enable_buffers(struct iio_dev *indio_dev, 1059623d74e3SLars-Peter Clausen struct iio_device_config *config) 1060623d74e3SLars-Peter Clausen { 10616a8c6b26SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1062e18a2ad4SLars-Peter Clausen struct iio_buffer *buffer; 1063623d74e3SLars-Peter Clausen int ret; 1064623d74e3SLars-Peter Clausen 1065623d74e3SLars-Peter Clausen indio_dev->active_scan_mask = config->scan_mask; 1066623d74e3SLars-Peter Clausen indio_dev->scan_timestamp = config->scan_timestamp; 1067623d74e3SLars-Peter Clausen indio_dev->scan_bytes = config->scan_bytes; 10685cb1a548SLars-Peter Clausen indio_dev->currentmode = config->mode; 1069623d74e3SLars-Peter Clausen 1070623d74e3SLars-Peter Clausen iio_update_demux(indio_dev); 1071623d74e3SLars-Peter Clausen 1072623d74e3SLars-Peter Clausen /* Wind up again */ 1073623d74e3SLars-Peter Clausen if (indio_dev->setup_ops->preenable) { 1074623d74e3SLars-Peter Clausen ret = indio_dev->setup_ops->preenable(indio_dev); 1075623d74e3SLars-Peter Clausen if (ret) { 1076623d74e3SLars-Peter Clausen dev_dbg(&indio_dev->dev, 1077623d74e3SLars-Peter Clausen "Buffer not started: buffer preenable failed (%d)\n", ret); 1078623d74e3SLars-Peter Clausen goto err_undo_config; 1079623d74e3SLars-Peter Clausen } 1080623d74e3SLars-Peter Clausen } 1081623d74e3SLars-Peter Clausen 1082623d74e3SLars-Peter Clausen if (indio_dev->info->update_scan_mode) { 1083623d74e3SLars-Peter Clausen ret = indio_dev->info 1084623d74e3SLars-Peter Clausen ->update_scan_mode(indio_dev, 1085623d74e3SLars-Peter Clausen indio_dev->active_scan_mask); 1086623d74e3SLars-Peter Clausen if (ret < 0) { 1087623d74e3SLars-Peter Clausen dev_dbg(&indio_dev->dev, 1088623d74e3SLars-Peter Clausen "Buffer not started: update scan mode failed (%d)\n", 1089623d74e3SLars-Peter Clausen ret); 1090623d74e3SLars-Peter Clausen goto err_run_postdisable; 1091623d74e3SLars-Peter Clausen } 1092623d74e3SLars-Peter Clausen } 1093623d74e3SLars-Peter Clausen 1094f0566c0cSLars-Peter Clausen if (indio_dev->info->hwfifo_set_watermark) 1095f0566c0cSLars-Peter Clausen indio_dev->info->hwfifo_set_watermark(indio_dev, 1096f0566c0cSLars-Peter Clausen config->watermark); 1097f0566c0cSLars-Peter Clausen 10986a8c6b26SAlexandru Ardelean list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { 1099e18a2ad4SLars-Peter Clausen ret = iio_buffer_enable(buffer, indio_dev); 1100e18a2ad4SLars-Peter Clausen if (ret) 1101e18a2ad4SLars-Peter Clausen goto err_disable_buffers; 1102e18a2ad4SLars-Peter Clausen } 1103e18a2ad4SLars-Peter Clausen 1104f11d59d8SLars-Peter Clausen if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { 1105f11d59d8SLars-Peter Clausen ret = iio_trigger_attach_poll_func(indio_dev->trig, 1106f11d59d8SLars-Peter Clausen indio_dev->pollfunc); 1107f11d59d8SLars-Peter Clausen if (ret) 1108f11d59d8SLars-Peter Clausen goto err_disable_buffers; 1109f11d59d8SLars-Peter Clausen } 1110f11d59d8SLars-Peter Clausen 111162a30a29SAlexandru Ardelean if (indio_dev->setup_ops->postenable) { 111262a30a29SAlexandru Ardelean ret = indio_dev->setup_ops->postenable(indio_dev); 111362a30a29SAlexandru Ardelean if (ret) { 111462a30a29SAlexandru Ardelean dev_dbg(&indio_dev->dev, 111562a30a29SAlexandru Ardelean "Buffer not started: postenable failed (%d)\n", ret); 111662a30a29SAlexandru Ardelean goto err_detach_pollfunc; 111762a30a29SAlexandru Ardelean } 111862a30a29SAlexandru Ardelean } 111962a30a29SAlexandru Ardelean 1120623d74e3SLars-Peter Clausen return 0; 1121623d74e3SLars-Peter Clausen 112262a30a29SAlexandru Ardelean err_detach_pollfunc: 112362a30a29SAlexandru Ardelean if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { 112462a30a29SAlexandru Ardelean iio_trigger_detach_poll_func(indio_dev->trig, 112562a30a29SAlexandru Ardelean indio_dev->pollfunc); 112662a30a29SAlexandru Ardelean } 1127e18a2ad4SLars-Peter Clausen err_disable_buffers: 11286a8c6b26SAlexandru Ardelean list_for_each_entry_continue_reverse(buffer, &iio_dev_opaque->buffer_list, 1129e18a2ad4SLars-Peter Clausen buffer_list) 1130e18a2ad4SLars-Peter Clausen iio_buffer_disable(buffer, indio_dev); 1131623d74e3SLars-Peter Clausen err_run_postdisable: 1132623d74e3SLars-Peter Clausen if (indio_dev->setup_ops->postdisable) 1133623d74e3SLars-Peter Clausen indio_dev->setup_ops->postdisable(indio_dev); 1134623d74e3SLars-Peter Clausen err_undo_config: 11355cb1a548SLars-Peter Clausen indio_dev->currentmode = INDIO_DIRECT_MODE; 1136623d74e3SLars-Peter Clausen indio_dev->active_scan_mask = NULL; 1137623d74e3SLars-Peter Clausen 1138623d74e3SLars-Peter Clausen return ret; 1139623d74e3SLars-Peter Clausen } 1140623d74e3SLars-Peter Clausen 1141623d74e3SLars-Peter Clausen static int iio_disable_buffers(struct iio_dev *indio_dev) 1142623d74e3SLars-Peter Clausen { 11436a8c6b26SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1144e18a2ad4SLars-Peter Clausen struct iio_buffer *buffer; 11451250186aSLars-Peter Clausen int ret = 0; 11461250186aSLars-Peter Clausen int ret2; 1147623d74e3SLars-Peter Clausen 1148623d74e3SLars-Peter Clausen /* Wind down existing buffers - iff there are any */ 11496a8c6b26SAlexandru Ardelean if (list_empty(&iio_dev_opaque->buffer_list)) 1150623d74e3SLars-Peter Clausen return 0; 1151623d74e3SLars-Peter Clausen 11521250186aSLars-Peter Clausen /* 11531250186aSLars-Peter Clausen * If things go wrong at some step in disable we still need to continue 11541250186aSLars-Peter Clausen * to perform the other steps, otherwise we leave the device in a 11551250186aSLars-Peter Clausen * inconsistent state. We return the error code for the first error we 11561250186aSLars-Peter Clausen * encountered. 11571250186aSLars-Peter Clausen */ 11581250186aSLars-Peter Clausen 1159623d74e3SLars-Peter Clausen if (indio_dev->setup_ops->predisable) { 11601250186aSLars-Peter Clausen ret2 = indio_dev->setup_ops->predisable(indio_dev); 11611250186aSLars-Peter Clausen if (ret2 && !ret) 11621250186aSLars-Peter Clausen ret = ret2; 1163623d74e3SLars-Peter Clausen } 1164623d74e3SLars-Peter Clausen 116562a30a29SAlexandru Ardelean if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { 116662a30a29SAlexandru Ardelean iio_trigger_detach_poll_func(indio_dev->trig, 116762a30a29SAlexandru Ardelean indio_dev->pollfunc); 116862a30a29SAlexandru Ardelean } 116962a30a29SAlexandru Ardelean 11706a8c6b26SAlexandru Ardelean list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { 1171e18a2ad4SLars-Peter Clausen ret2 = iio_buffer_disable(buffer, indio_dev); 1172e18a2ad4SLars-Peter Clausen if (ret2 && !ret) 1173e18a2ad4SLars-Peter Clausen ret = ret2; 1174e18a2ad4SLars-Peter Clausen } 1175e18a2ad4SLars-Peter Clausen 1176623d74e3SLars-Peter Clausen if (indio_dev->setup_ops->postdisable) { 11771250186aSLars-Peter Clausen ret2 = indio_dev->setup_ops->postdisable(indio_dev); 11781250186aSLars-Peter Clausen if (ret2 && !ret) 11791250186aSLars-Peter Clausen ret = ret2; 1180623d74e3SLars-Peter Clausen } 1181623d74e3SLars-Peter Clausen 11821250186aSLars-Peter Clausen iio_free_scan_mask(indio_dev, indio_dev->active_scan_mask); 11831250186aSLars-Peter Clausen indio_dev->active_scan_mask = NULL; 11845cb1a548SLars-Peter Clausen indio_dev->currentmode = INDIO_DIRECT_MODE; 11851250186aSLars-Peter Clausen 11861250186aSLars-Peter Clausen return ret; 1187623d74e3SLars-Peter Clausen } 1188623d74e3SLars-Peter Clausen 1189a9519456SLars-Peter Clausen static int __iio_update_buffers(struct iio_dev *indio_dev, 119084b36ce5SJonathan Cameron struct iio_buffer *insert_buffer, 119184b36ce5SJonathan Cameron struct iio_buffer *remove_buffer) 1192a980e046SJonathan Cameron { 11936a8c6b26SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 11946e509c4dSLars-Peter Clausen struct iio_device_config new_config; 11951250186aSLars-Peter Clausen int ret; 11966e509c4dSLars-Peter Clausen 11976e509c4dSLars-Peter Clausen ret = iio_verify_update(indio_dev, insert_buffer, remove_buffer, 11986e509c4dSLars-Peter Clausen &new_config); 11996e509c4dSLars-Peter Clausen if (ret) 12006e509c4dSLars-Peter Clausen return ret; 1201a980e046SJonathan Cameron 1202fcc1b2f5SLars-Peter Clausen if (insert_buffer) { 1203fcc1b2f5SLars-Peter Clausen ret = iio_buffer_request_update(indio_dev, insert_buffer); 1204fcc1b2f5SLars-Peter Clausen if (ret) 12056e509c4dSLars-Peter Clausen goto err_free_config; 1206fcc1b2f5SLars-Peter Clausen } 1207fcc1b2f5SLars-Peter Clausen 1208623d74e3SLars-Peter Clausen ret = iio_disable_buffers(indio_dev); 12091250186aSLars-Peter Clausen if (ret) 12101250186aSLars-Peter Clausen goto err_deactivate_all; 1211623d74e3SLars-Peter Clausen 121284b36ce5SJonathan Cameron if (remove_buffer) 12139e69c935SLars-Peter Clausen iio_buffer_deactivate(remove_buffer); 121484b36ce5SJonathan Cameron if (insert_buffer) 12159e69c935SLars-Peter Clausen iio_buffer_activate(indio_dev, insert_buffer); 121684b36ce5SJonathan Cameron 121784b36ce5SJonathan Cameron /* If no buffers in list, we are done */ 12186a8c6b26SAlexandru Ardelean if (list_empty(&iio_dev_opaque->buffer_list)) 121984b36ce5SJonathan Cameron return 0; 1220a980e046SJonathan Cameron 1221623d74e3SLars-Peter Clausen ret = iio_enable_buffers(indio_dev, &new_config); 12221250186aSLars-Peter Clausen if (ret) 12231250186aSLars-Peter Clausen goto err_deactivate_all; 1224623d74e3SLars-Peter Clausen 1225623d74e3SLars-Peter Clausen return 0; 12266e509c4dSLars-Peter Clausen 12271250186aSLars-Peter Clausen err_deactivate_all: 12281250186aSLars-Peter Clausen /* 12291250186aSLars-Peter Clausen * We've already verified that the config is valid earlier. If things go 12301250186aSLars-Peter Clausen * wrong in either enable or disable the most likely reason is an IO 12311250186aSLars-Peter Clausen * error from the device. In this case there is no good recovery 12321250186aSLars-Peter Clausen * strategy. Just make sure to disable everything and leave the device 12331250186aSLars-Peter Clausen * in a sane state. With a bit of luck the device might come back to 12341250186aSLars-Peter Clausen * life again later and userspace can try again. 12351250186aSLars-Peter Clausen */ 12361250186aSLars-Peter Clausen iio_buffer_deactivate_all(indio_dev); 12371250186aSLars-Peter Clausen 12386e509c4dSLars-Peter Clausen err_free_config: 12396e509c4dSLars-Peter Clausen iio_free_scan_mask(indio_dev, new_config.scan_mask); 12406e509c4dSLars-Peter Clausen return ret; 124184b36ce5SJonathan Cameron } 1242a9519456SLars-Peter Clausen 1243a9519456SLars-Peter Clausen int iio_update_buffers(struct iio_dev *indio_dev, 1244a9519456SLars-Peter Clausen struct iio_buffer *insert_buffer, 1245a9519456SLars-Peter Clausen struct iio_buffer *remove_buffer) 1246a9519456SLars-Peter Clausen { 1247b804e2b7SJonathan Cameron struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1248a9519456SLars-Peter Clausen int ret; 1249a9519456SLars-Peter Clausen 12503909fab5SLars-Peter Clausen if (insert_buffer == remove_buffer) 12513909fab5SLars-Peter Clausen return 0; 12523909fab5SLars-Peter Clausen 1253*9eeee3b0SMihail Chindris if (insert_buffer && 1254*9eeee3b0SMihail Chindris (insert_buffer->direction == IIO_BUFFER_DIRECTION_OUT)) 1255*9eeee3b0SMihail Chindris return -EINVAL; 1256*9eeee3b0SMihail Chindris 1257b804e2b7SJonathan Cameron mutex_lock(&iio_dev_opaque->info_exist_lock); 1258a9519456SLars-Peter Clausen mutex_lock(&indio_dev->mlock); 1259a9519456SLars-Peter Clausen 12603909fab5SLars-Peter Clausen if (insert_buffer && iio_buffer_is_active(insert_buffer)) 12613909fab5SLars-Peter Clausen insert_buffer = NULL; 12623909fab5SLars-Peter Clausen 12633909fab5SLars-Peter Clausen if (remove_buffer && !iio_buffer_is_active(remove_buffer)) 12643909fab5SLars-Peter Clausen remove_buffer = NULL; 12653909fab5SLars-Peter Clausen 12663909fab5SLars-Peter Clausen if (!insert_buffer && !remove_buffer) { 12673909fab5SLars-Peter Clausen ret = 0; 12683909fab5SLars-Peter Clausen goto out_unlock; 12693909fab5SLars-Peter Clausen } 12703909fab5SLars-Peter Clausen 1271a9519456SLars-Peter Clausen if (indio_dev->info == NULL) { 1272a9519456SLars-Peter Clausen ret = -ENODEV; 1273a9519456SLars-Peter Clausen goto out_unlock; 1274a9519456SLars-Peter Clausen } 1275a9519456SLars-Peter Clausen 1276a9519456SLars-Peter Clausen ret = __iio_update_buffers(indio_dev, insert_buffer, remove_buffer); 1277a9519456SLars-Peter Clausen 1278a9519456SLars-Peter Clausen out_unlock: 1279a9519456SLars-Peter Clausen mutex_unlock(&indio_dev->mlock); 1280b804e2b7SJonathan Cameron mutex_unlock(&iio_dev_opaque->info_exist_lock); 1281a9519456SLars-Peter Clausen 1282a9519456SLars-Peter Clausen return ret; 1283a9519456SLars-Peter Clausen } 128484b36ce5SJonathan Cameron EXPORT_SYMBOL_GPL(iio_update_buffers); 128584b36ce5SJonathan Cameron 1286623d74e3SLars-Peter Clausen void iio_disable_all_buffers(struct iio_dev *indio_dev) 1287623d74e3SLars-Peter Clausen { 1288623d74e3SLars-Peter Clausen iio_disable_buffers(indio_dev); 12891250186aSLars-Peter Clausen iio_buffer_deactivate_all(indio_dev); 1290623d74e3SLars-Peter Clausen } 1291623d74e3SLars-Peter Clausen 129208e7e0adSLars-Peter Clausen static ssize_t iio_buffer_store_enable(struct device *dev, 129384b36ce5SJonathan Cameron struct device_attribute *attr, 129484b36ce5SJonathan Cameron const char *buf, 129584b36ce5SJonathan Cameron size_t len) 129684b36ce5SJonathan Cameron { 129784b36ce5SJonathan Cameron int ret; 129884b36ce5SJonathan Cameron bool requested_state; 129984b36ce5SJonathan Cameron struct iio_dev *indio_dev = dev_to_iio_dev(dev); 130015097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 130184b36ce5SJonathan Cameron bool inlist; 130284b36ce5SJonathan Cameron 130384b36ce5SJonathan Cameron ret = strtobool(buf, &requested_state); 130484b36ce5SJonathan Cameron if (ret < 0) 130584b36ce5SJonathan Cameron return ret; 130684b36ce5SJonathan Cameron 130784b36ce5SJonathan Cameron mutex_lock(&indio_dev->mlock); 130884b36ce5SJonathan Cameron 130984b36ce5SJonathan Cameron /* Find out if it is in the list */ 1310ff3f7e04SAlexandru Ardelean inlist = iio_buffer_is_active(buffer); 131184b36ce5SJonathan Cameron /* Already in desired state */ 131284b36ce5SJonathan Cameron if (inlist == requested_state) 131384b36ce5SJonathan Cameron goto done; 131484b36ce5SJonathan Cameron 131584b36ce5SJonathan Cameron if (requested_state) 1316ff3f7e04SAlexandru Ardelean ret = __iio_update_buffers(indio_dev, buffer, NULL); 131784b36ce5SJonathan Cameron else 1318ff3f7e04SAlexandru Ardelean ret = __iio_update_buffers(indio_dev, NULL, buffer); 131984b36ce5SJonathan Cameron 132084b36ce5SJonathan Cameron done: 132184b36ce5SJonathan Cameron mutex_unlock(&indio_dev->mlock); 132284b36ce5SJonathan Cameron return (ret < 0) ? ret : len; 132384b36ce5SJonathan Cameron } 132484b36ce5SJonathan Cameron 132537d34556SJosselin Costanzi static ssize_t iio_buffer_show_watermark(struct device *dev, 132637d34556SJosselin Costanzi struct device_attribute *attr, 132737d34556SJosselin Costanzi char *buf) 132837d34556SJosselin Costanzi { 132915097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 133037d34556SJosselin Costanzi 133183ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%u\n", buffer->watermark); 133237d34556SJosselin Costanzi } 133337d34556SJosselin Costanzi 133437d34556SJosselin Costanzi static ssize_t iio_buffer_store_watermark(struct device *dev, 133537d34556SJosselin Costanzi struct device_attribute *attr, 133637d34556SJosselin Costanzi const char *buf, 133737d34556SJosselin Costanzi size_t len) 133837d34556SJosselin Costanzi { 133937d34556SJosselin Costanzi struct iio_dev *indio_dev = dev_to_iio_dev(dev); 134015097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 134137d34556SJosselin Costanzi unsigned int val; 134237d34556SJosselin Costanzi int ret; 134337d34556SJosselin Costanzi 134437d34556SJosselin Costanzi ret = kstrtouint(buf, 10, &val); 134537d34556SJosselin Costanzi if (ret) 134637d34556SJosselin Costanzi return ret; 134737d34556SJosselin Costanzi if (!val) 134837d34556SJosselin Costanzi return -EINVAL; 134937d34556SJosselin Costanzi 135037d34556SJosselin Costanzi mutex_lock(&indio_dev->mlock); 135137d34556SJosselin Costanzi 135237d34556SJosselin Costanzi if (val > buffer->length) { 135337d34556SJosselin Costanzi ret = -EINVAL; 135437d34556SJosselin Costanzi goto out; 135537d34556SJosselin Costanzi } 135637d34556SJosselin Costanzi 1357ff3f7e04SAlexandru Ardelean if (iio_buffer_is_active(buffer)) { 135837d34556SJosselin Costanzi ret = -EBUSY; 135937d34556SJosselin Costanzi goto out; 136037d34556SJosselin Costanzi } 136137d34556SJosselin Costanzi 136237d34556SJosselin Costanzi buffer->watermark = val; 136337d34556SJosselin Costanzi out: 136437d34556SJosselin Costanzi mutex_unlock(&indio_dev->mlock); 136537d34556SJosselin Costanzi 136637d34556SJosselin Costanzi return ret ? ret : len; 136737d34556SJosselin Costanzi } 136837d34556SJosselin Costanzi 1369350f6c75SMatt Fornero static ssize_t iio_dma_show_data_available(struct device *dev, 1370350f6c75SMatt Fornero struct device_attribute *attr, 1371350f6c75SMatt Fornero char *buf) 1372350f6c75SMatt Fornero { 137315097c7aSAlexandru Ardelean struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 1374350f6c75SMatt Fornero 137583ca56b6SLars-Peter Clausen return sysfs_emit(buf, "%zu\n", iio_buffer_data_available(buffer)); 1376350f6c75SMatt Fornero } 1377350f6c75SMatt Fornero 1378*9eeee3b0SMihail Chindris static ssize_t direction_show(struct device *dev, 1379*9eeee3b0SMihail Chindris struct device_attribute *attr, 1380*9eeee3b0SMihail Chindris char *buf) 1381*9eeee3b0SMihail Chindris { 1382*9eeee3b0SMihail Chindris struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 1383*9eeee3b0SMihail Chindris 1384*9eeee3b0SMihail Chindris switch (buffer->direction) { 1385*9eeee3b0SMihail Chindris case IIO_BUFFER_DIRECTION_IN: 1386*9eeee3b0SMihail Chindris return sprintf(buf, "in\n"); 1387*9eeee3b0SMihail Chindris case IIO_BUFFER_DIRECTION_OUT: 1388*9eeee3b0SMihail Chindris return sprintf(buf, "out\n"); 1389*9eeee3b0SMihail Chindris default: 1390*9eeee3b0SMihail Chindris return -EINVAL; 1391*9eeee3b0SMihail Chindris } 1392*9eeee3b0SMihail Chindris } 1393*9eeee3b0SMihail Chindris 139408e7e0adSLars-Peter Clausen static DEVICE_ATTR(length, S_IRUGO | S_IWUSR, iio_buffer_read_length, 139508e7e0adSLars-Peter Clausen iio_buffer_write_length); 13968d92db28SLars-Peter Clausen static struct device_attribute dev_attr_length_ro = __ATTR(length, 13978d92db28SLars-Peter Clausen S_IRUGO, iio_buffer_read_length, NULL); 139808e7e0adSLars-Peter Clausen static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, 139908e7e0adSLars-Peter Clausen iio_buffer_show_enable, iio_buffer_store_enable); 140037d34556SJosselin Costanzi static DEVICE_ATTR(watermark, S_IRUGO | S_IWUSR, 140137d34556SJosselin Costanzi iio_buffer_show_watermark, iio_buffer_store_watermark); 1402b440655bSLars-Peter Clausen static struct device_attribute dev_attr_watermark_ro = __ATTR(watermark, 1403b440655bSLars-Peter Clausen S_IRUGO, iio_buffer_show_watermark, NULL); 1404350f6c75SMatt Fornero static DEVICE_ATTR(data_available, S_IRUGO, 1405350f6c75SMatt Fornero iio_dma_show_data_available, NULL); 1406*9eeee3b0SMihail Chindris static DEVICE_ATTR_RO(direction); 140708e7e0adSLars-Peter Clausen 1408*9eeee3b0SMihail Chindris /* 1409*9eeee3b0SMihail Chindris * When adding new attributes here, put the at the end, at least until 1410*9eeee3b0SMihail Chindris * the code that handles the length/length_ro & watermark/watermark_ro 1411*9eeee3b0SMihail Chindris * assignments gets cleaned up. Otherwise these can create some weird 1412*9eeee3b0SMihail Chindris * duplicate attributes errors under some setups. 1413*9eeee3b0SMihail Chindris */ 14146da9b382SOctavian Purdila static struct attribute *iio_buffer_attrs[] = { 14156da9b382SOctavian Purdila &dev_attr_length.attr, 14166da9b382SOctavian Purdila &dev_attr_enable.attr, 141737d34556SJosselin Costanzi &dev_attr_watermark.attr, 1418350f6c75SMatt Fornero &dev_attr_data_available.attr, 1419*9eeee3b0SMihail Chindris &dev_attr_direction.attr, 14206da9b382SOctavian Purdila }; 14216da9b382SOctavian Purdila 142215097c7aSAlexandru Ardelean #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) 142315097c7aSAlexandru Ardelean 142415097c7aSAlexandru Ardelean static struct attribute *iio_buffer_wrap_attr(struct iio_buffer *buffer, 142515097c7aSAlexandru Ardelean struct attribute *attr) 142615097c7aSAlexandru Ardelean { 142715097c7aSAlexandru Ardelean struct device_attribute *dattr = to_dev_attr(attr); 142815097c7aSAlexandru Ardelean struct iio_dev_attr *iio_attr; 142915097c7aSAlexandru Ardelean 143015097c7aSAlexandru Ardelean iio_attr = kzalloc(sizeof(*iio_attr), GFP_KERNEL); 143115097c7aSAlexandru Ardelean if (!iio_attr) 143215097c7aSAlexandru Ardelean return NULL; 143315097c7aSAlexandru Ardelean 143415097c7aSAlexandru Ardelean iio_attr->buffer = buffer; 143515097c7aSAlexandru Ardelean memcpy(&iio_attr->dev_attr, dattr, sizeof(iio_attr->dev_attr)); 143615097c7aSAlexandru Ardelean iio_attr->dev_attr.attr.name = kstrdup_const(attr->name, GFP_KERNEL); 1437ca3e7d52SAlexandru Ardelean sysfs_attr_init(&iio_attr->dev_attr.attr); 143815097c7aSAlexandru Ardelean 143915097c7aSAlexandru Ardelean list_add(&iio_attr->l, &buffer->buffer_attr_list); 144015097c7aSAlexandru Ardelean 144115097c7aSAlexandru Ardelean return &iio_attr->dev_attr.attr; 144215097c7aSAlexandru Ardelean } 144315097c7aSAlexandru Ardelean 1444d9a62574SAlexandru Ardelean static int iio_buffer_register_legacy_sysfs_groups(struct iio_dev *indio_dev, 1445d9a62574SAlexandru Ardelean struct attribute **buffer_attrs, 1446d9a62574SAlexandru Ardelean int buffer_attrcount, 1447d9a62574SAlexandru Ardelean int scan_el_attrcount) 1448d9a62574SAlexandru Ardelean { 1449d9a62574SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1450d9a62574SAlexandru Ardelean struct attribute_group *group; 1451d9a62574SAlexandru Ardelean struct attribute **attrs; 1452d9a62574SAlexandru Ardelean int ret; 1453d9a62574SAlexandru Ardelean 1454d9a62574SAlexandru Ardelean attrs = kcalloc(buffer_attrcount + 1, sizeof(*attrs), GFP_KERNEL); 1455d9a62574SAlexandru Ardelean if (!attrs) 1456d9a62574SAlexandru Ardelean return -ENOMEM; 1457d9a62574SAlexandru Ardelean 1458d9a62574SAlexandru Ardelean memcpy(attrs, buffer_attrs, buffer_attrcount * sizeof(*attrs)); 1459d9a62574SAlexandru Ardelean 1460d9a62574SAlexandru Ardelean group = &iio_dev_opaque->legacy_buffer_group; 1461d9a62574SAlexandru Ardelean group->attrs = attrs; 1462d9a62574SAlexandru Ardelean group->name = "buffer"; 1463d9a62574SAlexandru Ardelean 1464d9a62574SAlexandru Ardelean ret = iio_device_register_sysfs_group(indio_dev, group); 1465d9a62574SAlexandru Ardelean if (ret) 1466d9a62574SAlexandru Ardelean goto error_free_buffer_attrs; 1467d9a62574SAlexandru Ardelean 1468d9a62574SAlexandru Ardelean attrs = kcalloc(scan_el_attrcount + 1, sizeof(*attrs), GFP_KERNEL); 1469d9a62574SAlexandru Ardelean if (!attrs) { 1470d9a62574SAlexandru Ardelean ret = -ENOMEM; 1471d9a62574SAlexandru Ardelean goto error_free_buffer_attrs; 1472d9a62574SAlexandru Ardelean } 1473d9a62574SAlexandru Ardelean 1474d9a62574SAlexandru Ardelean memcpy(attrs, &buffer_attrs[buffer_attrcount], 1475d9a62574SAlexandru Ardelean scan_el_attrcount * sizeof(*attrs)); 1476d9a62574SAlexandru Ardelean 1477d9a62574SAlexandru Ardelean group = &iio_dev_opaque->legacy_scan_el_group; 1478d9a62574SAlexandru Ardelean group->attrs = attrs; 1479d9a62574SAlexandru Ardelean group->name = "scan_elements"; 1480d9a62574SAlexandru Ardelean 1481d9a62574SAlexandru Ardelean ret = iio_device_register_sysfs_group(indio_dev, group); 1482d9a62574SAlexandru Ardelean if (ret) 1483d9a62574SAlexandru Ardelean goto error_free_scan_el_attrs; 1484d9a62574SAlexandru Ardelean 1485d9a62574SAlexandru Ardelean return 0; 1486d9a62574SAlexandru Ardelean 1487d9a62574SAlexandru Ardelean error_free_buffer_attrs: 1488d9a62574SAlexandru Ardelean kfree(iio_dev_opaque->legacy_buffer_group.attrs); 1489d9a62574SAlexandru Ardelean error_free_scan_el_attrs: 1490d9a62574SAlexandru Ardelean kfree(iio_dev_opaque->legacy_scan_el_group.attrs); 1491d9a62574SAlexandru Ardelean 1492d9a62574SAlexandru Ardelean return ret; 1493d9a62574SAlexandru Ardelean } 1494d9a62574SAlexandru Ardelean 1495d9a62574SAlexandru Ardelean static void iio_buffer_unregister_legacy_sysfs_groups(struct iio_dev *indio_dev) 1496d9a62574SAlexandru Ardelean { 1497d9a62574SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1498d9a62574SAlexandru Ardelean 1499d9a62574SAlexandru Ardelean kfree(iio_dev_opaque->legacy_buffer_group.attrs); 1500d9a62574SAlexandru Ardelean kfree(iio_dev_opaque->legacy_scan_el_group.attrs); 1501d9a62574SAlexandru Ardelean } 1502d9a62574SAlexandru Ardelean 1503f73f7f4dSAlexandru Ardelean static int iio_buffer_chrdev_release(struct inode *inode, struct file *filep) 1504f73f7f4dSAlexandru Ardelean { 1505f73f7f4dSAlexandru Ardelean struct iio_dev_buffer_pair *ib = filep->private_data; 1506f73f7f4dSAlexandru Ardelean struct iio_dev *indio_dev = ib->indio_dev; 1507f73f7f4dSAlexandru Ardelean struct iio_buffer *buffer = ib->buffer; 1508f73f7f4dSAlexandru Ardelean 1509f73f7f4dSAlexandru Ardelean wake_up(&buffer->pollq); 1510f73f7f4dSAlexandru Ardelean 1511f73f7f4dSAlexandru Ardelean kfree(ib); 1512f73f7f4dSAlexandru Ardelean clear_bit(IIO_BUSY_BIT_POS, &buffer->flags); 1513f73f7f4dSAlexandru Ardelean iio_device_put(indio_dev); 1514f73f7f4dSAlexandru Ardelean 1515f73f7f4dSAlexandru Ardelean return 0; 1516f73f7f4dSAlexandru Ardelean } 1517f73f7f4dSAlexandru Ardelean 1518f73f7f4dSAlexandru Ardelean static const struct file_operations iio_buffer_chrdev_fileops = { 1519f73f7f4dSAlexandru Ardelean .owner = THIS_MODULE, 1520f73f7f4dSAlexandru Ardelean .llseek = noop_llseek, 1521f73f7f4dSAlexandru Ardelean .read = iio_buffer_read, 1522*9eeee3b0SMihail Chindris .write = iio_buffer_write, 1523f73f7f4dSAlexandru Ardelean .poll = iio_buffer_poll, 1524f73f7f4dSAlexandru Ardelean .release = iio_buffer_chrdev_release, 1525f73f7f4dSAlexandru Ardelean }; 1526f73f7f4dSAlexandru Ardelean 1527f73f7f4dSAlexandru Ardelean static long iio_device_buffer_getfd(struct iio_dev *indio_dev, unsigned long arg) 1528f73f7f4dSAlexandru Ardelean { 1529f73f7f4dSAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1530f73f7f4dSAlexandru Ardelean int __user *ival = (int __user *)arg; 1531f73f7f4dSAlexandru Ardelean struct iio_dev_buffer_pair *ib; 1532f73f7f4dSAlexandru Ardelean struct iio_buffer *buffer; 1533f73f7f4dSAlexandru Ardelean int fd, idx, ret; 1534f73f7f4dSAlexandru Ardelean 1535f73f7f4dSAlexandru Ardelean if (copy_from_user(&idx, ival, sizeof(idx))) 1536f73f7f4dSAlexandru Ardelean return -EFAULT; 1537f73f7f4dSAlexandru Ardelean 1538f73f7f4dSAlexandru Ardelean if (idx >= iio_dev_opaque->attached_buffers_cnt) 1539f73f7f4dSAlexandru Ardelean return -ENODEV; 1540f73f7f4dSAlexandru Ardelean 1541f73f7f4dSAlexandru Ardelean iio_device_get(indio_dev); 1542f73f7f4dSAlexandru Ardelean 1543f73f7f4dSAlexandru Ardelean buffer = iio_dev_opaque->attached_buffers[idx]; 1544f73f7f4dSAlexandru Ardelean 1545f73f7f4dSAlexandru Ardelean if (test_and_set_bit(IIO_BUSY_BIT_POS, &buffer->flags)) { 1546f73f7f4dSAlexandru Ardelean ret = -EBUSY; 1547f73f7f4dSAlexandru Ardelean goto error_iio_dev_put; 1548f73f7f4dSAlexandru Ardelean } 1549f73f7f4dSAlexandru Ardelean 1550f73f7f4dSAlexandru Ardelean ib = kzalloc(sizeof(*ib), GFP_KERNEL); 1551f73f7f4dSAlexandru Ardelean if (!ib) { 1552f73f7f4dSAlexandru Ardelean ret = -ENOMEM; 1553f73f7f4dSAlexandru Ardelean goto error_clear_busy_bit; 1554f73f7f4dSAlexandru Ardelean } 1555f73f7f4dSAlexandru Ardelean 1556f73f7f4dSAlexandru Ardelean ib->indio_dev = indio_dev; 1557f73f7f4dSAlexandru Ardelean ib->buffer = buffer; 1558f73f7f4dSAlexandru Ardelean 1559f73f7f4dSAlexandru Ardelean fd = anon_inode_getfd("iio:buffer", &iio_buffer_chrdev_fileops, 1560f73f7f4dSAlexandru Ardelean ib, O_RDWR | O_CLOEXEC); 1561f73f7f4dSAlexandru Ardelean if (fd < 0) { 1562f73f7f4dSAlexandru Ardelean ret = fd; 1563f73f7f4dSAlexandru Ardelean goto error_free_ib; 1564f73f7f4dSAlexandru Ardelean } 1565f73f7f4dSAlexandru Ardelean 1566f73f7f4dSAlexandru Ardelean if (copy_to_user(ival, &fd, sizeof(fd))) { 1567f73f7f4dSAlexandru Ardelean put_unused_fd(fd); 1568f73f7f4dSAlexandru Ardelean ret = -EFAULT; 1569f73f7f4dSAlexandru Ardelean goto error_free_ib; 1570f73f7f4dSAlexandru Ardelean } 1571f73f7f4dSAlexandru Ardelean 15724c822244SAlexandru Ardelean return 0; 1573f73f7f4dSAlexandru Ardelean 1574f73f7f4dSAlexandru Ardelean error_free_ib: 1575f73f7f4dSAlexandru Ardelean kfree(ib); 1576f73f7f4dSAlexandru Ardelean error_clear_busy_bit: 1577f73f7f4dSAlexandru Ardelean clear_bit(IIO_BUSY_BIT_POS, &buffer->flags); 1578f73f7f4dSAlexandru Ardelean error_iio_dev_put: 1579f73f7f4dSAlexandru Ardelean iio_device_put(indio_dev); 1580f73f7f4dSAlexandru Ardelean return ret; 1581f73f7f4dSAlexandru Ardelean } 1582f73f7f4dSAlexandru Ardelean 1583f73f7f4dSAlexandru Ardelean static long iio_device_buffer_ioctl(struct iio_dev *indio_dev, struct file *filp, 1584f73f7f4dSAlexandru Ardelean unsigned int cmd, unsigned long arg) 1585f73f7f4dSAlexandru Ardelean { 1586f73f7f4dSAlexandru Ardelean switch (cmd) { 1587f73f7f4dSAlexandru Ardelean case IIO_BUFFER_GET_FD_IOCTL: 1588f73f7f4dSAlexandru Ardelean return iio_device_buffer_getfd(indio_dev, arg); 1589f73f7f4dSAlexandru Ardelean default: 1590f73f7f4dSAlexandru Ardelean return IIO_IOCTL_UNHANDLED; 1591f73f7f4dSAlexandru Ardelean } 1592f73f7f4dSAlexandru Ardelean } 1593f73f7f4dSAlexandru Ardelean 1594e16e0a77SAlexandru Ardelean static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, 1595d9a62574SAlexandru Ardelean struct iio_dev *indio_dev, 1596d9a62574SAlexandru Ardelean int index) 1597d967cb6bSLars-Peter Clausen { 159862f4f36cSJonathan Cameron struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1599d967cb6bSLars-Peter Clausen struct iio_dev_attr *p; 1600d967cb6bSLars-Peter Clausen struct attribute **attr; 1601e2b4d7acSAlexandru Ardelean int ret, i, attrn, scan_el_attrcount, buffer_attrcount; 1602d967cb6bSLars-Peter Clausen const struct iio_chan_spec *channels; 1603d967cb6bSLars-Peter Clausen 1604e2b4d7acSAlexandru Ardelean buffer_attrcount = 0; 160508e7e0adSLars-Peter Clausen if (buffer->attrs) { 1606e2b4d7acSAlexandru Ardelean while (buffer->attrs[buffer_attrcount] != NULL) 1607e2b4d7acSAlexandru Ardelean buffer_attrcount++; 160808e7e0adSLars-Peter Clausen } 160908e7e0adSLars-Peter Clausen 1610e2b4d7acSAlexandru Ardelean scan_el_attrcount = 0; 161115097c7aSAlexandru Ardelean INIT_LIST_HEAD(&buffer->buffer_attr_list); 1612d967cb6bSLars-Peter Clausen channels = indio_dev->channels; 1613d967cb6bSLars-Peter Clausen if (channels) { 1614d967cb6bSLars-Peter Clausen /* new magic */ 1615d967cb6bSLars-Peter Clausen for (i = 0; i < indio_dev->num_channels; i++) { 1616d967cb6bSLars-Peter Clausen if (channels[i].scan_index < 0) 1617d967cb6bSLars-Peter Clausen continue; 1618d967cb6bSLars-Peter Clausen 1619ff3f7e04SAlexandru Ardelean ret = iio_buffer_add_channel_sysfs(indio_dev, buffer, 1620d967cb6bSLars-Peter Clausen &channels[i]); 1621d967cb6bSLars-Peter Clausen if (ret < 0) 1622d967cb6bSLars-Peter Clausen goto error_cleanup_dynamic; 1623e2b4d7acSAlexandru Ardelean scan_el_attrcount += ret; 1624d967cb6bSLars-Peter Clausen if (channels[i].type == IIO_TIMESTAMP) 162562f4f36cSJonathan Cameron iio_dev_opaque->scan_index_timestamp = 1626d967cb6bSLars-Peter Clausen channels[i].scan_index; 1627d967cb6bSLars-Peter Clausen } 1628d967cb6bSLars-Peter Clausen if (indio_dev->masklength && buffer->scan_mask == NULL) { 16293862828aSAndy Shevchenko buffer->scan_mask = bitmap_zalloc(indio_dev->masklength, 1630d967cb6bSLars-Peter Clausen GFP_KERNEL); 1631d967cb6bSLars-Peter Clausen if (buffer->scan_mask == NULL) { 1632d967cb6bSLars-Peter Clausen ret = -ENOMEM; 1633d967cb6bSLars-Peter Clausen goto error_cleanup_dynamic; 1634d967cb6bSLars-Peter Clausen } 1635d967cb6bSLars-Peter Clausen } 1636d967cb6bSLars-Peter Clausen } 1637d967cb6bSLars-Peter Clausen 1638d9a62574SAlexandru Ardelean attrn = buffer_attrcount + scan_el_attrcount + ARRAY_SIZE(iio_buffer_attrs); 1639d9a62574SAlexandru Ardelean attr = kcalloc(attrn + 1, sizeof(* attr), GFP_KERNEL); 1640e2b4d7acSAlexandru Ardelean if (!attr) { 1641e2b4d7acSAlexandru Ardelean ret = -ENOMEM; 1642e2b4d7acSAlexandru Ardelean goto error_free_scan_mask; 1643e2b4d7acSAlexandru Ardelean } 1644e2b4d7acSAlexandru Ardelean 1645e2b4d7acSAlexandru Ardelean memcpy(attr, iio_buffer_attrs, sizeof(iio_buffer_attrs)); 1646e2b4d7acSAlexandru Ardelean if (!buffer->access->set_length) 1647e2b4d7acSAlexandru Ardelean attr[0] = &dev_attr_length_ro.attr; 1648e2b4d7acSAlexandru Ardelean 1649e2b4d7acSAlexandru Ardelean if (buffer->access->flags & INDIO_BUFFER_FLAG_FIXED_WATERMARK) 1650e2b4d7acSAlexandru Ardelean attr[2] = &dev_attr_watermark_ro.attr; 1651e2b4d7acSAlexandru Ardelean 1652e2b4d7acSAlexandru Ardelean if (buffer->attrs) 1653e2b4d7acSAlexandru Ardelean memcpy(&attr[ARRAY_SIZE(iio_buffer_attrs)], buffer->attrs, 1654e2b4d7acSAlexandru Ardelean sizeof(struct attribute *) * buffer_attrcount); 1655e2b4d7acSAlexandru Ardelean 1656e2b4d7acSAlexandru Ardelean buffer_attrcount += ARRAY_SIZE(iio_buffer_attrs); 1657e2b4d7acSAlexandru Ardelean 165815097c7aSAlexandru Ardelean for (i = 0; i < buffer_attrcount; i++) { 165915097c7aSAlexandru Ardelean struct attribute *wrapped; 1660d9a62574SAlexandru Ardelean 166115097c7aSAlexandru Ardelean wrapped = iio_buffer_wrap_attr(buffer, attr[i]); 166215097c7aSAlexandru Ardelean if (!wrapped) { 166315097c7aSAlexandru Ardelean ret = -ENOMEM; 166415097c7aSAlexandru Ardelean goto error_free_scan_mask; 166515097c7aSAlexandru Ardelean } 166615097c7aSAlexandru Ardelean attr[i] = wrapped; 166715097c7aSAlexandru Ardelean } 166815097c7aSAlexandru Ardelean 166915097c7aSAlexandru Ardelean attrn = 0; 167015097c7aSAlexandru Ardelean list_for_each_entry(p, &buffer->buffer_attr_list, l) 1671d9a62574SAlexandru Ardelean attr[attrn++] = &p->dev_attr.attr; 1672d9a62574SAlexandru Ardelean 1673d9a62574SAlexandru Ardelean buffer->buffer_group.name = kasprintf(GFP_KERNEL, "buffer%d", index); 1674d9a62574SAlexandru Ardelean if (!buffer->buffer_group.name) { 1675d9a62574SAlexandru Ardelean ret = -ENOMEM; 1676d9a62574SAlexandru Ardelean goto error_free_buffer_attrs; 1677d9a62574SAlexandru Ardelean } 1678d9a62574SAlexandru Ardelean 1679e2b4d7acSAlexandru Ardelean buffer->buffer_group.attrs = attr; 1680e2b4d7acSAlexandru Ardelean 1681e2b4d7acSAlexandru Ardelean ret = iio_device_register_sysfs_group(indio_dev, &buffer->buffer_group); 1682e2b4d7acSAlexandru Ardelean if (ret) 1683d9a62574SAlexandru Ardelean goto error_free_buffer_attr_group_name; 1684e2b4d7acSAlexandru Ardelean 1685d9a62574SAlexandru Ardelean /* we only need to register the legacy groups for the first buffer */ 1686d9a62574SAlexandru Ardelean if (index > 0) 1687d9a62574SAlexandru Ardelean return 0; 1688d967cb6bSLars-Peter Clausen 1689d9a62574SAlexandru Ardelean ret = iio_buffer_register_legacy_sysfs_groups(indio_dev, attr, 1690d9a62574SAlexandru Ardelean buffer_attrcount, 1691d9a62574SAlexandru Ardelean scan_el_attrcount); 169232f17172SAlexandru Ardelean if (ret) 1693d9a62574SAlexandru Ardelean goto error_free_buffer_attr_group_name; 1694d967cb6bSLars-Peter Clausen 1695d967cb6bSLars-Peter Clausen return 0; 1696d967cb6bSLars-Peter Clausen 1697d9a62574SAlexandru Ardelean error_free_buffer_attr_group_name: 1698d9a62574SAlexandru Ardelean kfree(buffer->buffer_group.name); 1699e2b4d7acSAlexandru Ardelean error_free_buffer_attrs: 1700e2b4d7acSAlexandru Ardelean kfree(buffer->buffer_group.attrs); 1701d967cb6bSLars-Peter Clausen error_free_scan_mask: 17023862828aSAndy Shevchenko bitmap_free(buffer->scan_mask); 1703d967cb6bSLars-Peter Clausen error_cleanup_dynamic: 170415097c7aSAlexandru Ardelean iio_free_chan_devattr_list(&buffer->buffer_attr_list); 1705d967cb6bSLars-Peter Clausen 1706d967cb6bSLars-Peter Clausen return ret; 1707d967cb6bSLars-Peter Clausen } 1708d967cb6bSLars-Peter Clausen 17090224af85SAlexandru Ardelean static void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer) 17100224af85SAlexandru Ardelean { 17110224af85SAlexandru Ardelean bitmap_free(buffer->scan_mask); 17120224af85SAlexandru Ardelean kfree(buffer->buffer_group.name); 17130224af85SAlexandru Ardelean kfree(buffer->buffer_group.attrs); 17140224af85SAlexandru Ardelean iio_free_chan_devattr_list(&buffer->buffer_attr_list); 17150224af85SAlexandru Ardelean } 17160224af85SAlexandru Ardelean 1717ee708e6bSAlexandru Ardelean int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev) 1718e16e0a77SAlexandru Ardelean { 1719ee708e6bSAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1720e16e0a77SAlexandru Ardelean const struct iio_chan_spec *channels; 1721ee708e6bSAlexandru Ardelean struct iio_buffer *buffer; 1722ee708e6bSAlexandru Ardelean int unwind_idx; 1723ee708e6bSAlexandru Ardelean int ret, i; 1724f73f7f4dSAlexandru Ardelean size_t sz; 1725e16e0a77SAlexandru Ardelean 1726e16e0a77SAlexandru Ardelean channels = indio_dev->channels; 1727e16e0a77SAlexandru Ardelean if (channels) { 1728e16e0a77SAlexandru Ardelean int ml = indio_dev->masklength; 1729e16e0a77SAlexandru Ardelean 1730e16e0a77SAlexandru Ardelean for (i = 0; i < indio_dev->num_channels; i++) 1731e16e0a77SAlexandru Ardelean ml = max(ml, channels[i].scan_index + 1); 1732e16e0a77SAlexandru Ardelean indio_dev->masklength = ml; 1733e16e0a77SAlexandru Ardelean } 1734e16e0a77SAlexandru Ardelean 1735ee708e6bSAlexandru Ardelean if (!iio_dev_opaque->attached_buffers_cnt) 1736e16e0a77SAlexandru Ardelean return 0; 1737e16e0a77SAlexandru Ardelean 1738ee708e6bSAlexandru Ardelean for (i = 0; i < iio_dev_opaque->attached_buffers_cnt; i++) { 1739ee708e6bSAlexandru Ardelean buffer = iio_dev_opaque->attached_buffers[i]; 1740ee708e6bSAlexandru Ardelean ret = __iio_buffer_alloc_sysfs_and_mask(buffer, indio_dev, i); 1741ee708e6bSAlexandru Ardelean if (ret) { 1742ee708e6bSAlexandru Ardelean unwind_idx = i; 1743ee708e6bSAlexandru Ardelean goto error_unwind_sysfs_and_mask; 1744ee708e6bSAlexandru Ardelean } 1745e16e0a77SAlexandru Ardelean } 1746f73f7f4dSAlexandru Ardelean unwind_idx = iio_dev_opaque->attached_buffers_cnt - 1; 1747f73f7f4dSAlexandru Ardelean 1748f73f7f4dSAlexandru Ardelean sz = sizeof(*(iio_dev_opaque->buffer_ioctl_handler)); 1749f73f7f4dSAlexandru Ardelean iio_dev_opaque->buffer_ioctl_handler = kzalloc(sz, GFP_KERNEL); 1750f73f7f4dSAlexandru Ardelean if (!iio_dev_opaque->buffer_ioctl_handler) { 1751f73f7f4dSAlexandru Ardelean ret = -ENOMEM; 1752f73f7f4dSAlexandru Ardelean goto error_unwind_sysfs_and_mask; 1753f73f7f4dSAlexandru Ardelean } 1754f73f7f4dSAlexandru Ardelean 1755f73f7f4dSAlexandru Ardelean iio_dev_opaque->buffer_ioctl_handler->ioctl = iio_device_buffer_ioctl; 1756f73f7f4dSAlexandru Ardelean iio_device_ioctl_handler_register(indio_dev, 1757f73f7f4dSAlexandru Ardelean iio_dev_opaque->buffer_ioctl_handler); 1758e16e0a77SAlexandru Ardelean 1759ee708e6bSAlexandru Ardelean return 0; 1760ff3f7e04SAlexandru Ardelean 1761ee708e6bSAlexandru Ardelean error_unwind_sysfs_and_mask: 1762ee708e6bSAlexandru Ardelean for (; unwind_idx >= 0; unwind_idx--) { 1763ee708e6bSAlexandru Ardelean buffer = iio_dev_opaque->attached_buffers[unwind_idx]; 1764ee708e6bSAlexandru Ardelean __iio_buffer_free_sysfs_and_mask(buffer); 1765ee708e6bSAlexandru Ardelean } 1766ee708e6bSAlexandru Ardelean return ret; 1767ee708e6bSAlexandru Ardelean } 1768ee708e6bSAlexandru Ardelean 1769ee708e6bSAlexandru Ardelean void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev) 1770ee708e6bSAlexandru Ardelean { 1771ee708e6bSAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1772ee708e6bSAlexandru Ardelean struct iio_buffer *buffer; 1773ee708e6bSAlexandru Ardelean int i; 1774ee708e6bSAlexandru Ardelean 1775ee708e6bSAlexandru Ardelean if (!iio_dev_opaque->attached_buffers_cnt) 1776d967cb6bSLars-Peter Clausen return; 1777d967cb6bSLars-Peter Clausen 1778f73f7f4dSAlexandru Ardelean iio_device_ioctl_handler_unregister(iio_dev_opaque->buffer_ioctl_handler); 1779f73f7f4dSAlexandru Ardelean kfree(iio_dev_opaque->buffer_ioctl_handler); 1780f73f7f4dSAlexandru Ardelean 1781d9a62574SAlexandru Ardelean iio_buffer_unregister_legacy_sysfs_groups(indio_dev); 1782d9a62574SAlexandru Ardelean 1783ee708e6bSAlexandru Ardelean for (i = iio_dev_opaque->attached_buffers_cnt - 1; i >= 0; i--) { 1784ee708e6bSAlexandru Ardelean buffer = iio_dev_opaque->attached_buffers[i]; 1785e16e0a77SAlexandru Ardelean __iio_buffer_free_sysfs_and_mask(buffer); 1786d967cb6bSLars-Peter Clausen } 1787ee708e6bSAlexandru Ardelean } 1788ee708e6bSAlexandru Ardelean 1789a980e046SJonathan Cameron /** 179081636632SLars-Peter Clausen * iio_validate_scan_mask_onehot() - Validates that exactly one channel is selected 179181636632SLars-Peter Clausen * @indio_dev: the iio device 179281636632SLars-Peter Clausen * @mask: scan mask to be checked 179381636632SLars-Peter Clausen * 179481636632SLars-Peter Clausen * Return true if exactly one bit is set in the scan mask, false otherwise. It 179581636632SLars-Peter Clausen * can be used for devices where only one channel can be active for sampling at 179681636632SLars-Peter Clausen * a time. 179781636632SLars-Peter Clausen */ 179881636632SLars-Peter Clausen bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev, 179981636632SLars-Peter Clausen const unsigned long *mask) 180081636632SLars-Peter Clausen { 180181636632SLars-Peter Clausen return bitmap_weight(mask, indio_dev->masklength) == 1; 180281636632SLars-Peter Clausen } 180381636632SLars-Peter Clausen EXPORT_SYMBOL_GPL(iio_validate_scan_mask_onehot); 180481636632SLars-Peter Clausen 18055d65d920SLars-Peter Clausen static const void *iio_demux(struct iio_buffer *buffer, 18065d65d920SLars-Peter Clausen const void *datain) 1807a980e046SJonathan Cameron { 1808a980e046SJonathan Cameron struct iio_demux_table *t; 1809a980e046SJonathan Cameron 1810a980e046SJonathan Cameron if (list_empty(&buffer->demux_list)) 1811a980e046SJonathan Cameron return datain; 1812a980e046SJonathan Cameron list_for_each_entry(t, &buffer->demux_list, l) 1813a980e046SJonathan Cameron memcpy(buffer->demux_bounce + t->to, 1814a980e046SJonathan Cameron datain + t->from, t->length); 1815a980e046SJonathan Cameron 1816a980e046SJonathan Cameron return buffer->demux_bounce; 1817a980e046SJonathan Cameron } 1818a980e046SJonathan Cameron 18195d65d920SLars-Peter Clausen static int iio_push_to_buffer(struct iio_buffer *buffer, const void *data) 1820a980e046SJonathan Cameron { 18215d65d920SLars-Peter Clausen const void *dataout = iio_demux(buffer, data); 182237d34556SJosselin Costanzi int ret; 1823a980e046SJonathan Cameron 182437d34556SJosselin Costanzi ret = buffer->access->store_to(buffer, dataout); 182537d34556SJosselin Costanzi if (ret) 182637d34556SJosselin Costanzi return ret; 182737d34556SJosselin Costanzi 182837d34556SJosselin Costanzi /* 182937d34556SJosselin Costanzi * We can't just test for watermark to decide if we wake the poll queue 183037d34556SJosselin Costanzi * because read may request less samples than the watermark. 183137d34556SJosselin Costanzi */ 1832a9a08845SLinus Torvalds wake_up_interruptible_poll(&buffer->pollq, EPOLLIN | EPOLLRDNORM); 183337d34556SJosselin Costanzi return 0; 1834a980e046SJonathan Cameron } 1835a980e046SJonathan Cameron 1836315a19ecSJonathan Cameron /** 1837315a19ecSJonathan Cameron * iio_push_to_buffers() - push to a registered buffer. 1838315a19ecSJonathan Cameron * @indio_dev: iio_dev structure for device. 1839315a19ecSJonathan Cameron * @data: Full scan. 1840315a19ecSJonathan Cameron */ 18415d65d920SLars-Peter Clausen int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data) 184284b36ce5SJonathan Cameron { 18436a8c6b26SAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 184484b36ce5SJonathan Cameron int ret; 184584b36ce5SJonathan Cameron struct iio_buffer *buf; 184684b36ce5SJonathan Cameron 18476a8c6b26SAlexandru Ardelean list_for_each_entry(buf, &iio_dev_opaque->buffer_list, buffer_list) { 184884b36ce5SJonathan Cameron ret = iio_push_to_buffer(buf, data); 184984b36ce5SJonathan Cameron if (ret < 0) 185084b36ce5SJonathan Cameron return ret; 185184b36ce5SJonathan Cameron } 185284b36ce5SJonathan Cameron 185384b36ce5SJonathan Cameron return 0; 185484b36ce5SJonathan Cameron } 185584b36ce5SJonathan Cameron EXPORT_SYMBOL_GPL(iio_push_to_buffers); 185684b36ce5SJonathan Cameron 18579e69c935SLars-Peter Clausen /** 185895ec3fdfSJonathan Cameron * iio_push_to_buffers_with_ts_unaligned() - push to registered buffer, 185995ec3fdfSJonathan Cameron * no alignment or space requirements. 186095ec3fdfSJonathan Cameron * @indio_dev: iio_dev structure for device. 186195ec3fdfSJonathan Cameron * @data: channel data excluding the timestamp. 186295ec3fdfSJonathan Cameron * @data_sz: size of data. 186395ec3fdfSJonathan Cameron * @timestamp: timestamp for the sample data. 186495ec3fdfSJonathan Cameron * 186595ec3fdfSJonathan Cameron * This special variant of iio_push_to_buffers_with_timestamp() does 186695ec3fdfSJonathan Cameron * not require space for the timestamp, or 8 byte alignment of data. 186795ec3fdfSJonathan Cameron * It does however require an allocation on first call and additional 186895ec3fdfSJonathan Cameron * copies on all calls, so should be avoided if possible. 186995ec3fdfSJonathan Cameron */ 187095ec3fdfSJonathan Cameron int iio_push_to_buffers_with_ts_unaligned(struct iio_dev *indio_dev, 187195ec3fdfSJonathan Cameron const void *data, 187295ec3fdfSJonathan Cameron size_t data_sz, 187395ec3fdfSJonathan Cameron int64_t timestamp) 187495ec3fdfSJonathan Cameron { 187595ec3fdfSJonathan Cameron struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 187695ec3fdfSJonathan Cameron 187795ec3fdfSJonathan Cameron /* 187895ec3fdfSJonathan Cameron * Conservative estimate - we can always safely copy the minimum 187995ec3fdfSJonathan Cameron * of either the data provided or the length of the destination buffer. 188095ec3fdfSJonathan Cameron * This relaxed limit allows the calling drivers to be lax about 188195ec3fdfSJonathan Cameron * tracking the size of the data they are pushing, at the cost of 188295ec3fdfSJonathan Cameron * unnecessary copying of padding. 188395ec3fdfSJonathan Cameron */ 188495ec3fdfSJonathan Cameron data_sz = min_t(size_t, indio_dev->scan_bytes, data_sz); 188595ec3fdfSJonathan Cameron if (iio_dev_opaque->bounce_buffer_size != indio_dev->scan_bytes) { 188695ec3fdfSJonathan Cameron void *bb; 188795ec3fdfSJonathan Cameron 188895ec3fdfSJonathan Cameron bb = devm_krealloc(&indio_dev->dev, 188995ec3fdfSJonathan Cameron iio_dev_opaque->bounce_buffer, 189095ec3fdfSJonathan Cameron indio_dev->scan_bytes, GFP_KERNEL); 189195ec3fdfSJonathan Cameron if (!bb) 189295ec3fdfSJonathan Cameron return -ENOMEM; 189395ec3fdfSJonathan Cameron iio_dev_opaque->bounce_buffer = bb; 189495ec3fdfSJonathan Cameron iio_dev_opaque->bounce_buffer_size = indio_dev->scan_bytes; 189595ec3fdfSJonathan Cameron } 189695ec3fdfSJonathan Cameron memcpy(iio_dev_opaque->bounce_buffer, data, data_sz); 189795ec3fdfSJonathan Cameron return iio_push_to_buffers_with_timestamp(indio_dev, 189895ec3fdfSJonathan Cameron iio_dev_opaque->bounce_buffer, 189995ec3fdfSJonathan Cameron timestamp); 190095ec3fdfSJonathan Cameron } 190195ec3fdfSJonathan Cameron EXPORT_SYMBOL_GPL(iio_push_to_buffers_with_ts_unaligned); 190295ec3fdfSJonathan Cameron 190395ec3fdfSJonathan Cameron /** 19049e69c935SLars-Peter Clausen * iio_buffer_release() - Free a buffer's resources 19059e69c935SLars-Peter Clausen * @ref: Pointer to the kref embedded in the iio_buffer struct 19069e69c935SLars-Peter Clausen * 19079e69c935SLars-Peter Clausen * This function is called when the last reference to the buffer has been 19089e69c935SLars-Peter Clausen * dropped. It will typically free all resources allocated by the buffer. Do not 19099e69c935SLars-Peter Clausen * call this function manually, always use iio_buffer_put() when done using a 19109e69c935SLars-Peter Clausen * buffer. 19119e69c935SLars-Peter Clausen */ 19129e69c935SLars-Peter Clausen static void iio_buffer_release(struct kref *ref) 19139e69c935SLars-Peter Clausen { 19149e69c935SLars-Peter Clausen struct iio_buffer *buffer = container_of(ref, struct iio_buffer, ref); 19159e69c935SLars-Peter Clausen 19169e69c935SLars-Peter Clausen buffer->access->release(buffer); 19179e69c935SLars-Peter Clausen } 19189e69c935SLars-Peter Clausen 19199e69c935SLars-Peter Clausen /** 19209e69c935SLars-Peter Clausen * iio_buffer_get() - Grab a reference to the buffer 19219e69c935SLars-Peter Clausen * @buffer: The buffer to grab a reference for, may be NULL 19229e69c935SLars-Peter Clausen * 19239e69c935SLars-Peter Clausen * Returns the pointer to the buffer that was passed into the function. 19249e69c935SLars-Peter Clausen */ 19259e69c935SLars-Peter Clausen struct iio_buffer *iio_buffer_get(struct iio_buffer *buffer) 19269e69c935SLars-Peter Clausen { 19279e69c935SLars-Peter Clausen if (buffer) 19289e69c935SLars-Peter Clausen kref_get(&buffer->ref); 19299e69c935SLars-Peter Clausen 19309e69c935SLars-Peter Clausen return buffer; 19319e69c935SLars-Peter Clausen } 19329e69c935SLars-Peter Clausen EXPORT_SYMBOL_GPL(iio_buffer_get); 19339e69c935SLars-Peter Clausen 19349e69c935SLars-Peter Clausen /** 19359e69c935SLars-Peter Clausen * iio_buffer_put() - Release the reference to the buffer 19369e69c935SLars-Peter Clausen * @buffer: The buffer to release the reference for, may be NULL 19379e69c935SLars-Peter Clausen */ 19389e69c935SLars-Peter Clausen void iio_buffer_put(struct iio_buffer *buffer) 19399e69c935SLars-Peter Clausen { 19409e69c935SLars-Peter Clausen if (buffer) 19419e69c935SLars-Peter Clausen kref_put(&buffer->ref, iio_buffer_release); 19429e69c935SLars-Peter Clausen } 19439e69c935SLars-Peter Clausen EXPORT_SYMBOL_GPL(iio_buffer_put); 19442b827ad5SJonathan Cameron 19452b827ad5SJonathan Cameron /** 19462b827ad5SJonathan Cameron * iio_device_attach_buffer - Attach a buffer to a IIO device 19472b827ad5SJonathan Cameron * @indio_dev: The device the buffer should be attached to 19482b827ad5SJonathan Cameron * @buffer: The buffer to attach to the device 19492b827ad5SJonathan Cameron * 1950ee708e6bSAlexandru Ardelean * Return 0 if successful, negative if error. 1951ee708e6bSAlexandru Ardelean * 19522b827ad5SJonathan Cameron * This function attaches a buffer to a IIO device. The buffer stays attached to 1953ee708e6bSAlexandru Ardelean * the device until the device is freed. For legacy reasons, the first attached 1954ee708e6bSAlexandru Ardelean * buffer will also be assigned to 'indio_dev->buffer'. 1955218bc53dSAlexandru Ardelean * The array allocated here, will be free'd via the iio_device_detach_buffers() 1956218bc53dSAlexandru Ardelean * call which is handled by the iio_device_free(). 19572b827ad5SJonathan Cameron */ 1958ee708e6bSAlexandru Ardelean int iio_device_attach_buffer(struct iio_dev *indio_dev, 19592b827ad5SJonathan Cameron struct iio_buffer *buffer) 19602b827ad5SJonathan Cameron { 1961ee708e6bSAlexandru Ardelean struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1962ee708e6bSAlexandru Ardelean struct iio_buffer **new, **old = iio_dev_opaque->attached_buffers; 1963ee708e6bSAlexandru Ardelean unsigned int cnt = iio_dev_opaque->attached_buffers_cnt; 1964ee708e6bSAlexandru Ardelean 1965ee708e6bSAlexandru Ardelean cnt++; 1966ee708e6bSAlexandru Ardelean 1967ee708e6bSAlexandru Ardelean new = krealloc(old, sizeof(*new) * cnt, GFP_KERNEL); 1968ee708e6bSAlexandru Ardelean if (!new) 1969ee708e6bSAlexandru Ardelean return -ENOMEM; 1970ee708e6bSAlexandru Ardelean iio_dev_opaque->attached_buffers = new; 1971ee708e6bSAlexandru Ardelean 1972ee708e6bSAlexandru Ardelean buffer = iio_buffer_get(buffer); 1973ee708e6bSAlexandru Ardelean 1974ee708e6bSAlexandru Ardelean /* first buffer is legacy; attach it to the IIO device directly */ 1975ee708e6bSAlexandru Ardelean if (!indio_dev->buffer) 1976ee708e6bSAlexandru Ardelean indio_dev->buffer = buffer; 1977ee708e6bSAlexandru Ardelean 1978ee708e6bSAlexandru Ardelean iio_dev_opaque->attached_buffers[cnt - 1] = buffer; 1979ee708e6bSAlexandru Ardelean iio_dev_opaque->attached_buffers_cnt = cnt; 1980ee708e6bSAlexandru Ardelean 1981ee708e6bSAlexandru Ardelean return 0; 19822b827ad5SJonathan Cameron } 19832b827ad5SJonathan Cameron EXPORT_SYMBOL_GPL(iio_device_attach_buffer); 1984