diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /kernel/kfifo.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'kernel/kfifo.c')
-rw-r--r-- | kernel/kfifo.c | 410 |
1 files changed, 329 insertions, 81 deletions
diff --git a/kernel/kfifo.c b/kernel/kfifo.c index 3765ff3c1bbe..35edbe22e9a9 100644 --- a/kernel/kfifo.c +++ b/kernel/kfifo.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * A simple kernel FIFO implementation. | 2 | * A generic kernel FIFO implementation. |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Stefani Seibold <stefani@seibold.net> | ||
4 | * Copyright (C) 2004 Stelian Pop <stelian@popies.net> | 5 | * Copyright (C) 2004 Stelian Pop <stelian@popies.net> |
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -25,50 +26,48 @@ | |||
25 | #include <linux/err.h> | 26 | #include <linux/err.h> |
26 | #include <linux/kfifo.h> | 27 | #include <linux/kfifo.h> |
27 | #include <linux/log2.h> | 28 | #include <linux/log2.h> |
29 | #include <linux/uaccess.h> | ||
30 | |||
31 | static void _kfifo_init(struct kfifo *fifo, void *buffer, | ||
32 | unsigned int size) | ||
33 | { | ||
34 | fifo->buffer = buffer; | ||
35 | fifo->size = size; | ||
36 | |||
37 | kfifo_reset(fifo); | ||
38 | } | ||
28 | 39 | ||
29 | /** | 40 | /** |
30 | * kfifo_init - allocates a new FIFO using a preallocated buffer | 41 | * kfifo_init - initialize a FIFO using a preallocated buffer |
42 | * @fifo: the fifo to assign the buffer | ||
31 | * @buffer: the preallocated buffer to be used. | 43 | * @buffer: the preallocated buffer to be used. |
32 | * @size: the size of the internal buffer, this have to be a power of 2. | 44 | * @size: the size of the internal buffer, this has to be a power of 2. |
33 | * @gfp_mask: get_free_pages mask, passed to kmalloc() | ||
34 | * @lock: the lock to be used to protect the fifo buffer | ||
35 | * | 45 | * |
36 | * Do NOT pass the kfifo to kfifo_free() after use! Simply free the | ||
37 | * &struct kfifo with kfree(). | ||
38 | */ | 46 | */ |
39 | struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size, | 47 | void kfifo_init(struct kfifo *fifo, void *buffer, unsigned int size) |
40 | gfp_t gfp_mask, spinlock_t *lock) | ||
41 | { | 48 | { |
42 | struct kfifo *fifo; | ||
43 | |||
44 | /* size must be a power of 2 */ | 49 | /* size must be a power of 2 */ |
45 | BUG_ON(!is_power_of_2(size)); | 50 | BUG_ON(!is_power_of_2(size)); |
46 | 51 | ||
47 | fifo = kmalloc(sizeof(struct kfifo), gfp_mask); | 52 | _kfifo_init(fifo, buffer, size); |
48 | if (!fifo) | ||
49 | return ERR_PTR(-ENOMEM); | ||
50 | |||
51 | fifo->buffer = buffer; | ||
52 | fifo->size = size; | ||
53 | fifo->in = fifo->out = 0; | ||
54 | fifo->lock = lock; | ||
55 | |||
56 | return fifo; | ||
57 | } | 53 | } |
58 | EXPORT_SYMBOL(kfifo_init); | 54 | EXPORT_SYMBOL(kfifo_init); |
59 | 55 | ||
60 | /** | 56 | /** |
61 | * kfifo_alloc - allocates a new FIFO and its internal buffer | 57 | * kfifo_alloc - allocates a new FIFO internal buffer |
62 | * @size: the size of the internal buffer to be allocated. | 58 | * @fifo: the fifo to assign then new buffer |
59 | * @size: the size of the buffer to be allocated, this have to be a power of 2. | ||
63 | * @gfp_mask: get_free_pages mask, passed to kmalloc() | 60 | * @gfp_mask: get_free_pages mask, passed to kmalloc() |
64 | * @lock: the lock to be used to protect the fifo buffer | 61 | * |
62 | * This function dynamically allocates a new fifo internal buffer | ||
65 | * | 63 | * |
66 | * The size will be rounded-up to a power of 2. | 64 | * The size will be rounded-up to a power of 2. |
65 | * The buffer will be release with kfifo_free(). | ||
66 | * Return 0 if no error, otherwise the an error code | ||
67 | */ | 67 | */ |
68 | struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock) | 68 | int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask) |
69 | { | 69 | { |
70 | unsigned char *buffer; | 70 | unsigned char *buffer; |
71 | struct kfifo *ret; | ||
72 | 71 | ||
73 | /* | 72 | /* |
74 | * round up to the next power of 2, since our 'let the indices | 73 | * round up to the next power of 2, since our 'let the indices |
@@ -80,48 +79,93 @@ struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock) | |||
80 | } | 79 | } |
81 | 80 | ||
82 | buffer = kmalloc(size, gfp_mask); | 81 | buffer = kmalloc(size, gfp_mask); |
83 | if (!buffer) | 82 | if (!buffer) { |
84 | return ERR_PTR(-ENOMEM); | 83 | _kfifo_init(fifo, NULL, 0); |
85 | 84 | return -ENOMEM; | |
86 | ret = kfifo_init(buffer, size, gfp_mask, lock); | 85 | } |
87 | 86 | ||
88 | if (IS_ERR(ret)) | 87 | _kfifo_init(fifo, buffer, size); |
89 | kfree(buffer); | ||
90 | 88 | ||
91 | return ret; | 89 | return 0; |
92 | } | 90 | } |
93 | EXPORT_SYMBOL(kfifo_alloc); | 91 | EXPORT_SYMBOL(kfifo_alloc); |
94 | 92 | ||
95 | /** | 93 | /** |
96 | * kfifo_free - frees the FIFO | 94 | * kfifo_free - frees the FIFO internal buffer |
97 | * @fifo: the fifo to be freed. | 95 | * @fifo: the fifo to be freed. |
98 | */ | 96 | */ |
99 | void kfifo_free(struct kfifo *fifo) | 97 | void kfifo_free(struct kfifo *fifo) |
100 | { | 98 | { |
101 | kfree(fifo->buffer); | 99 | kfree(fifo->buffer); |
102 | kfree(fifo); | 100 | _kfifo_init(fifo, NULL, 0); |
103 | } | 101 | } |
104 | EXPORT_SYMBOL(kfifo_free); | 102 | EXPORT_SYMBOL(kfifo_free); |
105 | 103 | ||
106 | /** | 104 | /** |
107 | * __kfifo_put - puts some data into the FIFO, no locking version | 105 | * kfifo_skip - skip output data |
108 | * @fifo: the fifo to be used. | 106 | * @fifo: the fifo to be used. |
109 | * @buffer: the data to be added. | 107 | * @len: number of bytes to skip |
110 | * @len: the length of the data to be added. | ||
111 | * | ||
112 | * This function copies at most @len bytes from the @buffer into | ||
113 | * the FIFO depending on the free space, and returns the number of | ||
114 | * bytes copied. | ||
115 | * | ||
116 | * Note that with only one concurrent reader and one concurrent | ||
117 | * writer, you don't need extra locking to use these functions. | ||
118 | */ | 108 | */ |
119 | unsigned int __kfifo_put(struct kfifo *fifo, | 109 | void kfifo_skip(struct kfifo *fifo, unsigned int len) |
120 | const unsigned char *buffer, unsigned int len) | 110 | { |
111 | if (len < kfifo_len(fifo)) { | ||
112 | __kfifo_add_out(fifo, len); | ||
113 | return; | ||
114 | } | ||
115 | kfifo_reset_out(fifo); | ||
116 | } | ||
117 | EXPORT_SYMBOL(kfifo_skip); | ||
118 | |||
119 | static inline void __kfifo_in_data(struct kfifo *fifo, | ||
120 | const void *from, unsigned int len, unsigned int off) | ||
121 | { | 121 | { |
122 | unsigned int l; | 122 | unsigned int l; |
123 | 123 | ||
124 | len = min(len, fifo->size - fifo->in + fifo->out); | 124 | /* |
125 | * Ensure that we sample the fifo->out index -before- we | ||
126 | * start putting bytes into the kfifo. | ||
127 | */ | ||
128 | |||
129 | smp_mb(); | ||
130 | |||
131 | off = __kfifo_off(fifo, fifo->in + off); | ||
132 | |||
133 | /* first put the data starting from fifo->in to buffer end */ | ||
134 | l = min(len, fifo->size - off); | ||
135 | memcpy(fifo->buffer + off, from, l); | ||
136 | |||
137 | /* then put the rest (if any) at the beginning of the buffer */ | ||
138 | memcpy(fifo->buffer, from + l, len - l); | ||
139 | } | ||
140 | |||
141 | static inline void __kfifo_out_data(struct kfifo *fifo, | ||
142 | void *to, unsigned int len, unsigned int off) | ||
143 | { | ||
144 | unsigned int l; | ||
145 | |||
146 | /* | ||
147 | * Ensure that we sample the fifo->in index -before- we | ||
148 | * start removing bytes from the kfifo. | ||
149 | */ | ||
150 | |||
151 | smp_rmb(); | ||
152 | |||
153 | off = __kfifo_off(fifo, fifo->out + off); | ||
154 | |||
155 | /* first get the data from fifo->out until the end of the buffer */ | ||
156 | l = min(len, fifo->size - off); | ||
157 | memcpy(to, fifo->buffer + off, l); | ||
158 | |||
159 | /* then get the rest (if any) from the beginning of the buffer */ | ||
160 | memcpy(to + l, fifo->buffer, len - l); | ||
161 | } | ||
162 | |||
163 | static inline int __kfifo_from_user_data(struct kfifo *fifo, | ||
164 | const void __user *from, unsigned int len, unsigned int off, | ||
165 | unsigned *lenout) | ||
166 | { | ||
167 | unsigned int l; | ||
168 | int ret; | ||
125 | 169 | ||
126 | /* | 170 | /* |
127 | * Ensure that we sample the fifo->out index -before- we | 171 | * Ensure that we sample the fifo->out index -before- we |
@@ -130,68 +174,272 @@ unsigned int __kfifo_put(struct kfifo *fifo, | |||
130 | 174 | ||
131 | smp_mb(); | 175 | smp_mb(); |
132 | 176 | ||
177 | off = __kfifo_off(fifo, fifo->in + off); | ||
178 | |||
133 | /* first put the data starting from fifo->in to buffer end */ | 179 | /* first put the data starting from fifo->in to buffer end */ |
134 | l = min(len, fifo->size - (fifo->in & (fifo->size - 1))); | 180 | l = min(len, fifo->size - off); |
135 | memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l); | 181 | ret = copy_from_user(fifo->buffer + off, from, l); |
182 | if (unlikely(ret)) { | ||
183 | *lenout = ret; | ||
184 | return -EFAULT; | ||
185 | } | ||
186 | *lenout = l; | ||
136 | 187 | ||
137 | /* then put the rest (if any) at the beginning of the buffer */ | 188 | /* then put the rest (if any) at the beginning of the buffer */ |
138 | memcpy(fifo->buffer, buffer + l, len - l); | 189 | ret = copy_from_user(fifo->buffer, from + l, len - l); |
190 | *lenout += ret ? ret : len - l; | ||
191 | return ret ? -EFAULT : 0; | ||
192 | } | ||
193 | |||
194 | static inline int __kfifo_to_user_data(struct kfifo *fifo, | ||
195 | void __user *to, unsigned int len, unsigned int off, unsigned *lenout) | ||
196 | { | ||
197 | unsigned int l; | ||
198 | int ret; | ||
139 | 199 | ||
140 | /* | 200 | /* |
141 | * Ensure that we add the bytes to the kfifo -before- | 201 | * Ensure that we sample the fifo->in index -before- we |
142 | * we update the fifo->in index. | 202 | * start removing bytes from the kfifo. |
143 | */ | 203 | */ |
144 | 204 | ||
145 | smp_wmb(); | 205 | smp_rmb(); |
206 | |||
207 | off = __kfifo_off(fifo, fifo->out + off); | ||
208 | |||
209 | /* first get the data from fifo->out until the end of the buffer */ | ||
210 | l = min(len, fifo->size - off); | ||
211 | ret = copy_to_user(to, fifo->buffer + off, l); | ||
212 | *lenout = l; | ||
213 | if (unlikely(ret)) { | ||
214 | *lenout -= ret; | ||
215 | return -EFAULT; | ||
216 | } | ||
217 | |||
218 | /* then get the rest (if any) from the beginning of the buffer */ | ||
219 | len -= l; | ||
220 | ret = copy_to_user(to + l, fifo->buffer, len); | ||
221 | if (unlikely(ret)) { | ||
222 | *lenout += len - ret; | ||
223 | return -EFAULT; | ||
224 | } | ||
225 | *lenout += len; | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | unsigned int __kfifo_in_n(struct kfifo *fifo, | ||
230 | const void *from, unsigned int len, unsigned int recsize) | ||
231 | { | ||
232 | if (kfifo_avail(fifo) < len + recsize) | ||
233 | return len + 1; | ||
234 | |||
235 | __kfifo_in_data(fifo, from, len, recsize); | ||
236 | return 0; | ||
237 | } | ||
238 | EXPORT_SYMBOL(__kfifo_in_n); | ||
146 | 239 | ||
147 | fifo->in += len; | 240 | /** |
241 | * kfifo_in - puts some data into the FIFO | ||
242 | * @fifo: the fifo to be used. | ||
243 | * @from: the data to be added. | ||
244 | * @len: the length of the data to be added. | ||
245 | * | ||
246 | * This function copies at most @len bytes from the @from buffer into | ||
247 | * the FIFO depending on the free space, and returns the number of | ||
248 | * bytes copied. | ||
249 | * | ||
250 | * Note that with only one concurrent reader and one concurrent | ||
251 | * writer, you don't need extra locking to use these functions. | ||
252 | */ | ||
253 | unsigned int kfifo_in(struct kfifo *fifo, const void *from, | ||
254 | unsigned int len) | ||
255 | { | ||
256 | len = min(kfifo_avail(fifo), len); | ||
148 | 257 | ||
258 | __kfifo_in_data(fifo, from, len, 0); | ||
259 | __kfifo_add_in(fifo, len); | ||
149 | return len; | 260 | return len; |
150 | } | 261 | } |
151 | EXPORT_SYMBOL(__kfifo_put); | 262 | EXPORT_SYMBOL(kfifo_in); |
263 | |||
264 | unsigned int __kfifo_in_generic(struct kfifo *fifo, | ||
265 | const void *from, unsigned int len, unsigned int recsize) | ||
266 | { | ||
267 | return __kfifo_in_rec(fifo, from, len, recsize); | ||
268 | } | ||
269 | EXPORT_SYMBOL(__kfifo_in_generic); | ||
270 | |||
271 | unsigned int __kfifo_out_n(struct kfifo *fifo, | ||
272 | void *to, unsigned int len, unsigned int recsize) | ||
273 | { | ||
274 | if (kfifo_len(fifo) < len + recsize) | ||
275 | return len; | ||
276 | |||
277 | __kfifo_out_data(fifo, to, len, recsize); | ||
278 | __kfifo_add_out(fifo, len + recsize); | ||
279 | return 0; | ||
280 | } | ||
281 | EXPORT_SYMBOL(__kfifo_out_n); | ||
152 | 282 | ||
153 | /** | 283 | /** |
154 | * __kfifo_get - gets some data from the FIFO, no locking version | 284 | * kfifo_out - gets some data from the FIFO |
155 | * @fifo: the fifo to be used. | 285 | * @fifo: the fifo to be used. |
156 | * @buffer: where the data must be copied. | 286 | * @to: where the data must be copied. |
157 | * @len: the size of the destination buffer. | 287 | * @len: the size of the destination buffer. |
158 | * | 288 | * |
159 | * This function copies at most @len bytes from the FIFO into the | 289 | * This function copies at most @len bytes from the FIFO into the |
160 | * @buffer and returns the number of copied bytes. | 290 | * @to buffer and returns the number of copied bytes. |
161 | * | 291 | * |
162 | * Note that with only one concurrent reader and one concurrent | 292 | * Note that with only one concurrent reader and one concurrent |
163 | * writer, you don't need extra locking to use these functions. | 293 | * writer, you don't need extra locking to use these functions. |
164 | */ | 294 | */ |
165 | unsigned int __kfifo_get(struct kfifo *fifo, | 295 | unsigned int kfifo_out(struct kfifo *fifo, void *to, unsigned int len) |
166 | unsigned char *buffer, unsigned int len) | ||
167 | { | 296 | { |
168 | unsigned int l; | 297 | len = min(kfifo_len(fifo), len); |
169 | 298 | ||
170 | len = min(len, fifo->in - fifo->out); | 299 | __kfifo_out_data(fifo, to, len, 0); |
300 | __kfifo_add_out(fifo, len); | ||
171 | 301 | ||
172 | /* | 302 | return len; |
173 | * Ensure that we sample the fifo->in index -before- we | 303 | } |
174 | * start removing bytes from the kfifo. | 304 | EXPORT_SYMBOL(kfifo_out); |
175 | */ | ||
176 | 305 | ||
177 | smp_rmb(); | 306 | /** |
307 | * kfifo_out_peek - copy some data from the FIFO, but do not remove it | ||
308 | * @fifo: the fifo to be used. | ||
309 | * @to: where the data must be copied. | ||
310 | * @len: the size of the destination buffer. | ||
311 | * @offset: offset into the fifo | ||
312 | * | ||
313 | * This function copies at most @len bytes at @offset from the FIFO | ||
314 | * into the @to buffer and returns the number of copied bytes. | ||
315 | * The data is not removed from the FIFO. | ||
316 | */ | ||
317 | unsigned int kfifo_out_peek(struct kfifo *fifo, void *to, unsigned int len, | ||
318 | unsigned offset) | ||
319 | { | ||
320 | len = min(kfifo_len(fifo), len + offset); | ||
178 | 321 | ||
179 | /* first get the data from fifo->out until the end of the buffer */ | 322 | __kfifo_out_data(fifo, to, len, offset); |
180 | l = min(len, fifo->size - (fifo->out & (fifo->size - 1))); | 323 | return len; |
181 | memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l); | 324 | } |
325 | EXPORT_SYMBOL(kfifo_out_peek); | ||
182 | 326 | ||
183 | /* then get the rest (if any) from the beginning of the buffer */ | 327 | unsigned int __kfifo_out_generic(struct kfifo *fifo, |
184 | memcpy(buffer + l, fifo->buffer, len - l); | 328 | void *to, unsigned int len, unsigned int recsize, |
329 | unsigned int *total) | ||
330 | { | ||
331 | return __kfifo_out_rec(fifo, to, len, recsize, total); | ||
332 | } | ||
333 | EXPORT_SYMBOL(__kfifo_out_generic); | ||
185 | 334 | ||
186 | /* | 335 | unsigned int __kfifo_from_user_n(struct kfifo *fifo, |
187 | * Ensure that we remove the bytes from the kfifo -before- | 336 | const void __user *from, unsigned int len, unsigned int recsize) |
188 | * we update the fifo->out index. | 337 | { |
189 | */ | 338 | unsigned total; |
190 | 339 | ||
191 | smp_mb(); | 340 | if (kfifo_avail(fifo) < len + recsize) |
341 | return len + 1; | ||
192 | 342 | ||
193 | fifo->out += len; | 343 | __kfifo_from_user_data(fifo, from, len, recsize, &total); |
344 | return total; | ||
345 | } | ||
346 | EXPORT_SYMBOL(__kfifo_from_user_n); | ||
194 | 347 | ||
195 | return len; | 348 | /** |
349 | * kfifo_from_user - puts some data from user space into the FIFO | ||
350 | * @fifo: the fifo to be used. | ||
351 | * @from: pointer to the data to be added. | ||
352 | * @len: the length of the data to be added. | ||
353 | * @total: the actual returned data length. | ||
354 | * | ||
355 | * This function copies at most @len bytes from the @from into the | ||
356 | * FIFO depending and returns -EFAULT/0. | ||
357 | * | ||
358 | * Note that with only one concurrent reader and one concurrent | ||
359 | * writer, you don't need extra locking to use these functions. | ||
360 | */ | ||
361 | int kfifo_from_user(struct kfifo *fifo, | ||
362 | const void __user *from, unsigned int len, unsigned *total) | ||
363 | { | ||
364 | int ret; | ||
365 | len = min(kfifo_avail(fifo), len); | ||
366 | ret = __kfifo_from_user_data(fifo, from, len, 0, total); | ||
367 | if (ret) | ||
368 | return ret; | ||
369 | __kfifo_add_in(fifo, len); | ||
370 | return 0; | ||
196 | } | 371 | } |
197 | EXPORT_SYMBOL(__kfifo_get); | 372 | EXPORT_SYMBOL(kfifo_from_user); |
373 | |||
374 | unsigned int __kfifo_from_user_generic(struct kfifo *fifo, | ||
375 | const void __user *from, unsigned int len, unsigned int recsize) | ||
376 | { | ||
377 | return __kfifo_from_user_rec(fifo, from, len, recsize); | ||
378 | } | ||
379 | EXPORT_SYMBOL(__kfifo_from_user_generic); | ||
380 | |||
381 | unsigned int __kfifo_to_user_n(struct kfifo *fifo, | ||
382 | void __user *to, unsigned int len, unsigned int reclen, | ||
383 | unsigned int recsize) | ||
384 | { | ||
385 | unsigned int ret, total; | ||
386 | |||
387 | if (kfifo_len(fifo) < reclen + recsize) | ||
388 | return len; | ||
389 | |||
390 | ret = __kfifo_to_user_data(fifo, to, reclen, recsize, &total); | ||
391 | |||
392 | if (likely(ret == 0)) | ||
393 | __kfifo_add_out(fifo, reclen + recsize); | ||
394 | |||
395 | return total; | ||
396 | } | ||
397 | EXPORT_SYMBOL(__kfifo_to_user_n); | ||
398 | |||
399 | /** | ||
400 | * kfifo_to_user - gets data from the FIFO and write it to user space | ||
401 | * @fifo: the fifo to be used. | ||
402 | * @to: where the data must be copied. | ||
403 | * @len: the size of the destination buffer. | ||
404 | * @lenout: pointer to output variable with copied data | ||
405 | * | ||
406 | * This function copies at most @len bytes from the FIFO into the | ||
407 | * @to buffer and 0 or -EFAULT. | ||
408 | * | ||
409 | * Note that with only one concurrent reader and one concurrent | ||
410 | * writer, you don't need extra locking to use these functions. | ||
411 | */ | ||
412 | int kfifo_to_user(struct kfifo *fifo, | ||
413 | void __user *to, unsigned int len, unsigned *lenout) | ||
414 | { | ||
415 | int ret; | ||
416 | len = min(kfifo_len(fifo), len); | ||
417 | ret = __kfifo_to_user_data(fifo, to, len, 0, lenout); | ||
418 | __kfifo_add_out(fifo, *lenout); | ||
419 | return ret; | ||
420 | } | ||
421 | EXPORT_SYMBOL(kfifo_to_user); | ||
422 | |||
423 | unsigned int __kfifo_to_user_generic(struct kfifo *fifo, | ||
424 | void __user *to, unsigned int len, unsigned int recsize, | ||
425 | unsigned int *total) | ||
426 | { | ||
427 | return __kfifo_to_user_rec(fifo, to, len, recsize, total); | ||
428 | } | ||
429 | EXPORT_SYMBOL(__kfifo_to_user_generic); | ||
430 | |||
431 | unsigned int __kfifo_peek_generic(struct kfifo *fifo, unsigned int recsize) | ||
432 | { | ||
433 | if (recsize == 0) | ||
434 | return kfifo_avail(fifo); | ||
435 | |||
436 | return __kfifo_peek_n(fifo, recsize); | ||
437 | } | ||
438 | EXPORT_SYMBOL(__kfifo_peek_generic); | ||
439 | |||
440 | void __kfifo_skip_generic(struct kfifo *fifo, unsigned int recsize) | ||
441 | { | ||
442 | __kfifo_skip_rec(fifo, recsize); | ||
443 | } | ||
444 | EXPORT_SYMBOL(__kfifo_skip_generic); | ||
445 | |||