Branch data Line data Source code
1 : : /*
2 : : * A generic kernel FIFO implementation
3 : : *
4 : : * Copyright (C) 2009/2010 Stefani Seibold <stefani@seibold.net>
5 : : *
6 : : * This program is free software; you can redistribute it and/or modify
7 : : * it under the terms of the GNU General Public License as published by
8 : : * the Free Software Foundation; either version 2 of the License, or
9 : : * (at your option) any later version.
10 : : *
11 : : * This program is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : : * GNU General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU General Public License
17 : : * along with this program; if not, write to the Free Software
18 : : * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 : : *
20 : : */
21 : :
22 : : #include <linux/kernel.h>
23 : : #include <linux/export.h>
24 : : #include <linux/slab.h>
25 : : #include <linux/err.h>
26 : : #include <linux/log2.h>
27 : : #include <linux/uaccess.h>
28 : : #include <linux/kfifo.h>
29 : :
30 : : /*
31 : : * internal helper to calculate the unused elements in a fifo
32 : : */
33 : : static inline unsigned int kfifo_unused(struct __kfifo *fifo)
34 : : {
35 : 0 : return (fifo->mask + 1) - (fifo->in - fifo->out);
36 : : }
37 : :
38 : 0 : int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
39 : : size_t esize, gfp_t gfp_mask)
40 : : {
41 : : /*
42 : : * round down to the next power of 2, since our 'let the indices
43 : : * wrap' technique works only in this case.
44 : : */
45 [ # # ][ # # ]: 0 : size = roundup_pow_of_two(size);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
46 : :
47 : 0 : fifo->in = 0;
48 : 0 : fifo->out = 0;
49 : 0 : fifo->esize = esize;
50 : :
51 [ # # ]: 0 : if (size < 2) {
52 : 0 : fifo->data = NULL;
53 : 0 : fifo->mask = 0;
54 : 0 : return -EINVAL;
55 : : }
56 : :
57 : 0 : fifo->data = kmalloc(size * esize, gfp_mask);
58 : :
59 [ # # ]: 0 : if (!fifo->data) {
60 : 0 : fifo->mask = 0;
61 : 0 : return -ENOMEM;
62 : : }
63 : 0 : fifo->mask = size - 1;
64 : :
65 : 0 : return 0;
66 : : }
67 : : EXPORT_SYMBOL(__kfifo_alloc);
68 : :
69 : 0 : void __kfifo_free(struct __kfifo *fifo)
70 : : {
71 : 0 : kfree(fifo->data);
72 : 0 : fifo->in = 0;
73 : 0 : fifo->out = 0;
74 : 0 : fifo->esize = 0;
75 : 0 : fifo->data = NULL;
76 : 0 : fifo->mask = 0;
77 : 0 : }
78 : : EXPORT_SYMBOL(__kfifo_free);
79 : :
80 : 0 : int __kfifo_init(struct __kfifo *fifo, void *buffer,
81 : : unsigned int size, size_t esize)
82 : : {
83 : 0 : size /= esize;
84 : :
85 [ # # ][ # # ]: 0 : size = roundup_pow_of_two(size);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
86 : :
87 : 0 : fifo->in = 0;
88 : 0 : fifo->out = 0;
89 : 0 : fifo->esize = esize;
90 : 0 : fifo->data = buffer;
91 : :
92 [ # # ]: 0 : if (size < 2) {
93 : 0 : fifo->mask = 0;
94 : 0 : return -EINVAL;
95 : : }
96 : 0 : fifo->mask = size - 1;
97 : :
98 : 0 : return 0;
99 : : }
100 : : EXPORT_SYMBOL(__kfifo_init);
101 : :
102 : 0 : static void kfifo_copy_in(struct __kfifo *fifo, const void *src,
103 : : unsigned int len, unsigned int off)
104 : : {
105 : 0 : unsigned int size = fifo->mask + 1;
106 : 0 : unsigned int esize = fifo->esize;
107 : : unsigned int l;
108 : :
109 : 0 : off &= fifo->mask;
110 [ # # ]: 0 : if (esize != 1) {
111 : 0 : off *= esize;
112 : 0 : size *= esize;
113 : 0 : len *= esize;
114 : : }
115 : 0 : l = min(len, size - off);
116 : :
117 : 0 : memcpy(fifo->data + off, src, l);
118 : 0 : memcpy(fifo->data, src + l, len - l);
119 : : /*
120 : : * make sure that the data in the fifo is up to date before
121 : : * incrementing the fifo->in index counter
122 : : */
123 : 0 : smp_wmb();
124 : 0 : }
125 : :
126 : 0 : unsigned int __kfifo_in(struct __kfifo *fifo,
127 : : const void *buf, unsigned int len)
128 : : {
129 : : unsigned int l;
130 : :
131 : : l = kfifo_unused(fifo);
132 [ # # ]: 0 : if (len > l)
133 : : len = l;
134 : :
135 : 0 : kfifo_copy_in(fifo, buf, len, fifo->in);
136 : 0 : fifo->in += len;
137 : 0 : return len;
138 : : }
139 : : EXPORT_SYMBOL(__kfifo_in);
140 : :
141 : 0 : static void kfifo_copy_out(struct __kfifo *fifo, void *dst,
142 : : unsigned int len, unsigned int off)
143 : : {
144 : 0 : unsigned int size = fifo->mask + 1;
145 : 0 : unsigned int esize = fifo->esize;
146 : : unsigned int l;
147 : :
148 : 0 : off &= fifo->mask;
149 [ # # ]: 0 : if (esize != 1) {
150 : 0 : off *= esize;
151 : 0 : size *= esize;
152 : 0 : len *= esize;
153 : : }
154 : 0 : l = min(len, size - off);
155 : :
156 : 0 : memcpy(dst, fifo->data + off, l);
157 : 0 : memcpy(dst + l, fifo->data, len - l);
158 : : /*
159 : : * make sure that the data is copied before
160 : : * incrementing the fifo->out index counter
161 : : */
162 : 0 : smp_wmb();
163 : 0 : }
164 : :
165 : 0 : unsigned int __kfifo_out_peek(struct __kfifo *fifo,
166 : : void *buf, unsigned int len)
167 : : {
168 : : unsigned int l;
169 : :
170 : 0 : l = fifo->in - fifo->out;
171 [ # # ][ # # ]: 0 : if (len > l)
172 : : len = l;
173 : :
174 : 0 : kfifo_copy_out(fifo, buf, len, fifo->out);
175 : 0 : return len;
176 : : }
177 : : EXPORT_SYMBOL(__kfifo_out_peek);
178 : :
179 : 0 : unsigned int __kfifo_out(struct __kfifo *fifo,
180 : : void *buf, unsigned int len)
181 : : {
182 : : len = __kfifo_out_peek(fifo, buf, len);
183 : 0 : fifo->out += len;
184 : 0 : return len;
185 : : }
186 : : EXPORT_SYMBOL(__kfifo_out);
187 : :
188 : 0 : static unsigned long kfifo_copy_from_user(struct __kfifo *fifo,
189 : : const void __user *from, unsigned int len, unsigned int off,
190 : : unsigned int *copied)
191 : : {
192 : 0 : unsigned int size = fifo->mask + 1;
193 : 0 : unsigned int esize = fifo->esize;
194 : : unsigned int l;
195 : : unsigned long ret;
196 : :
197 : 0 : off &= fifo->mask;
198 [ # # ]: 0 : if (esize != 1) {
199 : 0 : off *= esize;
200 : 0 : size *= esize;
201 : 0 : len *= esize;
202 : : }
203 : 0 : l = min(len, size - off);
204 : :
205 : 0 : ret = copy_from_user(fifo->data + off, from, l);
206 [ # # ]: 0 : if (unlikely(ret))
207 : 0 : ret = DIV_ROUND_UP(ret + len - l, esize);
208 : : else {
209 : 0 : ret = copy_from_user(fifo->data, from + l, len - l);
210 [ # # ]: 0 : if (unlikely(ret))
211 : 0 : ret = DIV_ROUND_UP(ret, esize);
212 : : }
213 : : /*
214 : : * make sure that the data in the fifo is up to date before
215 : : * incrementing the fifo->in index counter
216 : : */
217 : 0 : smp_wmb();
218 : 0 : *copied = len - ret * esize;
219 : : /* return the number of elements which are not copied */
220 : 0 : return ret;
221 : : }
222 : :
223 : 0 : int __kfifo_from_user(struct __kfifo *fifo, const void __user *from,
224 : : unsigned long len, unsigned int *copied)
225 : : {
226 : : unsigned int l;
227 : : unsigned long ret;
228 : 0 : unsigned int esize = fifo->esize;
229 : : int err;
230 : :
231 [ # # ]: 0 : if (esize != 1)
232 : 0 : len /= esize;
233 : :
234 : : l = kfifo_unused(fifo);
235 [ # # ]: 0 : if (len > l)
236 : : len = l;
237 : :
238 : 0 : ret = kfifo_copy_from_user(fifo, from, len, fifo->in, copied);
239 [ # # ]: 0 : if (unlikely(ret)) {
240 : 0 : len -= ret;
241 : : err = -EFAULT;
242 : : } else
243 : : err = 0;
244 : 0 : fifo->in += len;
245 : 0 : return err;
246 : : }
247 : : EXPORT_SYMBOL(__kfifo_from_user);
248 : :
249 : 0 : static unsigned long kfifo_copy_to_user(struct __kfifo *fifo, void __user *to,
250 : : unsigned int len, unsigned int off, unsigned int *copied)
251 : : {
252 : : unsigned int l;
253 : : unsigned long ret;
254 : 0 : unsigned int size = fifo->mask + 1;
255 : 0 : unsigned int esize = fifo->esize;
256 : :
257 : 0 : off &= fifo->mask;
258 [ # # ]: 0 : if (esize != 1) {
259 : 0 : off *= esize;
260 : 0 : size *= esize;
261 : 0 : len *= esize;
262 : : }
263 : 0 : l = min(len, size - off);
264 : :
265 : 0 : ret = copy_to_user(to, fifo->data + off, l);
266 [ # # ]: 0 : if (unlikely(ret))
267 : 0 : ret = DIV_ROUND_UP(ret + len - l, esize);
268 : : else {
269 : 0 : ret = copy_to_user(to + l, fifo->data, len - l);
270 [ # # ]: 0 : if (unlikely(ret))
271 : 0 : ret = DIV_ROUND_UP(ret, esize);
272 : : }
273 : : /*
274 : : * make sure that the data is copied before
275 : : * incrementing the fifo->out index counter
276 : : */
277 : 0 : smp_wmb();
278 : 0 : *copied = len - ret * esize;
279 : : /* return the number of elements which are not copied */
280 : 0 : return ret;
281 : : }
282 : :
283 : 0 : int __kfifo_to_user(struct __kfifo *fifo, void __user *to,
284 : : unsigned long len, unsigned int *copied)
285 : : {
286 : : unsigned int l;
287 : : unsigned long ret;
288 : 0 : unsigned int esize = fifo->esize;
289 : : int err;
290 : :
291 [ # # ]: 0 : if (esize != 1)
292 : 0 : len /= esize;
293 : :
294 : 0 : l = fifo->in - fifo->out;
295 [ # # ]: 0 : if (len > l)
296 : : len = l;
297 : 0 : ret = kfifo_copy_to_user(fifo, to, len, fifo->out, copied);
298 [ # # ]: 0 : if (unlikely(ret)) {
299 : 0 : len -= ret;
300 : : err = -EFAULT;
301 : : } else
302 : : err = 0;
303 : 0 : fifo->out += len;
304 : 0 : return err;
305 : : }
306 : : EXPORT_SYMBOL(__kfifo_to_user);
307 : :
308 : 0 : static int setup_sgl_buf(struct scatterlist *sgl, void *buf,
309 : : int nents, unsigned int len)
310 : : {
311 : : int n;
312 : : unsigned int l;
313 : : unsigned int off;
314 : : struct page *page;
315 : :
316 [ # # ]: 0 : if (!nents)
317 : : return 0;
318 : :
319 [ # # ]: 0 : if (!len)
320 : : return 0;
321 : :
322 : : n = 0;
323 : 0 : page = virt_to_page(buf);
324 : 0 : off = offset_in_page(buf);
325 : : l = 0;
326 : :
327 [ # # ]: 0 : while (len >= l + PAGE_SIZE - off) {
328 : : struct page *npage;
329 : :
330 : 0 : l += PAGE_SIZE;
331 : 0 : buf += PAGE_SIZE;
332 : 0 : npage = virt_to_page(buf);
333 [ # # ]: 0 : if (page_to_phys(page) != page_to_phys(npage) - l) {
334 : 0 : sg_set_page(sgl, page, l - off, off);
335 : 0 : sgl = sg_next(sgl);
336 [ # # ][ # # ]: 0 : if (++n == nents || sgl == NULL)
337 : : return n;
338 : : page = npage;
339 : 0 : len -= l - off;
340 : : l = off = 0;
341 : : }
342 : : }
343 : : sg_set_page(sgl, page, len, off);
344 : 0 : return n + 1;
345 : : }
346 : :
347 : 0 : static unsigned int setup_sgl(struct __kfifo *fifo, struct scatterlist *sgl,
348 : : int nents, unsigned int len, unsigned int off)
349 : : {
350 : 0 : unsigned int size = fifo->mask + 1;
351 : 0 : unsigned int esize = fifo->esize;
352 : : unsigned int l;
353 : : unsigned int n;
354 : :
355 : 0 : off &= fifo->mask;
356 [ # # ]: 0 : if (esize != 1) {
357 : 0 : off *= esize;
358 : 0 : size *= esize;
359 : 0 : len *= esize;
360 : : }
361 : 0 : l = min(len, size - off);
362 : :
363 : 0 : n = setup_sgl_buf(sgl, fifo->data + off, nents, l);
364 : 0 : n += setup_sgl_buf(sgl + n, fifo->data, nents - n, len - l);
365 : :
366 : 0 : return n;
367 : : }
368 : :
369 : 0 : unsigned int __kfifo_dma_in_prepare(struct __kfifo *fifo,
370 : : struct scatterlist *sgl, int nents, unsigned int len)
371 : : {
372 : : unsigned int l;
373 : :
374 : : l = kfifo_unused(fifo);
375 [ # # ]: 0 : if (len > l)
376 : : len = l;
377 : :
378 : 0 : return setup_sgl(fifo, sgl, nents, len, fifo->in);
379 : : }
380 : : EXPORT_SYMBOL(__kfifo_dma_in_prepare);
381 : :
382 : 0 : unsigned int __kfifo_dma_out_prepare(struct __kfifo *fifo,
383 : : struct scatterlist *sgl, int nents, unsigned int len)
384 : : {
385 : : unsigned int l;
386 : :
387 : 0 : l = fifo->in - fifo->out;
388 [ # # ]: 0 : if (len > l)
389 : : len = l;
390 : :
391 : 0 : return setup_sgl(fifo, sgl, nents, len, fifo->out);
392 : : }
393 : : EXPORT_SYMBOL(__kfifo_dma_out_prepare);
394 : :
395 : 0 : unsigned int __kfifo_max_r(unsigned int len, size_t recsize)
396 : : {
397 : 0 : unsigned int max = (1 << (recsize << 3)) - 1;
398 : :
399 [ # # ][ # # ]: 0 : if (len > max)
[ # # ][ # # ]
[ # # ]
400 : : return max;
401 : 0 : return len;
402 : : }
403 : : EXPORT_SYMBOL(__kfifo_max_r);
404 : :
405 : : #define __KFIFO_PEEK(data, out, mask) \
406 : : ((data)[(out) & (mask)])
407 : : /*
408 : : * __kfifo_peek_n internal helper function for determinate the length of
409 : : * the next record in the fifo
410 : : */
411 : : static unsigned int __kfifo_peek_n(struct __kfifo *fifo, size_t recsize)
412 : : {
413 : : unsigned int l;
414 : 0 : unsigned int mask = fifo->mask;
415 : 0 : unsigned char *data = fifo->data;
416 : :
417 : 0 : l = __KFIFO_PEEK(data, fifo->out, mask);
418 : :
419 [ # # ][ # # ]: 0 : if (--recsize)
[ # # ][ # # ]
[ # # ]
420 : 0 : l |= __KFIFO_PEEK(data, fifo->out + 1, mask) << 8;
421 : :
422 : : return l;
423 : : }
424 : :
425 : : #define __KFIFO_POKE(data, in, mask, val) \
426 : : ( \
427 : : (data)[(in) & (mask)] = (unsigned char)(val) \
428 : : )
429 : :
430 : : /*
431 : : * __kfifo_poke_n internal helper function for storeing the length of
432 : : * the record into the fifo
433 : : */
434 : : static void __kfifo_poke_n(struct __kfifo *fifo, unsigned int n, size_t recsize)
435 : : {
436 : 0 : unsigned int mask = fifo->mask;
437 : 0 : unsigned char *data = fifo->data;
438 : :
439 : 0 : __KFIFO_POKE(data, fifo->in, mask, n);
440 : :
441 [ # # ][ # # ]: 0 : if (recsize > 1)
[ # # ]
442 : 0 : __KFIFO_POKE(data, fifo->in + 1, mask, n >> 8);
443 : : }
444 : :
445 : 0 : unsigned int __kfifo_len_r(struct __kfifo *fifo, size_t recsize)
446 : : {
447 : 0 : return __kfifo_peek_n(fifo, recsize);
448 : : }
449 : : EXPORT_SYMBOL(__kfifo_len_r);
450 : :
451 : 0 : unsigned int __kfifo_in_r(struct __kfifo *fifo, const void *buf,
452 : : unsigned int len, size_t recsize)
453 : : {
454 [ # # ]: 0 : if (len + recsize > kfifo_unused(fifo))
455 : : return 0;
456 : :
457 : : __kfifo_poke_n(fifo, len, recsize);
458 : :
459 : 0 : kfifo_copy_in(fifo, buf, len, fifo->in + recsize);
460 : 0 : fifo->in += len + recsize;
461 : 0 : return len;
462 : : }
463 : : EXPORT_SYMBOL(__kfifo_in_r);
464 : :
465 : 0 : static unsigned int kfifo_out_copy_r(struct __kfifo *fifo,
466 : : void *buf, unsigned int len, size_t recsize, unsigned int *n)
467 : : {
468 : 0 : *n = __kfifo_peek_n(fifo, recsize);
469 : :
470 [ # # ]: 0 : if (len > *n)
471 : : len = *n;
472 : :
473 : 0 : kfifo_copy_out(fifo, buf, len, fifo->out + recsize);
474 : 0 : return len;
475 : : }
476 : :
477 : 0 : unsigned int __kfifo_out_peek_r(struct __kfifo *fifo, void *buf,
478 : : unsigned int len, size_t recsize)
479 : : {
480 : : unsigned int n;
481 : :
482 [ # # ]: 0 : if (fifo->in == fifo->out)
483 : : return 0;
484 : :
485 : 0 : return kfifo_out_copy_r(fifo, buf, len, recsize, &n);
486 : : }
487 : : EXPORT_SYMBOL(__kfifo_out_peek_r);
488 : :
489 : 0 : unsigned int __kfifo_out_r(struct __kfifo *fifo, void *buf,
490 : : unsigned int len, size_t recsize)
491 : : {
492 : : unsigned int n;
493 : :
494 [ # # ]: 0 : if (fifo->in == fifo->out)
495 : : return 0;
496 : :
497 : 0 : len = kfifo_out_copy_r(fifo, buf, len, recsize, &n);
498 : 0 : fifo->out += n + recsize;
499 : 0 : return len;
500 : : }
501 : : EXPORT_SYMBOL(__kfifo_out_r);
502 : :
503 : 0 : void __kfifo_skip_r(struct __kfifo *fifo, size_t recsize)
504 : : {
505 : : unsigned int n;
506 : :
507 : : n = __kfifo_peek_n(fifo, recsize);
508 : 0 : fifo->out += n + recsize;
509 : 0 : }
510 : : EXPORT_SYMBOL(__kfifo_skip_r);
511 : :
512 : 0 : int __kfifo_from_user_r(struct __kfifo *fifo, const void __user *from,
513 : : unsigned long len, unsigned int *copied, size_t recsize)
514 : : {
515 : : unsigned long ret;
516 : :
517 : : len = __kfifo_max_r(len, recsize);
518 : :
519 [ # # ]: 0 : if (len + recsize > kfifo_unused(fifo)) {
520 : 0 : *copied = 0;
521 : 0 : return 0;
522 : : }
523 : :
524 : : __kfifo_poke_n(fifo, len, recsize);
525 : :
526 : 0 : ret = kfifo_copy_from_user(fifo, from, len, fifo->in + recsize, copied);
527 [ # # ]: 0 : if (unlikely(ret)) {
528 : 0 : *copied = 0;
529 : 0 : return -EFAULT;
530 : : }
531 : 0 : fifo->in += len + recsize;
532 : 0 : return 0;
533 : : }
534 : : EXPORT_SYMBOL(__kfifo_from_user_r);
535 : :
536 : 0 : int __kfifo_to_user_r(struct __kfifo *fifo, void __user *to,
537 : : unsigned long len, unsigned int *copied, size_t recsize)
538 : : {
539 : : unsigned long ret;
540 : : unsigned int n;
541 : :
542 [ # # ]: 0 : if (fifo->in == fifo->out) {
543 : 0 : *copied = 0;
544 : 0 : return 0;
545 : : }
546 : :
547 : : n = __kfifo_peek_n(fifo, recsize);
548 [ # # ]: 0 : if (len > n)
549 : : len = n;
550 : :
551 : 0 : ret = kfifo_copy_to_user(fifo, to, len, fifo->out + recsize, copied);
552 [ # # ]: 0 : if (unlikely(ret)) {
553 : 0 : *copied = 0;
554 : 0 : return -EFAULT;
555 : : }
556 : 0 : fifo->out += n + recsize;
557 : 0 : return 0;
558 : : }
559 : : EXPORT_SYMBOL(__kfifo_to_user_r);
560 : :
561 : 0 : unsigned int __kfifo_dma_in_prepare_r(struct __kfifo *fifo,
562 : : struct scatterlist *sgl, int nents, unsigned int len, size_t recsize)
563 : : {
564 [ # # ]: 0 : if (!nents)
565 : 0 : BUG();
566 : :
567 : : len = __kfifo_max_r(len, recsize);
568 : :
569 [ # # ]: 0 : if (len + recsize > kfifo_unused(fifo))
570 : : return 0;
571 : :
572 : 0 : return setup_sgl(fifo, sgl, nents, len, fifo->in + recsize);
573 : : }
574 : : EXPORT_SYMBOL(__kfifo_dma_in_prepare_r);
575 : :
576 : 0 : void __kfifo_dma_in_finish_r(struct __kfifo *fifo,
577 : : unsigned int len, size_t recsize)
578 : : {
579 : : len = __kfifo_max_r(len, recsize);
580 : : __kfifo_poke_n(fifo, len, recsize);
581 : 0 : fifo->in += len + recsize;
582 : 0 : }
583 : : EXPORT_SYMBOL(__kfifo_dma_in_finish_r);
584 : :
585 : 0 : unsigned int __kfifo_dma_out_prepare_r(struct __kfifo *fifo,
586 : : struct scatterlist *sgl, int nents, unsigned int len, size_t recsize)
587 : : {
588 [ # # ]: 0 : if (!nents)
589 : 0 : BUG();
590 : :
591 : : len = __kfifo_max_r(len, recsize);
592 : :
593 [ # # ]: 0 : if (len + recsize > fifo->in - fifo->out)
594 : : return 0;
595 : :
596 : 0 : return setup_sgl(fifo, sgl, nents, len, fifo->out + recsize);
597 : : }
598 : : EXPORT_SYMBOL(__kfifo_dma_out_prepare_r);
599 : :
600 : 0 : void __kfifo_dma_out_finish_r(struct __kfifo *fifo, size_t recsize)
601 : : {
602 : : unsigned int len;
603 : :
604 : : len = __kfifo_peek_n(fifo, recsize);
605 : 0 : fifo->out += len + recsize;
606 : 0 : }
607 : : EXPORT_SYMBOL(__kfifo_dma_out_finish_r);
|