1#include <linux/slab.h> 2#include <linux/kernel.h> 3#include <linux/module.h> 4#include <linux/device.h> 5#include <linux/workqueue.h> 6#include <linux/kfifo.h> 7#include <linux/mutex.h> 8#include <linux/iio/kfifo_buf.h> 9 10struct iio_kfifo { 11 struct iio_buffer buffer; 12 struct kfifo kf; 13 int update_needed; 14}; 15 16#define iio_to_kfifo(r) container_of(r, struct iio_kfifo, buffer) 17 18static inline int __iio_allocate_kfifo(struct iio_kfifo *buf, 19 int bytes_per_datum, int length) 20{ 21 if ((length == 0) || (bytes_per_datum == 0)) 22 return -EINVAL; 23 24 __iio_update_buffer(&buf->buffer, bytes_per_datum, length); 25 return kfifo_alloc(&buf->kf, bytes_per_datum*length, GFP_KERNEL); 26} 27 28static int iio_request_update_kfifo(struct iio_buffer *r) 29{ 30 int ret = 0; 31 struct iio_kfifo *buf = iio_to_kfifo(r); 32 33 if (!buf->update_needed) 34 goto error_ret; 35 kfifo_free(&buf->kf); 36 ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum, 37 buf->buffer.length); 38error_ret: 39 return ret; 40} 41 42static int iio_get_length_kfifo(struct iio_buffer *r) 43{ 44 return r->length; 45} 46 47static IIO_BUFFER_ENABLE_ATTR; 48static IIO_BUFFER_LENGTH_ATTR; 49 50static struct attribute *iio_kfifo_attributes[] = { 51 &dev_attr_length.attr, 52 &dev_attr_enable.attr, 53 NULL, 54}; 55 56static struct attribute_group iio_kfifo_attribute_group = { 57 .attrs = iio_kfifo_attributes, 58 .name = "buffer", 59}; 60 61static int iio_get_bytes_per_datum_kfifo(struct iio_buffer *r) 62{ 63 return r->bytes_per_datum; 64} 65 66static int iio_mark_update_needed_kfifo(struct iio_buffer *r) 67{ 68 struct iio_kfifo *kf = iio_to_kfifo(r); 69 kf->update_needed = true; 70 return 0; 71} 72 73static int iio_set_bytes_per_datum_kfifo(struct iio_buffer *r, size_t bpd) 74{ 75 if (r->bytes_per_datum != bpd) { 76 r->bytes_per_datum = bpd; 77 iio_mark_update_needed_kfifo(r); 78 } 79 return 0; 80} 81 82static int iio_set_length_kfifo(struct iio_buffer *r, int length) 83{ 84 if (r->length != length) { 85 r->length = length; 86 iio_mark_update_needed_kfifo(r); 87 } 88 return 0; 89} 90 91static int iio_store_to_kfifo(struct iio_buffer *r, 92 u8 *data, 93 s64 timestamp) 94{ 95 int ret; 96 struct iio_kfifo *kf = iio_to_kfifo(r); 97 ret = kfifo_in(&kf->kf, data, r->bytes_per_datum); 98 if (ret != r->bytes_per_datum) 99 return -EBUSY; 100 return 0; 101} 102 103static int iio_read_first_n_kfifo(struct iio_buffer *r, 104 size_t n, char __user *buf) 105{ 106 int ret, copied; 107 struct iio_kfifo *kf = iio_to_kfifo(r); 108 109 if (n < r->bytes_per_datum) 110 return -EINVAL; 111 112 n = rounddown(n, r->bytes_per_datum); 113 ret = kfifo_to_user(&kf->kf, buf, n, &copied); 114 115 return copied; 116} 117 118static const struct iio_buffer_access_funcs kfifo_access_funcs = { 119 .store_to = &iio_store_to_kfifo, 120 .read_first_n = &iio_read_first_n_kfifo, 121 .request_update = &iio_request_update_kfifo, 122 .get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo, 123 .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, 124 .get_length = &iio_get_length_kfifo, 125 .set_length = &iio_set_length_kfifo, 126}; 127 128struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) 129{ 130 struct iio_kfifo *kf; 131 132 kf = kzalloc(sizeof *kf, GFP_KERNEL); 133 if (!kf) 134 return NULL; 135 kf->update_needed = true; 136 iio_buffer_init(&kf->buffer); 137 kf->buffer.attrs = &iio_kfifo_attribute_group; 138 kf->buffer.access = &kfifo_access_funcs; 139 140 return &kf->buffer; 141} 142EXPORT_SYMBOL(iio_kfifo_allocate); 143 144void iio_kfifo_free(struct iio_buffer *r) 145{ 146 kfree(iio_to_kfifo(r)); 147} 148EXPORT_SYMBOL(iio_kfifo_free); 149 150MODULE_LICENSE("GPL"); 151

