linux/drivers/iio/kfifo_buf.c
<<
>>
Prefs
   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#include <linux/sched.h>
  10
  11struct iio_kfifo {
  12        struct iio_buffer buffer;
  13        struct kfifo kf;
  14        int update_needed;
  15};
  16
  17#define iio_to_kfifo(r) container_of(r, struct iio_kfifo, buffer)
  18
  19static inline int __iio_allocate_kfifo(struct iio_kfifo *buf,
  20                                int bytes_per_datum, int length)
  21{
  22        if ((length == 0) || (bytes_per_datum == 0))
  23                return -EINVAL;
  24
  25        __iio_update_buffer(&buf->buffer, bytes_per_datum, length);
  26        return __kfifo_alloc((struct __kfifo *)&buf->kf, length,
  27                             bytes_per_datum, GFP_KERNEL);
  28}
  29
  30static int iio_request_update_kfifo(struct iio_buffer *r)
  31{
  32        int ret = 0;
  33        struct iio_kfifo *buf = iio_to_kfifo(r);
  34
  35        if (!buf->update_needed)
  36                goto error_ret;
  37        kfifo_free(&buf->kf);
  38        ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum,
  39                                   buf->buffer.length);
  40        r->stufftoread = false;
  41error_ret:
  42        return ret;
  43}
  44
  45static int iio_get_length_kfifo(struct iio_buffer *r)
  46{
  47        return r->length;
  48}
  49
  50static IIO_BUFFER_ENABLE_ATTR;
  51static IIO_BUFFER_LENGTH_ATTR;
  52
  53static struct attribute *iio_kfifo_attributes[] = {
  54        &dev_attr_length.attr,
  55        &dev_attr_enable.attr,
  56        NULL,
  57};
  58
  59static struct attribute_group iio_kfifo_attribute_group = {
  60        .attrs = iio_kfifo_attributes,
  61        .name = "buffer",
  62};
  63
  64static int iio_get_bytes_per_datum_kfifo(struct iio_buffer *r)
  65{
  66        return r->bytes_per_datum;
  67}
  68
  69static int iio_mark_update_needed_kfifo(struct iio_buffer *r)
  70{
  71        struct iio_kfifo *kf = iio_to_kfifo(r);
  72        kf->update_needed = true;
  73        return 0;
  74}
  75
  76static int iio_set_bytes_per_datum_kfifo(struct iio_buffer *r, size_t bpd)
  77{
  78        if (r->bytes_per_datum != bpd) {
  79                r->bytes_per_datum = bpd;
  80                iio_mark_update_needed_kfifo(r);
  81        }
  82        return 0;
  83}
  84
  85static int iio_set_length_kfifo(struct iio_buffer *r, int length)
  86{
  87        /* Avoid an invalid state */
  88        if (length < 2)
  89                length = 2;
  90        if (r->length != length) {
  91                r->length = length;
  92                iio_mark_update_needed_kfifo(r);
  93        }
  94        return 0;
  95}
  96
  97static int iio_store_to_kfifo(struct iio_buffer *r,
  98                              u8 *data)
  99{
 100        int ret;
 101        struct iio_kfifo *kf = iio_to_kfifo(r);
 102        ret = kfifo_in(&kf->kf, data, 1);
 103        if (ret != 1)
 104                return -EBUSY;
 105        r->stufftoread = true;
 106        wake_up_interruptible(&r->pollq);
 107
 108        return 0;
 109}
 110
 111static int iio_read_first_n_kfifo(struct iio_buffer *r,
 112                           size_t n, char __user *buf)
 113{
 114        int ret, copied;
 115        struct iio_kfifo *kf = iio_to_kfifo(r);
 116
 117        if (n < r->bytes_per_datum || r->bytes_per_datum == 0)
 118                return -EINVAL;
 119
 120        ret = kfifo_to_user(&kf->kf, buf, n, &copied);
 121        if (ret < 0)
 122                return ret;
 123
 124        if (kfifo_is_empty(&kf->kf))
 125                r->stufftoread = false;
 126        /* verify it is still empty to avoid race */
 127        if (!kfifo_is_empty(&kf->kf))
 128                r->stufftoread = true;
 129
 130        return copied;
 131}
 132
 133static const struct iio_buffer_access_funcs kfifo_access_funcs = {
 134        .store_to = &iio_store_to_kfifo,
 135        .read_first_n = &iio_read_first_n_kfifo,
 136        .request_update = &iio_request_update_kfifo,
 137        .get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo,
 138        .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo,
 139        .get_length = &iio_get_length_kfifo,
 140        .set_length = &iio_set_length_kfifo,
 141};
 142
 143struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev)
 144{
 145        struct iio_kfifo *kf;
 146
 147        kf = kzalloc(sizeof *kf, GFP_KERNEL);
 148        if (!kf)
 149                return NULL;
 150        kf->update_needed = true;
 151        iio_buffer_init(&kf->buffer);
 152        kf->buffer.attrs = &iio_kfifo_attribute_group;
 153        kf->buffer.access = &kfifo_access_funcs;
 154        kf->buffer.length = 2;
 155        return &kf->buffer;
 156}
 157EXPORT_SYMBOL(iio_kfifo_allocate);
 158
 159void iio_kfifo_free(struct iio_buffer *r)
 160{
 161        kfree(iio_to_kfifo(r));
 162}
 163EXPORT_SYMBOL(iio_kfifo_free);
 164
 165MODULE_LICENSE("GPL");
 166
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.