Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: Add output buffer support

Currently IIO only supports buffer mode for capture devices like ADCs. Add
support for buffered mode for output devices like DACs.

The output buffer implementation is analogous to the input buffer
implementation. Instead of using read() to get data from the buffer write()
is used to copy data into the buffer.

poll() with POLLOUT will wakeup if there is space available.

Drivers can remove data from a buffer using iio_pop_from_buffer(), the
function can e.g. called from a trigger handler to write the data to
hardware.

A buffer can only be either a output buffer or an input, but not both. So,
for a device that has an ADC and DAC path, this will mean 2 IIO buffers
(one for each direction).

The direction of the buffer is decided by the new direction field of the
iio_buffer struct and should be set after allocating and before registering
it.

Co-developed-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Co-developed-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
Signed-off-by: Mihail Chindris <mihail.chindris@analog.com>
Link: https://lore.kernel.org/r/20211007080035.2531-2-mihail.chindris@analog.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Mihail Chindris and committed by
Jonathan Cameron
9eeee3b0 d6fa1406

+148 -2
+4
drivers/iio/iio_core.h
··· 68 68 struct poll_table_struct *wait); 69 69 ssize_t iio_buffer_read_wrapper(struct file *filp, char __user *buf, 70 70 size_t n, loff_t *f_ps); 71 + ssize_t iio_buffer_write_wrapper(struct file *filp, const char __user *buf, 72 + size_t n, loff_t *f_ps); 71 73 72 74 int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev); 73 75 void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev); 74 76 75 77 #define iio_buffer_poll_addr (&iio_buffer_poll_wrapper) 76 78 #define iio_buffer_read_outer_addr (&iio_buffer_read_wrapper) 79 + #define iio_buffer_write_outer_addr (&iio_buffer_write_wrapper) 77 80 78 81 void iio_disable_all_buffers(struct iio_dev *indio_dev); 79 82 void iio_buffer_wakeup_poll(struct iio_dev *indio_dev); ··· 86 83 87 84 #define iio_buffer_poll_addr NULL 88 85 #define iio_buffer_read_outer_addr NULL 86 + #define iio_buffer_write_outer_addr NULL 89 87 90 88 static inline int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev) 91 89 {
+125 -2
drivers/iio/industrialio-buffer.c
··· 120 120 if (!rb || !rb->access->read) 121 121 return -EINVAL; 122 122 123 + if (rb->direction != IIO_BUFFER_DIRECTION_IN) 124 + return -EPERM; 125 + 123 126 datum_size = rb->bytes_per_datum; 124 127 125 128 /* ··· 164 161 return ret; 165 162 } 166 163 164 + static size_t iio_buffer_space_available(struct iio_buffer *buf) 165 + { 166 + if (buf->access->space_available) 167 + return buf->access->space_available(buf); 168 + 169 + return SIZE_MAX; 170 + } 171 + 172 + static ssize_t iio_buffer_write(struct file *filp, const char __user *buf, 173 + size_t n, loff_t *f_ps) 174 + { 175 + struct iio_dev_buffer_pair *ib = filp->private_data; 176 + struct iio_buffer *rb = ib->buffer; 177 + struct iio_dev *indio_dev = ib->indio_dev; 178 + DEFINE_WAIT_FUNC(wait, woken_wake_function); 179 + int ret; 180 + size_t written; 181 + 182 + if (!indio_dev->info) 183 + return -ENODEV; 184 + 185 + if (!rb || !rb->access->write) 186 + return -EINVAL; 187 + 188 + if (rb->direction != IIO_BUFFER_DIRECTION_OUT) 189 + return -EPERM; 190 + 191 + written = 0; 192 + add_wait_queue(&rb->pollq, &wait); 193 + do { 194 + if (indio_dev->info == NULL) 195 + return -ENODEV; 196 + 197 + if (!iio_buffer_space_available(rb)) { 198 + if (signal_pending(current)) { 199 + ret = -ERESTARTSYS; 200 + break; 201 + } 202 + 203 + wait_woken(&wait, TASK_INTERRUPTIBLE, 204 + MAX_SCHEDULE_TIMEOUT); 205 + continue; 206 + } 207 + 208 + ret = rb->access->write(rb, n - written, buf + written); 209 + if (ret == 0 && (filp->f_flags & O_NONBLOCK)) 210 + ret = -EAGAIN; 211 + 212 + if (ret > 0) { 213 + written += ret; 214 + if (written != n && !(filp->f_flags & O_NONBLOCK)) 215 + continue; 216 + } 217 + } while (ret == 0); 218 + remove_wait_queue(&rb->pollq, &wait); 219 + 220 + return ret < 0 ? ret : n; 221 + } 222 + 167 223 /** 168 224 * iio_buffer_poll() - poll the buffer to find out if it has data 169 225 * @filp: File structure pointer for device access ··· 243 181 return 0; 244 182 245 183 poll_wait(filp, &rb->pollq, wait); 246 - if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0)) 247 - return EPOLLIN | EPOLLRDNORM; 184 + 185 + switch (rb->direction) { 186 + case IIO_BUFFER_DIRECTION_IN: 187 + if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0)) 188 + return EPOLLIN | EPOLLRDNORM; 189 + break; 190 + case IIO_BUFFER_DIRECTION_OUT: 191 + if (iio_buffer_space_available(rb)) 192 + return EPOLLOUT | EPOLLWRNORM; 193 + break; 194 + } 195 + 248 196 return 0; 249 197 } 250 198 ··· 269 197 return -EBUSY; 270 198 271 199 return iio_buffer_read(filp, buf, n, f_ps); 200 + } 201 + 202 + ssize_t iio_buffer_write_wrapper(struct file *filp, const char __user *buf, 203 + size_t n, loff_t *f_ps) 204 + { 205 + struct iio_dev_buffer_pair *ib = filp->private_data; 206 + struct iio_buffer *rb = ib->buffer; 207 + 208 + /* check if buffer was opened through new API */ 209 + if (test_bit(IIO_BUSY_BIT_POS, &rb->flags)) 210 + return -EBUSY; 211 + 212 + return iio_buffer_write(filp, buf, n, f_ps); 272 213 } 273 214 274 215 __poll_t iio_buffer_poll_wrapper(struct file *filp, ··· 315 230 wake_up(&buffer->pollq); 316 231 } 317 232 } 233 + 234 + int iio_pop_from_buffer(struct iio_buffer *buffer, void *data) 235 + { 236 + if (!buffer || !buffer->access || !buffer->access->remove_from) 237 + return -EINVAL; 238 + 239 + return buffer->access->remove_from(buffer, data); 240 + } 241 + EXPORT_SYMBOL_GPL(iio_pop_from_buffer); 318 242 319 243 void iio_buffer_init(struct iio_buffer *buffer) 320 244 { ··· 1250 1156 if (insert_buffer == remove_buffer) 1251 1157 return 0; 1252 1158 1159 + if (insert_buffer && 1160 + (insert_buffer->direction == IIO_BUFFER_DIRECTION_OUT)) 1161 + return -EINVAL; 1162 + 1253 1163 mutex_lock(&iio_dev_opaque->info_exist_lock); 1254 1164 mutex_lock(&indio_dev->mlock); 1255 1165 ··· 1375 1277 return sysfs_emit(buf, "%zu\n", iio_buffer_data_available(buffer)); 1376 1278 } 1377 1279 1280 + static ssize_t direction_show(struct device *dev, 1281 + struct device_attribute *attr, 1282 + char *buf) 1283 + { 1284 + struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer; 1285 + 1286 + switch (buffer->direction) { 1287 + case IIO_BUFFER_DIRECTION_IN: 1288 + return sprintf(buf, "in\n"); 1289 + case IIO_BUFFER_DIRECTION_OUT: 1290 + return sprintf(buf, "out\n"); 1291 + default: 1292 + return -EINVAL; 1293 + } 1294 + } 1295 + 1378 1296 static DEVICE_ATTR(length, S_IRUGO | S_IWUSR, iio_buffer_read_length, 1379 1297 iio_buffer_write_length); 1380 1298 static struct device_attribute dev_attr_length_ro = __ATTR(length, ··· 1403 1289 S_IRUGO, iio_buffer_show_watermark, NULL); 1404 1290 static DEVICE_ATTR(data_available, S_IRUGO, 1405 1291 iio_dma_show_data_available, NULL); 1292 + static DEVICE_ATTR_RO(direction); 1406 1293 1294 + /* 1295 + * When adding new attributes here, put the at the end, at least until 1296 + * the code that handles the length/length_ro & watermark/watermark_ro 1297 + * assignments gets cleaned up. Otherwise these can create some weird 1298 + * duplicate attributes errors under some setups. 1299 + */ 1407 1300 static struct attribute *iio_buffer_attrs[] = { 1408 1301 &dev_attr_length.attr, 1409 1302 &dev_attr_enable.attr, 1410 1303 &dev_attr_watermark.attr, 1411 1304 &dev_attr_data_available.attr, 1305 + &dev_attr_direction.attr, 1412 1306 }; 1413 1307 1414 1308 #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) ··· 1519 1397 .owner = THIS_MODULE, 1520 1398 .llseek = noop_llseek, 1521 1399 .read = iio_buffer_read, 1400 + .write = iio_buffer_write, 1522 1401 .poll = iio_buffer_poll, 1523 1402 .release = iio_buffer_chrdev_release, 1524 1403 };
+1
drivers/iio/industrialio-core.c
··· 1822 1822 .owner = THIS_MODULE, 1823 1823 .llseek = noop_llseek, 1824 1824 .read = iio_buffer_read_outer_addr, 1825 + .write = iio_buffer_write_outer_addr, 1825 1826 .poll = iio_buffer_poll_addr, 1826 1827 .unlocked_ioctl = iio_ioctl, 1827 1828 .compat_ioctl = compat_ptr_ioctl,
+7
include/linux/iio/buffer.h
··· 11 11 12 12 struct iio_buffer; 13 13 14 + enum iio_buffer_direction { 15 + IIO_BUFFER_DIRECTION_IN, 16 + IIO_BUFFER_DIRECTION_OUT, 17 + }; 18 + 14 19 int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data); 20 + 21 + int iio_pop_from_buffer(struct iio_buffer *buffer, void *data); 15 22 16 23 /** 17 24 * iio_push_to_buffers_with_timestamp() - push data and timestamp to buffers
+11
include/linux/iio/buffer_impl.h
··· 7 7 #ifdef CONFIG_IIO_BUFFER 8 8 9 9 #include <uapi/linux/iio/buffer.h> 10 + #include <linux/iio/buffer.h> 10 11 11 12 struct iio_dev; 12 13 struct iio_buffer; ··· 24 23 * @read: try to get a specified number of bytes (must exist) 25 24 * @data_available: indicates how much data is available for reading from 26 25 * the buffer. 26 + * @remove_from: remove scan from buffer. Drivers should calls this to 27 + * remove a scan from a buffer. 28 + * @write: try to write a number of bytes 29 + * @space_available: returns the amount of bytes available in a buffer 27 30 * @request_update: if a parameter change has been marked, update underlying 28 31 * storage. 29 32 * @set_bytes_per_datum:set number of bytes per datum ··· 54 49 int (*store_to)(struct iio_buffer *buffer, const void *data); 55 50 int (*read)(struct iio_buffer *buffer, size_t n, char __user *buf); 56 51 size_t (*data_available)(struct iio_buffer *buffer); 52 + int (*remove_from)(struct iio_buffer *buffer, void *data); 53 + int (*write)(struct iio_buffer *buffer, size_t n, const char __user *buf); 54 + size_t (*space_available)(struct iio_buffer *buffer); 57 55 58 56 int (*request_update)(struct iio_buffer *buffer); 59 57 ··· 87 79 88 80 /** @bytes_per_datum: Size of individual datum including timestamp. */ 89 81 size_t bytes_per_datum; 82 + 83 + /* @direction: Direction of the data stream (in/out). */ 84 + enum iio_buffer_direction direction; 90 85 91 86 /** 92 87 * @access: Buffer access functions associated with the