aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/kfifo.h330
-rw-r--r--kernel/kfifo.c286
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 */
285static 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 */
306static 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 */
326extern unsigned int __kfifo_in_n(struct kfifo *fifo,
327 const void *from, unsigned int n, unsigned int recsize);
328
329extern unsigned int __kfifo_in_generic(struct kfifo *fifo,
330 const void *from, unsigned int n, unsigned int recsize);
331
332static 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 */
362static 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 */
374extern unsigned int __kfifo_out_n(struct kfifo *fifo,
375 void *to, unsigned int reclen, unsigned int recsize);
376
377extern unsigned int __kfifo_out_generic(struct kfifo *fifo,
378 void *to, unsigned int n,
379 unsigned int recsize, unsigned int *total);
380
381static 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 */
418static 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 */
432extern unsigned int __kfifo_from_user_n(struct kfifo *fifo,
433 const void __user *from, unsigned int n, unsigned int recsize);
434
435extern unsigned int __kfifo_from_user_generic(struct kfifo *fifo,
436 const void __user *from, unsigned int n, unsigned int recsize);
437
438static 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 */
469static 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 */
481extern unsigned int __kfifo_to_user_n(struct kfifo *fifo,
482 void __user *to, unsigned int n, unsigned int reclen,
483 unsigned int recsize);
484
485extern unsigned int __kfifo_to_user_generic(struct kfifo *fifo,
486 void __user *to, unsigned int n, unsigned int recsize,
487 unsigned int *total);
488
489static 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 */
527static 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 */
540extern 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 */
550static 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 */
564extern void __kfifo_skip_generic(struct kfifo *fifo, unsigned int recsize);
565
566static 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 */
589static 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 */
603static 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}
116EXPORT_SYMBOL(kfifo_skip); 116EXPORT_SYMBOL(kfifo_skip);
117 117
118/** 118static 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 */
131unsigned 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}
159EXPORT_SYMBOL(kfifo_in);
160 139
161/** 140static 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 */
173unsigned 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}
201EXPORT_SYMBOL(kfifo_out);
202 161
203/** 162static 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 */
215unsigned 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
188static 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
214unsigned 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}
223EXPORT_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 */
238unsigned 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}
250EXPORT_SYMBOL(kfifo_from_user); 247EXPORT_SYMBOL(kfifo_in);
248
249unsigned 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}
254EXPORT_SYMBOL(__kfifo_in_generic);
255
256unsigned 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}
266EXPORT_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 */
264unsigned int kfifo_to_user(struct kfifo *fifo, 280unsigned 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. 289EXPORT_SYMBOL(kfifo_out);
276 */
277 290
278 smp_rmb(); 291unsigned 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}
297EXPORT_SYMBOL(__kfifo_out_generic);
279 298
280 off = __kfifo_off(fifo, fifo->out); 299unsigned 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); 307EXPORT_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 */
321unsigned 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}
329EXPORT_SYMBOL(kfifo_from_user);
288 330
289 /* then get the rest (if any) from the beginning of the buffer */ 331unsigned 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}
336EXPORT_SYMBOL(__kfifo_from_user_generic);
291 337
292 if (unlikely(ret)) 338unsigned 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}
354EXPORT_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 */
368unsigned 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}
299EXPORT_SYMBOL(kfifo_to_user); 376EXPORT_SYMBOL(kfifo_to_user);
300 377
378unsigned 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}
384EXPORT_SYMBOL(__kfifo_to_user_generic);
385
386unsigned 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}
393EXPORT_SYMBOL(__kfifo_peek_generic);
394
395void __kfifo_skip_generic(struct kfifo *fifo, unsigned int recsize)
396{
397 __kfifo_skip_rec(fifo, recsize);
398}
399EXPORT_SYMBOL(__kfifo_skip_generic);
400