]>
Commit | Line | Data |
---|---|---|
b174baf4 JC |
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 | ||
9 | #include "kfifo_buf.h" | |
10 | ||
a710cc77 JC |
11 | struct iio_kfifo { |
12 | struct iio_ring_buffer ring; | |
13 | struct kfifo kf; | |
14 | int use_count; | |
15 | int update_needed; | |
16 | struct mutex use_lock; | |
17 | }; | |
18 | ||
5565a450 JC |
19 | #define iio_to_kfifo(r) container_of(r, struct iio_kfifo, ring) |
20 | ||
b174baf4 JC |
21 | static inline int __iio_allocate_kfifo(struct iio_kfifo *buf, |
22 | int bytes_per_datum, int length) | |
23 | { | |
24 | if ((length == 0) || (bytes_per_datum == 0)) | |
25 | return -EINVAL; | |
26 | ||
27 | __iio_update_ring_buffer(&buf->ring, bytes_per_datum, length); | |
28 | return kfifo_alloc(&buf->kf, bytes_per_datum*length, GFP_KERNEL); | |
29 | } | |
30 | ||
5565a450 | 31 | static int iio_request_update_kfifo(struct iio_ring_buffer *r) |
b174baf4 JC |
32 | { |
33 | int ret = 0; | |
34 | struct iio_kfifo *buf = iio_to_kfifo(r); | |
35 | ||
36 | mutex_lock(&buf->use_lock); | |
37 | if (!buf->update_needed) | |
38 | goto error_ret; | |
39 | if (buf->use_count) { | |
40 | ret = -EAGAIN; | |
41 | goto error_ret; | |
42 | } | |
43 | kfifo_free(&buf->kf); | |
44 | ret = __iio_allocate_kfifo(buf, buf->ring.bytes_per_datum, | |
45 | buf->ring.length); | |
46 | error_ret: | |
47 | mutex_unlock(&buf->use_lock); | |
48 | return ret; | |
49 | } | |
b174baf4 | 50 | |
5565a450 | 51 | static void iio_mark_kfifo_in_use(struct iio_ring_buffer *r) |
b174baf4 JC |
52 | { |
53 | struct iio_kfifo *buf = iio_to_kfifo(r); | |
54 | mutex_lock(&buf->use_lock); | |
55 | buf->use_count++; | |
56 | mutex_unlock(&buf->use_lock); | |
57 | } | |
b174baf4 | 58 | |
5565a450 | 59 | static void iio_unmark_kfifo_in_use(struct iio_ring_buffer *r) |
b174baf4 JC |
60 | { |
61 | struct iio_kfifo *buf = iio_to_kfifo(r); | |
62 | mutex_lock(&buf->use_lock); | |
63 | buf->use_count--; | |
64 | mutex_unlock(&buf->use_lock); | |
65 | } | |
b174baf4 | 66 | |
5565a450 | 67 | static int iio_get_length_kfifo(struct iio_ring_buffer *r) |
b174baf4 JC |
68 | { |
69 | return r->length; | |
70 | } | |
b174baf4 JC |
71 | |
72 | static inline void __iio_init_kfifo(struct iio_kfifo *kf) | |
73 | { | |
74 | mutex_init(&kf->use_lock); | |
75 | } | |
76 | ||
77 | static IIO_RING_ENABLE_ATTR; | |
78 | static IIO_RING_BYTES_PER_DATUM_ATTR; | |
79 | static IIO_RING_LENGTH_ATTR; | |
80 | ||
81 | static struct attribute *iio_kfifo_attributes[] = { | |
82 | &dev_attr_length.attr, | |
83 | &dev_attr_bytes_per_datum.attr, | |
84 | &dev_attr_enable.attr, | |
85 | NULL, | |
86 | }; | |
87 | ||
88 | static struct attribute_group iio_kfifo_attribute_group = { | |
89 | .attrs = iio_kfifo_attributes, | |
90 | }; | |
91 | ||
92 | static const struct attribute_group *iio_kfifo_attribute_groups[] = { | |
93 | &iio_kfifo_attribute_group, | |
94 | NULL | |
95 | }; | |
96 | ||
97 | static void iio_kfifo_release(struct device *dev) | |
98 | { | |
99 | struct iio_ring_buffer *r = to_iio_ring_buffer(dev); | |
100 | struct iio_kfifo *kf = iio_to_kfifo(r); | |
101 | kfifo_free(&kf->kf); | |
102 | kfree(kf); | |
103 | } | |
104 | ||
105 | static struct device_type iio_kfifo_type = { | |
106 | .release = iio_kfifo_release, | |
107 | .groups = iio_kfifo_attribute_groups, | |
108 | }; | |
109 | ||
110 | struct iio_ring_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) | |
111 | { | |
112 | struct iio_kfifo *kf; | |
113 | ||
114 | kf = kzalloc(sizeof *kf, GFP_KERNEL); | |
115 | if (!kf) | |
116 | return NULL; | |
5565a450 | 117 | kf->update_needed = true; |
b174baf4 JC |
118 | iio_ring_buffer_init(&kf->ring, indio_dev); |
119 | __iio_init_kfifo(kf); | |
120 | kf->ring.dev.type = &iio_kfifo_type; | |
b174baf4 | 121 | kf->ring.dev.parent = &indio_dev->dev; |
b174baf4 JC |
122 | dev_set_drvdata(&kf->ring.dev, (void *)&(kf->ring)); |
123 | ||
124 | return &kf->ring; | |
125 | } | |
126 | EXPORT_SYMBOL(iio_kfifo_allocate); | |
127 | ||
5565a450 | 128 | static int iio_get_bytes_per_datum_kfifo(struct iio_ring_buffer *r) |
b174baf4 JC |
129 | { |
130 | return r->bytes_per_datum; | |
131 | } | |
b174baf4 | 132 | |
5565a450 | 133 | static int iio_set_bytes_per_datum_kfifo(struct iio_ring_buffer *r, size_t bpd) |
b174baf4 JC |
134 | { |
135 | if (r->bytes_per_datum != bpd) { | |
136 | r->bytes_per_datum = bpd; | |
5565a450 JC |
137 | if (r->access->mark_param_change) |
138 | r->access->mark_param_change(r); | |
b174baf4 JC |
139 | } |
140 | return 0; | |
141 | } | |
b174baf4 | 142 | |
5565a450 | 143 | static int iio_mark_update_needed_kfifo(struct iio_ring_buffer *r) |
b174baf4 JC |
144 | { |
145 | struct iio_kfifo *kf = iio_to_kfifo(r); | |
146 | kf->update_needed = true; | |
147 | return 0; | |
148 | } | |
b174baf4 | 149 | |
5565a450 | 150 | static int iio_set_length_kfifo(struct iio_ring_buffer *r, int length) |
b174baf4 JC |
151 | { |
152 | if (r->length != length) { | |
153 | r->length = length; | |
5565a450 JC |
154 | if (r->access->mark_param_change) |
155 | r->access->mark_param_change(r); | |
b174baf4 JC |
156 | } |
157 | return 0; | |
158 | } | |
b174baf4 JC |
159 | |
160 | void iio_kfifo_free(struct iio_ring_buffer *r) | |
161 | { | |
162 | if (r) | |
163 | iio_put_ring_buffer(r); | |
164 | } | |
165 | EXPORT_SYMBOL(iio_kfifo_free); | |
166 | ||
5565a450 JC |
167 | static int iio_store_to_kfifo(struct iio_ring_buffer *r, |
168 | u8 *data, | |
169 | s64 timestamp) | |
b174baf4 JC |
170 | { |
171 | int ret; | |
172 | struct iio_kfifo *kf = iio_to_kfifo(r); | |
173 | u8 *datal = kmalloc(r->bytes_per_datum, GFP_KERNEL); | |
174 | memcpy(datal, data, r->bytes_per_datum - sizeof(timestamp)); | |
175 | memcpy(datal + r->bytes_per_datum - sizeof(timestamp), | |
176 | ×tamp, sizeof(timestamp)); | |
177 | ret = kfifo_in(&kf->kf, data, r->bytes_per_datum); | |
178 | if (ret != r->bytes_per_datum) { | |
179 | kfree(datal); | |
180 | return -EBUSY; | |
181 | } | |
182 | kfree(datal); | |
183 | return 0; | |
184 | } | |
b174baf4 | 185 | |
5565a450 | 186 | static int iio_read_first_n_kfifo(struct iio_ring_buffer *r, |
b26a2188 | 187 | size_t n, char __user *buf) |
b174baf4 JC |
188 | { |
189 | int ret, copied; | |
190 | struct iio_kfifo *kf = iio_to_kfifo(r); | |
191 | ||
b4281733 | 192 | ret = kfifo_to_user(&kf->kf, buf, r->bytes_per_datum*n, &copied); |
b174baf4 JC |
193 | |
194 | return copied; | |
195 | } | |
5565a450 JC |
196 | |
197 | const struct iio_ring_access_funcs kfifo_access_funcs = { | |
198 | .mark_in_use = &iio_mark_kfifo_in_use, | |
199 | .unmark_in_use = &iio_unmark_kfifo_in_use, | |
200 | .store_to = &iio_store_to_kfifo, | |
201 | .read_first_n = &iio_read_first_n_kfifo, | |
202 | .mark_param_change = &iio_mark_update_needed_kfifo, | |
203 | .request_update = &iio_request_update_kfifo, | |
204 | .get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo, | |
205 | .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, | |
206 | .get_length = &iio_get_length_kfifo, | |
207 | .set_length = &iio_set_length_kfifo, | |
208 | }; | |
209 | EXPORT_SYMBOL(kfifo_access_funcs); | |
210 | ||
b174baf4 | 211 | MODULE_LICENSE("GPL"); |