diff options
author | Jonathan Cameron <jic23@kernel.org> | 2012-04-25 10:54:59 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-25 14:11:38 -0400 |
commit | a980e046098b0a40eaff5e4e7fcde6cf035b7c06 (patch) | |
tree | 23375fc2bba39f088974cf621f7abf006d43d087 /drivers/iio/kfifo_buf.c | |
parent | 06458e277eac2b8761b0a04d3c808d57be281a2e (diff) |
IIO: Move the core files to drivers/iio
Take the core support + the kfifo buffer implentation out of
staging. Whilst we are far from done in improving this subsystem
it is now at a stage where the userspae interfaces (provided by
the core) can be considered stable.
Drivers will follow over a longer time scale.
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/iio/kfifo_buf.c')
-rw-r--r-- | drivers/iio/kfifo_buf.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c new file mode 100644 index 000000000000..6bf9d05f4841 --- /dev/null +++ b/drivers/iio/kfifo_buf.c | |||
@@ -0,0 +1,150 @@ | |||
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 | |||
10 | struct 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 | |||
18 | static 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 | |||
28 | static 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); | ||
38 | error_ret: | ||
39 | return ret; | ||
40 | } | ||
41 | |||
42 | static int iio_get_length_kfifo(struct iio_buffer *r) | ||
43 | { | ||
44 | return r->length; | ||
45 | } | ||
46 | |||
47 | static IIO_BUFFER_ENABLE_ATTR; | ||
48 | static IIO_BUFFER_LENGTH_ATTR; | ||
49 | |||
50 | static struct attribute *iio_kfifo_attributes[] = { | ||
51 | &dev_attr_length.attr, | ||
52 | &dev_attr_enable.attr, | ||
53 | NULL, | ||
54 | }; | ||
55 | |||
56 | static struct attribute_group iio_kfifo_attribute_group = { | ||
57 | .attrs = iio_kfifo_attributes, | ||
58 | .name = "buffer", | ||
59 | }; | ||
60 | |||
61 | static int iio_get_bytes_per_datum_kfifo(struct iio_buffer *r) | ||
62 | { | ||
63 | return r->bytes_per_datum; | ||
64 | } | ||
65 | |||
66 | static 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 | |||
73 | static 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 | |||
82 | static 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 | |||
91 | static 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 | |||
103 | static 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 | |||
118 | static 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 | |||
128 | struct 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 | } | ||
142 | EXPORT_SYMBOL(iio_kfifo_allocate); | ||
143 | |||
144 | void iio_kfifo_free(struct iio_buffer *r) | ||
145 | { | ||
146 | kfree(iio_to_kfifo(r)); | ||
147 | } | ||
148 | EXPORT_SYMBOL(iio_kfifo_free); | ||
149 | |||
150 | MODULE_LICENSE("GPL"); | ||