Commit 355c1a14d4009a43e4d1f9cb42a382f0a94d01c4

Authored by Lars-Peter Clausen
Committed by Jonathan Cameron
1 parent 647cc7b9be

iio: kfifo_buf: Implement data_available() callback

This patch implements the data_available() callback for the kfifo buffer instead
of using the stufftoread flag. The kfifo used by the buffer already knows
whether it is empty or not based on the position of its read and write pointer.
Using this makes it a lot easier to tell whether data is available or not and it
is not necessary to take special measures to ensure that no race conditions
between reading and writing from the buffer occur.

Note, that we still have to take the buffers lock to protect against concurrent
resizeing of the kfifo.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>

Showing 1 changed file with 14 additions and 9 deletions Inline Diff

drivers/iio/kfifo_buf.c
1 #include <linux/slab.h> 1 #include <linux/slab.h>
2 #include <linux/kernel.h> 2 #include <linux/kernel.h>
3 #include <linux/module.h> 3 #include <linux/module.h>
4 #include <linux/device.h> 4 #include <linux/device.h>
5 #include <linux/workqueue.h> 5 #include <linux/workqueue.h>
6 #include <linux/kfifo.h> 6 #include <linux/kfifo.h>
7 #include <linux/mutex.h> 7 #include <linux/mutex.h>
8 #include <linux/iio/kfifo_buf.h> 8 #include <linux/iio/kfifo_buf.h>
9 #include <linux/sched.h> 9 #include <linux/sched.h>
10 #include <linux/poll.h> 10 #include <linux/poll.h>
11 11
12 struct iio_kfifo { 12 struct iio_kfifo {
13 struct iio_buffer buffer; 13 struct iio_buffer buffer;
14 struct kfifo kf; 14 struct kfifo kf;
15 struct mutex user_lock; 15 struct mutex user_lock;
16 int update_needed; 16 int update_needed;
17 }; 17 };
18 18
19 #define iio_to_kfifo(r) container_of(r, struct iio_kfifo, buffer) 19 #define iio_to_kfifo(r) container_of(r, struct iio_kfifo, buffer)
20 20
21 static inline int __iio_allocate_kfifo(struct iio_kfifo *buf, 21 static inline int __iio_allocate_kfifo(struct iio_kfifo *buf,
22 int bytes_per_datum, int length) 22 int bytes_per_datum, int length)
23 { 23 {
24 if ((length == 0) || (bytes_per_datum == 0)) 24 if ((length == 0) || (bytes_per_datum == 0))
25 return -EINVAL; 25 return -EINVAL;
26 26
27 return __kfifo_alloc((struct __kfifo *)&buf->kf, length, 27 return __kfifo_alloc((struct __kfifo *)&buf->kf, length,
28 bytes_per_datum, GFP_KERNEL); 28 bytes_per_datum, GFP_KERNEL);
29 } 29 }
30 30
31 static int iio_request_update_kfifo(struct iio_buffer *r) 31 static int iio_request_update_kfifo(struct iio_buffer *r)
32 { 32 {
33 int ret = 0; 33 int ret = 0;
34 struct iio_kfifo *buf = iio_to_kfifo(r); 34 struct iio_kfifo *buf = iio_to_kfifo(r);
35 35
36 mutex_lock(&buf->user_lock); 36 mutex_lock(&buf->user_lock);
37 if (buf->update_needed) { 37 if (buf->update_needed) {
38 kfifo_free(&buf->kf); 38 kfifo_free(&buf->kf);
39 ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum, 39 ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum,
40 buf->buffer.length); 40 buf->buffer.length);
41 buf->update_needed = false; 41 buf->update_needed = false;
42 } else { 42 } else {
43 kfifo_reset_out(&buf->kf); 43 kfifo_reset_out(&buf->kf);
44 } 44 }
45 r->stufftoread = false;
46 mutex_unlock(&buf->user_lock); 45 mutex_unlock(&buf->user_lock);
47 46
48 return ret; 47 return ret;
49 } 48 }
50 49
51 static int iio_get_length_kfifo(struct iio_buffer *r) 50 static int iio_get_length_kfifo(struct iio_buffer *r)
52 { 51 {
53 return r->length; 52 return r->length;
54 } 53 }
55 54
56 static IIO_BUFFER_ENABLE_ATTR; 55 static IIO_BUFFER_ENABLE_ATTR;
57 static IIO_BUFFER_LENGTH_ATTR; 56 static IIO_BUFFER_LENGTH_ATTR;
58 57
59 static struct attribute *iio_kfifo_attributes[] = { 58 static struct attribute *iio_kfifo_attributes[] = {
60 &dev_attr_length.attr, 59 &dev_attr_length.attr,
61 &dev_attr_enable.attr, 60 &dev_attr_enable.attr,
62 NULL, 61 NULL,
63 }; 62 };
64 63
65 static struct attribute_group iio_kfifo_attribute_group = { 64 static struct attribute_group iio_kfifo_attribute_group = {
66 .attrs = iio_kfifo_attributes, 65 .attrs = iio_kfifo_attributes,
67 .name = "buffer", 66 .name = "buffer",
68 }; 67 };
69 68
70 static int iio_get_bytes_per_datum_kfifo(struct iio_buffer *r) 69 static int iio_get_bytes_per_datum_kfifo(struct iio_buffer *r)
71 { 70 {
72 return r->bytes_per_datum; 71 return r->bytes_per_datum;
73 } 72 }
74 73
75 static int iio_mark_update_needed_kfifo(struct iio_buffer *r) 74 static int iio_mark_update_needed_kfifo(struct iio_buffer *r)
76 { 75 {
77 struct iio_kfifo *kf = iio_to_kfifo(r); 76 struct iio_kfifo *kf = iio_to_kfifo(r);
78 kf->update_needed = true; 77 kf->update_needed = true;
79 return 0; 78 return 0;
80 } 79 }
81 80
82 static int iio_set_bytes_per_datum_kfifo(struct iio_buffer *r, size_t bpd) 81 static int iio_set_bytes_per_datum_kfifo(struct iio_buffer *r, size_t bpd)
83 { 82 {
84 if (r->bytes_per_datum != bpd) { 83 if (r->bytes_per_datum != bpd) {
85 r->bytes_per_datum = bpd; 84 r->bytes_per_datum = bpd;
86 iio_mark_update_needed_kfifo(r); 85 iio_mark_update_needed_kfifo(r);
87 } 86 }
88 return 0; 87 return 0;
89 } 88 }
90 89
91 static int iio_set_length_kfifo(struct iio_buffer *r, int length) 90 static int iio_set_length_kfifo(struct iio_buffer *r, int length)
92 { 91 {
93 /* Avoid an invalid state */ 92 /* Avoid an invalid state */
94 if (length < 2) 93 if (length < 2)
95 length = 2; 94 length = 2;
96 if (r->length != length) { 95 if (r->length != length) {
97 r->length = length; 96 r->length = length;
98 iio_mark_update_needed_kfifo(r); 97 iio_mark_update_needed_kfifo(r);
99 } 98 }
100 return 0; 99 return 0;
101 } 100 }
102 101
103 static int iio_store_to_kfifo(struct iio_buffer *r, 102 static int iio_store_to_kfifo(struct iio_buffer *r,
104 const void *data) 103 const void *data)
105 { 104 {
106 int ret; 105 int ret;
107 struct iio_kfifo *kf = iio_to_kfifo(r); 106 struct iio_kfifo *kf = iio_to_kfifo(r);
108 ret = kfifo_in(&kf->kf, data, 1); 107 ret = kfifo_in(&kf->kf, data, 1);
109 if (ret != 1) 108 if (ret != 1)
110 return -EBUSY; 109 return -EBUSY;
111 r->stufftoread = true; 110
112 wake_up_interruptible_poll(&r->pollq, POLLIN | POLLRDNORM); 111 wake_up_interruptible_poll(&r->pollq, POLLIN | POLLRDNORM);
113 112
114 return 0; 113 return 0;
115 } 114 }
116 115
117 static int iio_read_first_n_kfifo(struct iio_buffer *r, 116 static int iio_read_first_n_kfifo(struct iio_buffer *r,
118 size_t n, char __user *buf) 117 size_t n, char __user *buf)
119 { 118 {
120 int ret, copied; 119 int ret, copied;
121 struct iio_kfifo *kf = iio_to_kfifo(r); 120 struct iio_kfifo *kf = iio_to_kfifo(r);
122 121
123 if (mutex_lock_interruptible(&kf->user_lock)) 122 if (mutex_lock_interruptible(&kf->user_lock))
124 return -ERESTARTSYS; 123 return -ERESTARTSYS;
125 124
126 if (!kfifo_initialized(&kf->kf) || n < kfifo_esize(&kf->kf)) 125 if (!kfifo_initialized(&kf->kf) || n < kfifo_esize(&kf->kf))
127 ret = -EINVAL; 126 ret = -EINVAL;
128 else 127 else
129 ret = kfifo_to_user(&kf->kf, buf, n, &copied); 128 ret = kfifo_to_user(&kf->kf, buf, n, &copied);
130
131 if (kfifo_is_empty(&kf->kf))
132 r->stufftoread = false;
133 /* verify it is still empty to avoid race */
134 if (!kfifo_is_empty(&kf->kf))
135 r->stufftoread = true;
136
137 mutex_unlock(&kf->user_lock); 129 mutex_unlock(&kf->user_lock);
138 if (ret < 0) 130 if (ret < 0)
139 return ret; 131 return ret;
140 132
141 return copied; 133 return copied;
142 } 134 }
143 135
136 static bool iio_kfifo_buf_data_available(struct iio_buffer *r)
137 {
138 struct iio_kfifo *kf = iio_to_kfifo(r);
139 bool empty;
140
141 mutex_lock(&kf->user_lock);
142 empty = kfifo_is_empty(&kf->kf);
143 mutex_unlock(&kf->user_lock);
144
145 return !empty;
146 }
147
144 static void iio_kfifo_buffer_release(struct iio_buffer *buffer) 148 static void iio_kfifo_buffer_release(struct iio_buffer *buffer)
145 { 149 {
146 struct iio_kfifo *kf = iio_to_kfifo(buffer); 150 struct iio_kfifo *kf = iio_to_kfifo(buffer);
147 151
148 mutex_destroy(&kf->user_lock); 152 mutex_destroy(&kf->user_lock);
149 kfifo_free(&kf->kf); 153 kfifo_free(&kf->kf);
150 kfree(kf); 154 kfree(kf);
151 } 155 }
152 156
153 static const struct iio_buffer_access_funcs kfifo_access_funcs = { 157 static const struct iio_buffer_access_funcs kfifo_access_funcs = {
154 .store_to = &iio_store_to_kfifo, 158 .store_to = &iio_store_to_kfifo,
155 .read_first_n = &iio_read_first_n_kfifo, 159 .read_first_n = &iio_read_first_n_kfifo,
160 .data_available = iio_kfifo_buf_data_available,
156 .request_update = &iio_request_update_kfifo, 161 .request_update = &iio_request_update_kfifo,
157 .get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo, 162 .get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo,
158 .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, 163 .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo,
159 .get_length = &iio_get_length_kfifo, 164 .get_length = &iio_get_length_kfifo,
160 .set_length = &iio_set_length_kfifo, 165 .set_length = &iio_set_length_kfifo,
161 .release = &iio_kfifo_buffer_release, 166 .release = &iio_kfifo_buffer_release,
162 }; 167 };
163 168
164 struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) 169 struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev)
165 { 170 {
166 struct iio_kfifo *kf; 171 struct iio_kfifo *kf;
167 172
168 kf = kzalloc(sizeof *kf, GFP_KERNEL); 173 kf = kzalloc(sizeof *kf, GFP_KERNEL);
169 if (!kf) 174 if (!kf)
170 return NULL; 175 return NULL;
171 kf->update_needed = true; 176 kf->update_needed = true;
172 iio_buffer_init(&kf->buffer); 177 iio_buffer_init(&kf->buffer);
173 kf->buffer.attrs = &iio_kfifo_attribute_group; 178 kf->buffer.attrs = &iio_kfifo_attribute_group;
174 kf->buffer.access = &kfifo_access_funcs; 179 kf->buffer.access = &kfifo_access_funcs;
175 kf->buffer.length = 2; 180 kf->buffer.length = 2;
176 mutex_init(&kf->user_lock); 181 mutex_init(&kf->user_lock);
177 return &kf->buffer; 182 return &kf->buffer;
178 } 183 }
179 EXPORT_SYMBOL(iio_kfifo_allocate); 184 EXPORT_SYMBOL(iio_kfifo_allocate);
180 185