]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
lib/scatterlist: use page iterator in the mapping iterator
authorImre Deak <imre.deak@intel.com>
Wed, 20 Feb 2013 02:15:33 +0000 (13:15 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Wed, 20 Feb 2013 05:53:19 +0000 (16:53 +1100)
For better code reuse use the newly added page iterator to iterate through
the pages.  The offset, length within the page is still calculated by the
mapping iterator as well as the actual mapping.  Idea from Tejun Heo.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Cc: Maxim Levitsky <maximlevitsky@gmail.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
include/linux/scatterlist.h
lib/scatterlist.c

index 788a853aa7a7254cd8a8b4149242d1d212da4d91..a6cd6928dc3d1daebaf27049087f8274b28c7e22 100644 (file)
@@ -295,9 +295,9 @@ struct sg_mapping_iter {
        size_t                  consumed;       /* number of consumed bytes */
 
        /* these are internal states, keep away */
-       struct scatterlist      *__sg;          /* current entry */
-       unsigned int            __nents;        /* nr of remaining entries */
-       unsigned int            __offset;       /* offset within sg */
+       unsigned int            __offset;       /* offset within page */
+       struct sg_page_iter     __piter;        /* page iterator */
+       unsigned int            __remaining;    /* remaining bytes on page */
        unsigned int            __flags;
 };
 
index a1d15647d7dbf29944b1de36cd8c8049893aaa8a..4e4974a80b1a87dd20004fd4f621596ddc7d5b51 100644 (file)
@@ -449,9 +449,7 @@ void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl,
 {
        memset(miter, 0, sizeof(struct sg_mapping_iter));
 
-       miter->__sg = sgl;
-       miter->__nents = nents;
-       miter->__offset = 0;
+       __sg_page_iter_start(&miter->__piter, sgl, nents, 0);
        WARN_ON(!(flags & (SG_MITER_TO_SG | SG_MITER_FROM_SG)));
        miter->__flags = flags;
 }
@@ -476,36 +474,33 @@ EXPORT_SYMBOL(sg_miter_start);
  */
 bool sg_miter_next(struct sg_mapping_iter *miter)
 {
-       unsigned int off, len;
-
-       /* check for end and drop resources from the last iteration */
-       if (!miter->__nents)
-               return false;
-
        sg_miter_stop(miter);
 
-       /* get to the next sg if necessary.  __offset is adjusted by stop */
-       while (miter->__offset == miter->__sg->length) {
-               if (--miter->__nents) {
-                       miter->__sg = sg_next(miter->__sg);
-                       miter->__offset = 0;
-               } else
+       /*
+        * Get to the next page if necessary.
+        * __remaining, __offset is adjusted by sg_miter_stop
+        */
+       if (!miter->__remaining) {
+               struct scatterlist *sg;
+               unsigned long pgoffset;
+
+               if (!__sg_page_iter_next(&miter->__piter))
                        return false;
-       }
 
-       /* map the next page */
-       off = miter->__sg->offset + miter->__offset;
-       len = miter->__sg->length - miter->__offset;
+               sg = miter->__piter.sg;
+               pgoffset = miter->__piter.sg_pgoffset;
 
-       miter->page = nth_page(sg_page(miter->__sg), off >> PAGE_SHIFT);
-       off &= ~PAGE_MASK;
-       miter->length = min_t(unsigned int, len, PAGE_SIZE - off);
-       miter->consumed = miter->length;
+               miter->__offset = pgoffset ? 0 : sg->offset;
+               miter->__remaining = sg->offset + sg->length -
+                               (pgoffset << PAGE_SHIFT) - miter->__offset;
+       }
+       miter->page = miter->__piter.page;
+       miter->consumed = miter->length = miter->__remaining;
 
        if (miter->__flags & SG_MITER_ATOMIC)
-               miter->addr = kmap_atomic(miter->page) + off;
+               miter->addr = kmap_atomic(miter->page) + miter->__offset;
        else
-               miter->addr = kmap(miter->page) + off;
+               miter->addr = kmap(miter->page) + miter->__offset;
 
        return true;
 }
@@ -532,6 +527,7 @@ void sg_miter_stop(struct sg_mapping_iter *miter)
        /* drop resources from the last iteration */
        if (miter->addr) {
                miter->__offset += miter->consumed;
+               miter->__remaining -= miter->consumed;
 
                if (miter->__flags & SG_MITER_TO_SG)
                        flush_kernel_dcache_page(miter->page);