diff options
author | Akinobu Mita <akinobu.mita@gmail.com> | 2013-07-08 19:01:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-09 13:33:30 -0400 |
commit | df642cea25c90dc7d5dcd9d3b480b6b59de7d787 (patch) | |
tree | 947e40ff7e12907461082d88ef390084bb90f915 /lib | |
parent | 1105200480b4faeb673d1b23658650b003302c06 (diff) |
lib/scatterlist: introduce sg_pcopy_from_buffer() and sg_pcopy_to_buffer()
The only difference between sg_pcopy_{from,to}_buffer() and
sg_copy_{from,to}_buffer() is an additional argument that specifies the
number of bytes to skip the SG list before copying.
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: "James E.J. Bottomley" <JBottomley@parallels.com>
Cc: Douglas Gilbert <dgilbert@interlog.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Horia Geanta <horia.geanta@freescale.com>
Cc: Imre Deak <imre.deak@intel.com>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/scatterlist.c | 88 |
1 files changed, 83 insertions, 5 deletions
diff --git a/lib/scatterlist.c b/lib/scatterlist.c index c35b929435f3..129a82f707df 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c | |||
@@ -476,6 +476,43 @@ static bool sg_miter_get_next_page(struct sg_mapping_iter *miter) | |||
476 | } | 476 | } |
477 | 477 | ||
478 | /** | 478 | /** |
479 | * sg_miter_skip - reposition mapping iterator | ||
480 | * @miter: sg mapping iter to be skipped | ||
481 | * @offset: number of bytes to plus the current location | ||
482 | * | ||
483 | * Description: | ||
484 | * Sets the offset of @miter to its current location plus @offset bytes. | ||
485 | * If mapping iterator @miter has been proceeded by sg_miter_next(), this | ||
486 | * stops @miter. | ||
487 | * | ||
488 | * Context: | ||
489 | * Don't care if @miter is stopped, or not proceeded yet. | ||
490 | * Otherwise, preemption disabled if the SG_MITER_ATOMIC is set. | ||
491 | * | ||
492 | * Returns: | ||
493 | * true if @miter contains the valid mapping. false if end of sg | ||
494 | * list is reached. | ||
495 | */ | ||
496 | static bool sg_miter_skip(struct sg_mapping_iter *miter, off_t offset) | ||
497 | { | ||
498 | sg_miter_stop(miter); | ||
499 | |||
500 | while (offset) { | ||
501 | off_t consumed; | ||
502 | |||
503 | if (!sg_miter_get_next_page(miter)) | ||
504 | return false; | ||
505 | |||
506 | consumed = min_t(off_t, offset, miter->__remaining); | ||
507 | miter->__offset += consumed; | ||
508 | miter->__remaining -= consumed; | ||
509 | offset -= consumed; | ||
510 | } | ||
511 | |||
512 | return true; | ||
513 | } | ||
514 | |||
515 | /** | ||
479 | * sg_miter_next - proceed mapping iterator to the next mapping | 516 | * sg_miter_next - proceed mapping iterator to the next mapping |
480 | * @miter: sg mapping iter to proceed | 517 | * @miter: sg mapping iter to proceed |
481 | * | 518 | * |
@@ -561,14 +598,16 @@ EXPORT_SYMBOL(sg_miter_stop); | |||
561 | * @nents: Number of SG entries | 598 | * @nents: Number of SG entries |
562 | * @buf: Where to copy from | 599 | * @buf: Where to copy from |
563 | * @buflen: The number of bytes to copy | 600 | * @buflen: The number of bytes to copy |
564 | * @to_buffer: transfer direction (non zero == from an sg list to a | 601 | * @skip: Number of bytes to skip before copying |
565 | * buffer, 0 == from a buffer to an sg list | 602 | * @to_buffer: transfer direction (true == from an sg list to a |
603 | * buffer, false == from a buffer to an sg list | ||
566 | * | 604 | * |
567 | * Returns the number of copied bytes. | 605 | * Returns the number of copied bytes. |
568 | * | 606 | * |
569 | **/ | 607 | **/ |
570 | static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, | 608 | static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, |
571 | void *buf, size_t buflen, int to_buffer) | 609 | void *buf, size_t buflen, off_t skip, |
610 | bool to_buffer) | ||
572 | { | 611 | { |
573 | unsigned int offset = 0; | 612 | unsigned int offset = 0; |
574 | struct sg_mapping_iter miter; | 613 | struct sg_mapping_iter miter; |
@@ -582,6 +621,9 @@ static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, | |||
582 | 621 | ||
583 | sg_miter_start(&miter, sgl, nents, sg_flags); | 622 | sg_miter_start(&miter, sgl, nents, sg_flags); |
584 | 623 | ||
624 | if (!sg_miter_skip(&miter, skip)) | ||
625 | return false; | ||
626 | |||
585 | local_irq_save(flags); | 627 | local_irq_save(flags); |
586 | 628 | ||
587 | while (sg_miter_next(&miter) && offset < buflen) { | 629 | while (sg_miter_next(&miter) && offset < buflen) { |
@@ -616,7 +658,7 @@ static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, | |||
616 | size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents, | 658 | size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents, |
617 | void *buf, size_t buflen) | 659 | void *buf, size_t buflen) |
618 | { | 660 | { |
619 | return sg_copy_buffer(sgl, nents, buf, buflen, 0); | 661 | return sg_copy_buffer(sgl, nents, buf, buflen, 0, false); |
620 | } | 662 | } |
621 | EXPORT_SYMBOL(sg_copy_from_buffer); | 663 | EXPORT_SYMBOL(sg_copy_from_buffer); |
622 | 664 | ||
@@ -633,6 +675,42 @@ EXPORT_SYMBOL(sg_copy_from_buffer); | |||
633 | size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents, | 675 | size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents, |
634 | void *buf, size_t buflen) | 676 | void *buf, size_t buflen) |
635 | { | 677 | { |
636 | return sg_copy_buffer(sgl, nents, buf, buflen, 1); | 678 | return sg_copy_buffer(sgl, nents, buf, buflen, 0, true); |
637 | } | 679 | } |
638 | EXPORT_SYMBOL(sg_copy_to_buffer); | 680 | EXPORT_SYMBOL(sg_copy_to_buffer); |
681 | |||
682 | /** | ||
683 | * sg_pcopy_from_buffer - Copy from a linear buffer to an SG list | ||
684 | * @sgl: The SG list | ||
685 | * @nents: Number of SG entries | ||
686 | * @buf: Where to copy from | ||
687 | * @skip: Number of bytes to skip before copying | ||
688 | * @buflen: The number of bytes to copy | ||
689 | * | ||
690 | * Returns the number of copied bytes. | ||
691 | * | ||
692 | **/ | ||
693 | size_t sg_pcopy_from_buffer(struct scatterlist *sgl, unsigned int nents, | ||
694 | void *buf, size_t buflen, off_t skip) | ||
695 | { | ||
696 | return sg_copy_buffer(sgl, nents, buf, buflen, skip, false); | ||
697 | } | ||
698 | EXPORT_SYMBOL(sg_pcopy_from_buffer); | ||
699 | |||
700 | /** | ||
701 | * sg_pcopy_to_buffer - Copy from an SG list to a linear buffer | ||
702 | * @sgl: The SG list | ||
703 | * @nents: Number of SG entries | ||
704 | * @buf: Where to copy to | ||
705 | * @skip: Number of bytes to skip before copying | ||
706 | * @buflen: The number of bytes to copy | ||
707 | * | ||
708 | * Returns the number of copied bytes. | ||
709 | * | ||
710 | **/ | ||
711 | size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents, | ||
712 | void *buf, size_t buflen, off_t skip) | ||
713 | { | ||
714 | return sg_copy_buffer(sgl, nents, buf, buflen, skip, true); | ||
715 | } | ||
716 | EXPORT_SYMBOL(sg_pcopy_to_buffer); | ||