diff options
author | Stefani Seibold <stefani@seibold.net> | 2009-12-21 17:37:32 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-22 17:17:56 -0500 |
commit | 86d4880313603810901f639ccb5c88ff13d4ad3c (patch) | |
tree | c182d890b5c96a1143b70b00b93e3fc4a9263555 | |
parent | a121f24accac1600bf5b6fb1e12eeabdfed7cb1a (diff) |
kfifo: add record handling functions
Add kfifo_in_rec() - puts some record data into the FIFO
Add kfifo_out_rec() - gets some record data from the FIFO
Add kfifo_from_user_rec() - puts some data from user space into the FIFO
Add kfifo_to_user_rec() - gets data from the FIFO and write it to user space
Add kfifo_peek_rec() - gets the size of the next FIFO record field
Add kfifo_skip_rec() - skip the next fifo out record
Add kfifo_avail_rec() - determinate the number of bytes available in a record FIFO
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | include/linux/kfifo.h | 330 | ||||
-rw-r--r-- | kernel/kfifo.c | 286 |
2 files changed, 523 insertions, 93 deletions
diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h index d3230fb08bc7..486e8ad3bb50 100644 --- a/include/linux/kfifo.h +++ b/include/linux/kfifo.h | |||
@@ -278,4 +278,334 @@ static inline unsigned int __kfifo_off(struct kfifo *fifo, unsigned int off) | |||
278 | return off & (fifo->size - 1); | 278 | return off & (fifo->size - 1); |
279 | } | 279 | } |
280 | 280 | ||
281 | /** | ||
282 | * __kfifo_peek_n internal helper function for determinate the length of | ||
283 | * the next record in the fifo | ||
284 | */ | ||
285 | static inline unsigned int __kfifo_peek_n(struct kfifo *fifo, | ||
286 | unsigned int recsize) | ||
287 | { | ||
288 | #define __KFIFO_GET(fifo, off, shift) \ | ||
289 | ((fifo)->buffer[__kfifo_off((fifo), (fifo)->out+(off))] << (shift)) | ||
290 | |||
291 | unsigned int l; | ||
292 | |||
293 | l = __KFIFO_GET(fifo, 0, 0); | ||
294 | |||
295 | if (--recsize) | ||
296 | l |= __KFIFO_GET(fifo, 1, 8); | ||
297 | |||
298 | return l; | ||
299 | #undef __KFIFO_GET | ||
300 | } | ||
301 | |||
302 | /** | ||
303 | * __kfifo_poke_n internal helper function for storing the length of | ||
304 | * the next record into the fifo | ||
305 | */ | ||
306 | static inline void __kfifo_poke_n(struct kfifo *fifo, | ||
307 | unsigned int recsize, unsigned int n) | ||
308 | { | ||
309 | #define __KFIFO_PUT(fifo, off, val, shift) \ | ||
310 | ( \ | ||
311 | (fifo)->buffer[__kfifo_off((fifo), (fifo)->in+(off))] = \ | ||
312 | (unsigned char)((val) >> (shift)) \ | ||
313 | ) | ||
314 | |||
315 | __KFIFO_PUT(fifo, 0, n, 0); | ||
316 | |||
317 | if (--recsize) | ||
318 | __KFIFO_PUT(fifo, 1, n, 8); | ||
319 | #undef __KFIFO_PUT | ||
320 | } | ||
321 | |||
322 | /** | ||
323 | * __kfifo_in_... internal functions for put date into the fifo | ||
324 | * do not call it directly, use kfifo_in_rec() instead | ||
325 | */ | ||
326 | extern unsigned int __kfifo_in_n(struct kfifo *fifo, | ||
327 | const void *from, unsigned int n, unsigned int recsize); | ||
328 | |||
329 | extern unsigned int __kfifo_in_generic(struct kfifo *fifo, | ||
330 | const void *from, unsigned int n, unsigned int recsize); | ||
331 | |||
332 | static inline unsigned int __kfifo_in_rec(struct kfifo *fifo, | ||
333 | const void *from, unsigned int n, unsigned int recsize) | ||
334 | { | ||
335 | unsigned int ret; | ||
336 | |||
337 | ret = __kfifo_in_n(fifo, from, n, recsize); | ||
338 | |||
339 | if (likely(ret == 0)) { | ||
340 | if (recsize) | ||
341 | __kfifo_poke_n(fifo, recsize, n); | ||
342 | __kfifo_add_in(fifo, n + recsize); | ||
343 | } | ||
344 | return ret; | ||
345 | } | ||
346 | |||
347 | /** | ||
348 | * kfifo_in_rec - puts some record data into the FIFO | ||
349 | * @fifo: the fifo to be used. | ||
350 | * @from: the data to be added. | ||
351 | * @n: the length of the data to be added. | ||
352 | * @recsize: size of record field | ||
353 | * | ||
354 | * This function copies @n bytes from the @from into the FIFO and returns | ||
355 | * the number of bytes which cannot be copied. | ||
356 | * A returned value greater than the @n value means that the record doesn't | ||
357 | * fit into the buffer. | ||
358 | * | ||
359 | * Note that with only one concurrent reader and one concurrent | ||
360 | * writer, you don't need extra locking to use these functions. | ||
361 | */ | ||
362 | static inline __must_check unsigned int kfifo_in_rec(struct kfifo *fifo, | ||
363 | void *from, unsigned int n, unsigned int recsize) | ||
364 | { | ||
365 | if (!__builtin_constant_p(recsize)) | ||
366 | return __kfifo_in_generic(fifo, from, n, recsize); | ||
367 | return __kfifo_in_rec(fifo, from, n, recsize); | ||
368 | } | ||
369 | |||
370 | /** | ||
371 | * __kfifo_out_... internal functions for get date from the fifo | ||
372 | * do not call it directly, use kfifo_out_rec() instead | ||
373 | */ | ||
374 | extern unsigned int __kfifo_out_n(struct kfifo *fifo, | ||
375 | void *to, unsigned int reclen, unsigned int recsize); | ||
376 | |||
377 | extern unsigned int __kfifo_out_generic(struct kfifo *fifo, | ||
378 | void *to, unsigned int n, | ||
379 | unsigned int recsize, unsigned int *total); | ||
380 | |||
381 | static inline unsigned int __kfifo_out_rec(struct kfifo *fifo, | ||
382 | void *to, unsigned int n, unsigned int recsize, | ||
383 | unsigned int *total) | ||
384 | { | ||
385 | unsigned int l; | ||
386 | |||
387 | if (!recsize) { | ||
388 | l = n; | ||
389 | if (total) | ||
390 | *total = l; | ||
391 | } else { | ||
392 | l = __kfifo_peek_n(fifo, recsize); | ||
393 | if (total) | ||
394 | *total = l; | ||
395 | if (n < l) | ||
396 | return l; | ||
397 | } | ||
398 | |||
399 | return __kfifo_out_n(fifo, to, l, recsize); | ||
400 | } | ||
401 | |||
402 | /** | ||
403 | * kfifo_out_rec - gets some record data from the FIFO | ||
404 | * @fifo: the fifo to be used. | ||
405 | * @to: where the data must be copied. | ||
406 | * @n: the size of the destination buffer. | ||
407 | * @recsize: size of record field | ||
408 | * @total: pointer where the total number of to copied bytes should stored | ||
409 | * | ||
410 | * This function copies at most @n bytes from the FIFO to @to and returns the | ||
411 | * number of bytes which cannot be copied. | ||
412 | * A returned value greater than the @n value means that the record doesn't | ||
413 | * fit into the @to buffer. | ||
414 | * | ||
415 | * Note that with only one concurrent reader and one concurrent | ||
416 | * writer, you don't need extra locking to use these functions. | ||
417 | */ | ||
418 | static inline __must_check unsigned int kfifo_out_rec(struct kfifo *fifo, | ||
419 | void *to, unsigned int n, unsigned int recsize, | ||
420 | unsigned int *total) | ||
421 | |||
422 | { | ||
423 | if (!__builtin_constant_p(recsize)) | ||
424 | return __kfifo_out_generic(fifo, to, n, recsize, total); | ||
425 | return __kfifo_out_rec(fifo, to, n, recsize, total); | ||
426 | } | ||
427 | |||
428 | /** | ||
429 | * __kfifo_from_user_... internal functions for transfer from user space into | ||
430 | * the fifo. do not call it directly, use kfifo_from_user_rec() instead | ||
431 | */ | ||
432 | extern unsigned int __kfifo_from_user_n(struct kfifo *fifo, | ||
433 | const void __user *from, unsigned int n, unsigned int recsize); | ||
434 | |||
435 | extern unsigned int __kfifo_from_user_generic(struct kfifo *fifo, | ||
436 | const void __user *from, unsigned int n, unsigned int recsize); | ||
437 | |||
438 | static inline unsigned int __kfifo_from_user_rec(struct kfifo *fifo, | ||
439 | const void __user *from, unsigned int n, unsigned int recsize) | ||
440 | { | ||
441 | unsigned int ret; | ||
442 | |||
443 | ret = __kfifo_from_user_n(fifo, from, n, recsize); | ||
444 | |||
445 | if (likely(ret == 0)) { | ||
446 | if (recsize) | ||
447 | __kfifo_poke_n(fifo, recsize, n); | ||
448 | __kfifo_add_in(fifo, n + recsize); | ||
449 | } | ||
450 | return ret; | ||
451 | } | ||
452 | |||
453 | /** | ||
454 | * kfifo_from_user_rec - puts some data from user space into the FIFO | ||
455 | * @fifo: the fifo to be used. | ||
456 | * @from: pointer to the data to be added. | ||
457 | * @n: the length of the data to be added. | ||
458 | * @recsize: size of record field | ||
459 | * | ||
460 | * This function copies @n bytes from the @from into the | ||
461 | * FIFO and returns the number of bytes which cannot be copied. | ||
462 | * | ||
463 | * If the returned value is equal or less the @n value, the copy_from_user() | ||
464 | * functions has failed. Otherwise the record doesn't fit into the buffer. | ||
465 | * | ||
466 | * Note that with only one concurrent reader and one concurrent | ||
467 | * writer, you don't need extra locking to use these functions. | ||
468 | */ | ||
469 | static inline __must_check unsigned int kfifo_from_user_rec(struct kfifo *fifo, | ||
470 | const void __user *from, unsigned int n, unsigned int recsize) | ||
471 | { | ||
472 | if (!__builtin_constant_p(recsize)) | ||
473 | return __kfifo_from_user_generic(fifo, from, n, recsize); | ||
474 | return __kfifo_from_user_rec(fifo, from, n, recsize); | ||
475 | } | ||
476 | |||
477 | /** | ||
478 | * __kfifo_to_user_... internal functions for transfer fifo data into user space | ||
479 | * do not call it directly, use kfifo_to_user_rec() instead | ||
480 | */ | ||
481 | extern unsigned int __kfifo_to_user_n(struct kfifo *fifo, | ||
482 | void __user *to, unsigned int n, unsigned int reclen, | ||
483 | unsigned int recsize); | ||
484 | |||
485 | extern unsigned int __kfifo_to_user_generic(struct kfifo *fifo, | ||
486 | void __user *to, unsigned int n, unsigned int recsize, | ||
487 | unsigned int *total); | ||
488 | |||
489 | static inline unsigned int __kfifo_to_user_rec(struct kfifo *fifo, | ||
490 | void __user *to, unsigned int n, | ||
491 | unsigned int recsize, unsigned int *total) | ||
492 | { | ||
493 | unsigned int l; | ||
494 | |||
495 | if (!recsize) { | ||
496 | l = n; | ||
497 | if (total) | ||
498 | *total = l; | ||
499 | } else { | ||
500 | l = __kfifo_peek_n(fifo, recsize); | ||
501 | if (total) | ||
502 | *total = l; | ||
503 | if (n < l) | ||
504 | return l; | ||
505 | } | ||
506 | |||
507 | return __kfifo_to_user_n(fifo, to, n, l, recsize); | ||
508 | } | ||
509 | |||
510 | /** | ||
511 | * kfifo_to_user_rec - gets data from the FIFO and write it to user space | ||
512 | * @fifo: the fifo to be used. | ||
513 | * @to: where the data must be copied. | ||
514 | * @n: the size of the destination buffer. | ||
515 | * @recsize: size of record field | ||
516 | * @total: pointer where the total number of to copied bytes should stored | ||
517 | * | ||
518 | * This function copies at most @n bytes from the FIFO to the @to. | ||
519 | * In case of an error, the function returns the number of bytes which cannot | ||
520 | * be copied. | ||
521 | * If the returned value is equal or less the @n value, the copy_to_user() | ||
522 | * functions has failed. Otherwise the record doesn't fit into the @to buffer. | ||
523 | * | ||
524 | * Note that with only one concurrent reader and one concurrent | ||
525 | * writer, you don't need extra locking to use these functions. | ||
526 | */ | ||
527 | static inline __must_check unsigned int kfifo_to_user_rec(struct kfifo *fifo, | ||
528 | void __user *to, unsigned int n, unsigned int recsize, | ||
529 | unsigned int *total) | ||
530 | { | ||
531 | if (!__builtin_constant_p(recsize)) | ||
532 | return __kfifo_to_user_generic(fifo, to, n, recsize, total); | ||
533 | return __kfifo_to_user_rec(fifo, to, n, recsize, total); | ||
534 | } | ||
535 | |||
536 | /** | ||
537 | * __kfifo_peek_... internal functions for peek into the next fifo record | ||
538 | * do not call it directly, use kfifo_peek_rec() instead | ||
539 | */ | ||
540 | extern unsigned int __kfifo_peek_generic(struct kfifo *fifo, | ||
541 | unsigned int recsize); | ||
542 | |||
543 | /** | ||
544 | * kfifo_peek_rec - gets the size of the next FIFO record data | ||
545 | * @fifo: the fifo to be used. | ||
546 | * @recsize: size of record field | ||
547 | * | ||
548 | * This function returns the size of the next FIFO record in number of bytes | ||
549 | */ | ||
550 | static inline __must_check unsigned int kfifo_peek_rec(struct kfifo *fifo, | ||
551 | unsigned int recsize) | ||
552 | { | ||
553 | if (!__builtin_constant_p(recsize)) | ||
554 | return __kfifo_peek_generic(fifo, recsize); | ||
555 | if (!recsize) | ||
556 | return kfifo_len(fifo); | ||
557 | return __kfifo_peek_n(fifo, recsize); | ||
558 | } | ||
559 | |||
560 | /** | ||
561 | * __kfifo_skip_... internal functions for skip the next fifo record | ||
562 | * do not call it directly, use kfifo_skip_rec() instead | ||
563 | */ | ||
564 | extern void __kfifo_skip_generic(struct kfifo *fifo, unsigned int recsize); | ||
565 | |||
566 | static inline void __kfifo_skip_rec(struct kfifo *fifo, | ||
567 | unsigned int recsize) | ||
568 | { | ||
569 | unsigned int l; | ||
570 | |||
571 | if (recsize) { | ||
572 | l = __kfifo_peek_n(fifo, recsize); | ||
573 | |||
574 | if (l + recsize <= kfifo_len(fifo)) { | ||
575 | __kfifo_add_out(fifo, l + recsize); | ||
576 | return; | ||
577 | } | ||
578 | } | ||
579 | kfifo_reset_out(fifo); | ||
580 | } | ||
581 | |||
582 | /** | ||
583 | * kfifo_skip_rec - skip the next fifo out record | ||
584 | * @fifo: the fifo to be used. | ||
585 | * @recsize: size of record field | ||
586 | * | ||
587 | * This function skips the next FIFO record | ||
588 | */ | ||
589 | static inline void kfifo_skip_rec(struct kfifo *fifo, | ||
590 | unsigned int recsize) | ||
591 | { | ||
592 | if (!__builtin_constant_p(recsize)) | ||
593 | __kfifo_skip_generic(fifo, recsize); | ||
594 | else | ||
595 | __kfifo_skip_rec(fifo, recsize); | ||
596 | } | ||
597 | |||
598 | /** | ||
599 | * kfifo_avail_rec - returns the number of bytes available in a record FIFO | ||
600 | * @fifo: the fifo to be used. | ||
601 | * @recsize: size of record field | ||
602 | */ | ||
603 | static inline __must_check unsigned int kfifo_avail_rec(struct kfifo *fifo, | ||
604 | unsigned int recsize) | ||
605 | { | ||
606 | unsigned int l = kfifo_size(fifo) - kfifo_len(fifo); | ||
607 | |||
608 | return (l > recsize) ? l - recsize : 0; | ||
609 | } | ||
610 | |||
281 | #endif | 611 | #endif |
diff --git a/kernel/kfifo.c b/kernel/kfifo.c index 2a78425ef67f..e92d519f93b1 100644 --- a/kernel/kfifo.c +++ b/kernel/kfifo.c | |||
@@ -115,27 +115,11 @@ void kfifo_skip(struct kfifo *fifo, unsigned int len) | |||
115 | } | 115 | } |
116 | EXPORT_SYMBOL(kfifo_skip); | 116 | EXPORT_SYMBOL(kfifo_skip); |
117 | 117 | ||
118 | /** | 118 | static inline void __kfifo_in_data(struct kfifo *fifo, |
119 | * kfifo_in - puts some data into the FIFO | 119 | const void *from, unsigned int len, unsigned int off) |
120 | * @fifo: the fifo to be used. | ||
121 | * @from: the data to be added. | ||
122 | * @len: the length of the data to be added. | ||
123 | * | ||
124 | * This function copies at most @len bytes from the @from buffer into | ||
125 | * the FIFO depending on the free space, and returns the number of | ||
126 | * bytes copied. | ||
127 | * | ||
128 | * Note that with only one concurrent reader and one concurrent | ||
129 | * writer, you don't need extra locking to use these functions. | ||
130 | */ | ||
131 | unsigned int kfifo_in(struct kfifo *fifo, | ||
132 | const unsigned char *from, unsigned int len) | ||
133 | { | 120 | { |
134 | unsigned int off; | ||
135 | unsigned int l; | 121 | unsigned int l; |
136 | 122 | ||
137 | len = min(len, fifo->size - fifo->in + fifo->out); | ||
138 | |||
139 | /* | 123 | /* |
140 | * Ensure that we sample the fifo->out index -before- we | 124 | * Ensure that we sample the fifo->out index -before- we |
141 | * start putting bytes into the kfifo. | 125 | * start putting bytes into the kfifo. |
@@ -143,7 +127,7 @@ unsigned int kfifo_in(struct kfifo *fifo, | |||
143 | 127 | ||
144 | smp_mb(); | 128 | smp_mb(); |
145 | 129 | ||
146 | off = __kfifo_off(fifo, fifo->in); | 130 | off = __kfifo_off(fifo, fifo->in + off); |
147 | 131 | ||
148 | /* first put the data starting from fifo->in to buffer end */ | 132 | /* first put the data starting from fifo->in to buffer end */ |
149 | l = min(len, fifo->size - off); | 133 | l = min(len, fifo->size - off); |
@@ -151,33 +135,13 @@ unsigned int kfifo_in(struct kfifo *fifo, | |||
151 | 135 | ||
152 | /* then put the rest (if any) at the beginning of the buffer */ | 136 | /* then put the rest (if any) at the beginning of the buffer */ |
153 | memcpy(fifo->buffer, from + l, len - l); | 137 | memcpy(fifo->buffer, from + l, len - l); |
154 | |||
155 | __kfifo_add_in(fifo, len); | ||
156 | |||
157 | return len; | ||
158 | } | 138 | } |
159 | EXPORT_SYMBOL(kfifo_in); | ||
160 | 139 | ||
161 | /** | 140 | static inline void __kfifo_out_data(struct kfifo *fifo, |
162 | * kfifo_out - gets some data from the FIFO | 141 | void *to, unsigned int len, unsigned int off) |
163 | * @fifo: the fifo to be used. | ||
164 | * @to: where the data must be copied. | ||
165 | * @len: the size of the destination buffer. | ||
166 | * | ||
167 | * This function copies at most @len bytes from the FIFO into the | ||
168 | * @to buffer and returns the number of copied bytes. | ||
169 | * | ||
170 | * Note that with only one concurrent reader and one concurrent | ||
171 | * writer, you don't need extra locking to use these functions. | ||
172 | */ | ||
173 | unsigned int kfifo_out(struct kfifo *fifo, | ||
174 | unsigned char *to, unsigned int len) | ||
175 | { | 142 | { |
176 | unsigned int off; | ||
177 | unsigned int l; | 143 | unsigned int l; |
178 | 144 | ||
179 | len = min(len, fifo->in - fifo->out); | ||
180 | |||
181 | /* | 145 | /* |
182 | * Ensure that we sample the fifo->in index -before- we | 146 | * Ensure that we sample the fifo->in index -before- we |
183 | * start removing bytes from the kfifo. | 147 | * start removing bytes from the kfifo. |
@@ -185,7 +149,7 @@ unsigned int kfifo_out(struct kfifo *fifo, | |||
185 | 149 | ||
186 | smp_rmb(); | 150 | smp_rmb(); |
187 | 151 | ||
188 | off = __kfifo_off(fifo, fifo->out); | 152 | off = __kfifo_off(fifo, fifo->out + off); |
189 | 153 | ||
190 | /* first get the data from fifo->out until the end of the buffer */ | 154 | /* first get the data from fifo->out until the end of the buffer */ |
191 | l = min(len, fifo->size - off); | 155 | l = min(len, fifo->size - off); |
@@ -193,34 +157,14 @@ unsigned int kfifo_out(struct kfifo *fifo, | |||
193 | 157 | ||
194 | /* then get the rest (if any) from the beginning of the buffer */ | 158 | /* then get the rest (if any) from the beginning of the buffer */ |
195 | memcpy(to + l, fifo->buffer, len - l); | 159 | memcpy(to + l, fifo->buffer, len - l); |
196 | |||
197 | __kfifo_add_out(fifo, len); | ||
198 | |||
199 | return len; | ||
200 | } | 160 | } |
201 | EXPORT_SYMBOL(kfifo_out); | ||
202 | 161 | ||
203 | /** | 162 | static inline unsigned int __kfifo_from_user_data(struct kfifo *fifo, |
204 | * kfifo_from_user - puts some data from user space into the FIFO | 163 | const void __user *from, unsigned int len, unsigned int off) |
205 | * @fifo: the fifo to be used. | ||
206 | * @from: pointer to the data to be added. | ||
207 | * @len: the length of the data to be added. | ||
208 | * | ||
209 | * This function copies at most @len bytes from the @from into the | ||
210 | * FIFO depending and returns the number of copied bytes. | ||
211 | * | ||
212 | * Note that with only one concurrent reader and one concurrent | ||
213 | * writer, you don't need extra locking to use these functions. | ||
214 | */ | ||
215 | unsigned int kfifo_from_user(struct kfifo *fifo, | ||
216 | const void __user *from, unsigned int len) | ||
217 | { | 164 | { |
218 | unsigned int off; | ||
219 | unsigned int l; | 165 | unsigned int l; |
220 | int ret; | 166 | int ret; |
221 | 167 | ||
222 | len = min(len, fifo->size - fifo->in + fifo->out); | ||
223 | |||
224 | /* | 168 | /* |
225 | * Ensure that we sample the fifo->out index -before- we | 169 | * Ensure that we sample the fifo->out index -before- we |
226 | * start putting bytes into the kfifo. | 170 | * start putting bytes into the kfifo. |
@@ -228,29 +172,101 @@ unsigned int kfifo_from_user(struct kfifo *fifo, | |||
228 | 172 | ||
229 | smp_mb(); | 173 | smp_mb(); |
230 | 174 | ||
231 | off = __kfifo_off(fifo, fifo->in); | 175 | off = __kfifo_off(fifo, fifo->in + off); |
232 | 176 | ||
233 | /* first put the data starting from fifo->in to buffer end */ | 177 | /* first put the data starting from fifo->in to buffer end */ |
234 | l = min(len, fifo->size - off); | 178 | l = min(len, fifo->size - off); |
235 | ret = copy_from_user(fifo->buffer + off, from, l); | 179 | ret = copy_from_user(fifo->buffer + off, from, l); |
236 | 180 | ||
237 | if (unlikely(ret)) | 181 | if (unlikely(ret)) |
238 | return l - ret; | 182 | return ret + len - l; |
239 | 183 | ||
240 | /* then put the rest (if any) at the beginning of the buffer */ | 184 | /* then put the rest (if any) at the beginning of the buffer */ |
241 | ret = copy_from_user(fifo->buffer, from + l, len - l); | 185 | return copy_from_user(fifo->buffer, from + l, len - l); |
186 | } | ||
187 | |||
188 | static inline unsigned int __kfifo_to_user_data(struct kfifo *fifo, | ||
189 | void __user *to, unsigned int len, unsigned int off) | ||
190 | { | ||
191 | unsigned int l; | ||
192 | int ret; | ||
193 | |||
194 | /* | ||
195 | * Ensure that we sample the fifo->in index -before- we | ||
196 | * start removing bytes from the kfifo. | ||
197 | */ | ||
198 | |||
199 | smp_rmb(); | ||
200 | |||
201 | off = __kfifo_off(fifo, fifo->out + off); | ||
202 | |||
203 | /* first get the data from fifo->out until the end of the buffer */ | ||
204 | l = min(len, fifo->size - off); | ||
205 | ret = copy_to_user(to, fifo->buffer + off, l); | ||
242 | 206 | ||
243 | if (unlikely(ret)) | 207 | if (unlikely(ret)) |
244 | return len - ret; | 208 | return ret + len - l; |
245 | 209 | ||
246 | __kfifo_add_in(fifo, len); | 210 | /* then get the rest (if any) from the beginning of the buffer */ |
211 | return copy_to_user(to + l, fifo->buffer, len - l); | ||
212 | } | ||
247 | 213 | ||
214 | unsigned int __kfifo_in_n(struct kfifo *fifo, | ||
215 | const void *from, unsigned int len, unsigned int recsize) | ||
216 | { | ||
217 | if (kfifo_avail(fifo) < len + recsize) | ||
218 | return len + 1; | ||
219 | |||
220 | __kfifo_in_data(fifo, from, len, recsize); | ||
221 | return 0; | ||
222 | } | ||
223 | EXPORT_SYMBOL(__kfifo_in_n); | ||
224 | |||
225 | /** | ||
226 | * kfifo_in - puts some data into the FIFO | ||
227 | * @fifo: the fifo to be used. | ||
228 | * @from: the data to be added. | ||
229 | * @len: the length of the data to be added. | ||
230 | * | ||
231 | * This function copies at most @len bytes from the @from buffer into | ||
232 | * the FIFO depending on the free space, and returns the number of | ||
233 | * bytes copied. | ||
234 | * | ||
235 | * Note that with only one concurrent reader and one concurrent | ||
236 | * writer, you don't need extra locking to use these functions. | ||
237 | */ | ||
238 | unsigned int kfifo_in(struct kfifo *fifo, const unsigned char *from, | ||
239 | unsigned int len) | ||
240 | { | ||
241 | len = min(kfifo_avail(fifo), len); | ||
242 | |||
243 | __kfifo_in_data(fifo, from, len, 0); | ||
244 | __kfifo_add_in(fifo, len); | ||
248 | return len; | 245 | return len; |
249 | } | 246 | } |
250 | EXPORT_SYMBOL(kfifo_from_user); | 247 | EXPORT_SYMBOL(kfifo_in); |
248 | |||
249 | unsigned int __kfifo_in_generic(struct kfifo *fifo, | ||
250 | const void *from, unsigned int len, unsigned int recsize) | ||
251 | { | ||
252 | return __kfifo_in_rec(fifo, from, len, recsize); | ||
253 | } | ||
254 | EXPORT_SYMBOL(__kfifo_in_generic); | ||
255 | |||
256 | unsigned int __kfifo_out_n(struct kfifo *fifo, | ||
257 | void *to, unsigned int len, unsigned int recsize) | ||
258 | { | ||
259 | if (kfifo_len(fifo) < len + recsize) | ||
260 | return len; | ||
261 | |||
262 | __kfifo_out_data(fifo, to, len, recsize); | ||
263 | __kfifo_add_out(fifo, len + recsize); | ||
264 | return 0; | ||
265 | } | ||
266 | EXPORT_SYMBOL(__kfifo_out_n); | ||
251 | 267 | ||
252 | /** | 268 | /** |
253 | * kfifo_to_user - gets data from the FIFO and write it to user space | 269 | * kfifo_out - gets some data from the FIFO |
254 | * @fifo: the fifo to be used. | 270 | * @fifo: the fifo to be used. |
255 | * @to: where the data must be copied. | 271 | * @to: where the data must be copied. |
256 | * @len: the size of the destination buffer. | 272 | * @len: the size of the destination buffer. |
@@ -261,40 +277,124 @@ EXPORT_SYMBOL(kfifo_from_user); | |||
261 | * Note that with only one concurrent reader and one concurrent | 277 | * Note that with only one concurrent reader and one concurrent |
262 | * writer, you don't need extra locking to use these functions. | 278 | * writer, you don't need extra locking to use these functions. |
263 | */ | 279 | */ |
264 | unsigned int kfifo_to_user(struct kfifo *fifo, | 280 | unsigned int kfifo_out(struct kfifo *fifo, unsigned char *to, unsigned int len) |
265 | void __user *to, unsigned int len) | ||
266 | { | 281 | { |
267 | unsigned int off; | 282 | len = min(kfifo_len(fifo), len); |
268 | unsigned int l; | ||
269 | int ret; | ||
270 | 283 | ||
271 | len = min(len, fifo->in - fifo->out); | 284 | __kfifo_out_data(fifo, to, len, 0); |
285 | __kfifo_add_out(fifo, len); | ||
272 | 286 | ||
273 | /* | 287 | return len; |
274 | * Ensure that we sample the fifo->in index -before- we | 288 | } |
275 | * start removing bytes from the kfifo. | 289 | EXPORT_SYMBOL(kfifo_out); |
276 | */ | ||
277 | 290 | ||
278 | smp_rmb(); | 291 | unsigned int __kfifo_out_generic(struct kfifo *fifo, |
292 | void *to, unsigned int len, unsigned int recsize, | ||
293 | unsigned int *total) | ||
294 | { | ||
295 | return __kfifo_out_rec(fifo, to, len, recsize, total); | ||
296 | } | ||
297 | EXPORT_SYMBOL(__kfifo_out_generic); | ||
279 | 298 | ||
280 | off = __kfifo_off(fifo, fifo->out); | 299 | unsigned int __kfifo_from_user_n(struct kfifo *fifo, |
300 | const void __user *from, unsigned int len, unsigned int recsize) | ||
301 | { | ||
302 | if (kfifo_avail(fifo) < len + recsize) | ||
303 | return len + 1; | ||
281 | 304 | ||
282 | /* first get the data from fifo->out until the end of the buffer */ | 305 | return __kfifo_from_user_data(fifo, from, len, recsize); |
283 | l = min(len, fifo->size - off); | 306 | } |
284 | ret = copy_to_user(to, fifo->buffer + off, l); | 307 | EXPORT_SYMBOL(__kfifo_from_user_n); |
285 | 308 | ||
286 | if (unlikely(ret)) | 309 | /** |
287 | return l - ret; | 310 | * kfifo_from_user - puts some data from user space into the FIFO |
311 | * @fifo: the fifo to be used. | ||
312 | * @from: pointer to the data to be added. | ||
313 | * @len: the length of the data to be added. | ||
314 | * | ||
315 | * This function copies at most @len bytes from the @from into the | ||
316 | * FIFO depending and returns the number of copied bytes. | ||
317 | * | ||
318 | * Note that with only one concurrent reader and one concurrent | ||
319 | * writer, you don't need extra locking to use these functions. | ||
320 | */ | ||
321 | unsigned int kfifo_from_user(struct kfifo *fifo, | ||
322 | const void __user *from, unsigned int len) | ||
323 | { | ||
324 | len = min(kfifo_avail(fifo), len); | ||
325 | len -= __kfifo_from_user_data(fifo, from, len, 0); | ||
326 | __kfifo_add_in(fifo, len); | ||
327 | return len; | ||
328 | } | ||
329 | EXPORT_SYMBOL(kfifo_from_user); | ||
288 | 330 | ||
289 | /* then get the rest (if any) from the beginning of the buffer */ | 331 | unsigned int __kfifo_from_user_generic(struct kfifo *fifo, |
290 | ret = copy_to_user(to + l, fifo->buffer, len - l); | 332 | const void __user *from, unsigned int len, unsigned int recsize) |
333 | { | ||
334 | return __kfifo_from_user_rec(fifo, from, len, recsize); | ||
335 | } | ||
336 | EXPORT_SYMBOL(__kfifo_from_user_generic); | ||
291 | 337 | ||
292 | if (unlikely(ret)) | 338 | unsigned int __kfifo_to_user_n(struct kfifo *fifo, |
293 | return len - ret; | 339 | void __user *to, unsigned int len, unsigned int reclen, |
340 | unsigned int recsize) | ||
341 | { | ||
342 | unsigned int ret; | ||
294 | 343 | ||
295 | __kfifo_add_out(fifo, len); | 344 | if (kfifo_len(fifo) < reclen + recsize) |
345 | return len; | ||
296 | 346 | ||
347 | ret = __kfifo_to_user_data(fifo, to, reclen, recsize); | ||
348 | |||
349 | if (likely(ret == 0)) | ||
350 | __kfifo_add_out(fifo, reclen + recsize); | ||
351 | |||
352 | return ret; | ||
353 | } | ||
354 | EXPORT_SYMBOL(__kfifo_to_user_n); | ||
355 | |||
356 | /** | ||
357 | * kfifo_to_user - gets data from the FIFO and write it to user space | ||
358 | * @fifo: the fifo to be used. | ||
359 | * @to: where the data must be copied. | ||
360 | * @len: the size of the destination buffer. | ||
361 | * | ||
362 | * This function copies at most @len bytes from the FIFO into the | ||
363 | * @to buffer and returns the number of copied bytes. | ||
364 | * | ||
365 | * Note that with only one concurrent reader and one concurrent | ||
366 | * writer, you don't need extra locking to use these functions. | ||
367 | */ | ||
368 | unsigned int kfifo_to_user(struct kfifo *fifo, | ||
369 | void __user *to, unsigned int len) | ||
370 | { | ||
371 | len = min(kfifo_len(fifo), len); | ||
372 | len -= __kfifo_to_user_data(fifo, to, len, 0); | ||
373 | __kfifo_add_out(fifo, len); | ||
297 | return len; | 374 | return len; |
298 | } | 375 | } |
299 | EXPORT_SYMBOL(kfifo_to_user); | 376 | EXPORT_SYMBOL(kfifo_to_user); |
300 | 377 | ||
378 | unsigned int __kfifo_to_user_generic(struct kfifo *fifo, | ||
379 | void __user *to, unsigned int len, unsigned int recsize, | ||
380 | unsigned int *total) | ||
381 | { | ||
382 | return __kfifo_to_user_rec(fifo, to, len, recsize, total); | ||
383 | } | ||
384 | EXPORT_SYMBOL(__kfifo_to_user_generic); | ||
385 | |||
386 | unsigned int __kfifo_peek_generic(struct kfifo *fifo, unsigned int recsize) | ||
387 | { | ||
388 | if (recsize == 0) | ||
389 | return kfifo_avail(fifo); | ||
390 | |||
391 | return __kfifo_peek_n(fifo, recsize); | ||
392 | } | ||
393 | EXPORT_SYMBOL(__kfifo_peek_generic); | ||
394 | |||
395 | void __kfifo_skip_generic(struct kfifo *fifo, unsigned int recsize) | ||
396 | { | ||
397 | __kfifo_skip_rec(fifo, recsize); | ||
398 | } | ||
399 | EXPORT_SYMBOL(__kfifo_skip_generic); | ||
400 | |||