kfifo_buf.c 3.3 KB

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