aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2013-02-27 20:02:57 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-27 22:10:10 -0500
commit4225fc8555a992c7f91d174ef424384d6781e144 (patch)
tree46f73428afef93acc729fd36842e463b503bab58
parenta321e91b6d73ed011ffceed384c40d2785cf723b (diff)
lib/scatterlist: use page iterator in the mapping iterator
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> Cc: James Hogan <james.hogan@imgtec.com> Cc: Stephen Warren <swarren@wwwdotorg.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/mmc/host/dw_mmc.c4
-rw-r--r--include/linux/scatterlist.h6
-rw-r--r--lib/scatterlist.c48
3 files changed, 28 insertions, 30 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 60063ccb4c4b..98342213ed21 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1453,7 +1453,7 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
1453 if (!sg_miter_next(sg_miter)) 1453 if (!sg_miter_next(sg_miter))
1454 goto done; 1454 goto done;
1455 1455
1456 host->sg = sg_miter->__sg; 1456 host->sg = sg_miter->piter.sg;
1457 buf = sg_miter->addr; 1457 buf = sg_miter->addr;
1458 remain = sg_miter->length; 1458 remain = sg_miter->length;
1459 offset = 0; 1459 offset = 0;
@@ -1508,7 +1508,7 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
1508 if (!sg_miter_next(sg_miter)) 1508 if (!sg_miter_next(sg_miter))
1509 goto done; 1509 goto done;
1510 1510
1511 host->sg = sg_miter->__sg; 1511 host->sg = sg_miter->piter.sg;
1512 buf = sg_miter->addr; 1512 buf = sg_miter->addr;
1513 remain = sg_miter->length; 1513 remain = sg_miter->length;
1514 offset = 0; 1514 offset = 0;
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 788a853aa7a7..2d8bdaef9611 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -293,11 +293,11 @@ struct sg_mapping_iter {
293 void *addr; /* pointer to the mapped area */ 293 void *addr; /* pointer to the mapped area */
294 size_t length; /* length of the mapped area */ 294 size_t length; /* length of the mapped area */
295 size_t consumed; /* number of consumed bytes */ 295 size_t consumed; /* number of consumed bytes */
296 struct sg_page_iter piter; /* page iterator */
296 297
297 /* these are internal states, keep away */ 298 /* these are internal states, keep away */
298 struct scatterlist *__sg; /* current entry */ 299 unsigned int __offset; /* offset within page */
299 unsigned int __nents; /* nr of remaining entries */ 300 unsigned int __remaining; /* remaining bytes on page */
300 unsigned int __offset; /* offset within sg */
301 unsigned int __flags; 301 unsigned int __flags;
302}; 302};
303 303
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index a1d15647d7db..b83c144d731f 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -449,9 +449,7 @@ void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl,
449{ 449{
450 memset(miter, 0, sizeof(struct sg_mapping_iter)); 450 memset(miter, 0, sizeof(struct sg_mapping_iter));
451 451
452 miter->__sg = sgl; 452 __sg_page_iter_start(&miter->piter, sgl, nents, 0);
453 miter->__nents = nents;
454 miter->__offset = 0;
455 WARN_ON(!(flags & (SG_MITER_TO_SG | SG_MITER_FROM_SG))); 453 WARN_ON(!(flags & (SG_MITER_TO_SG | SG_MITER_FROM_SG)));
456 miter->__flags = flags; 454 miter->__flags = flags;
457} 455}
@@ -476,36 +474,35 @@ EXPORT_SYMBOL(sg_miter_start);
476 */ 474 */
477bool sg_miter_next(struct sg_mapping_iter *miter) 475bool sg_miter_next(struct sg_mapping_iter *miter)
478{ 476{
479 unsigned int off, len;
480
481 /* check for end and drop resources from the last iteration */
482 if (!miter->__nents)
483 return false;
484
485 sg_miter_stop(miter); 477 sg_miter_stop(miter);
486 478
487 /* get to the next sg if necessary. __offset is adjusted by stop */ 479 /*
488 while (miter->__offset == miter->__sg->length) { 480 * Get to the next page if necessary.
489 if (--miter->__nents) { 481 * __remaining, __offset is adjusted by sg_miter_stop
490 miter->__sg = sg_next(miter->__sg); 482 */
491 miter->__offset = 0; 483 if (!miter->__remaining) {
492 } else 484 struct scatterlist *sg;
485 unsigned long pgoffset;
486
487 if (!__sg_page_iter_next(&miter->piter))
493 return false; 488 return false;
494 }
495 489
496 /* map the next page */ 490 sg = miter->piter.sg;
497 off = miter->__sg->offset + miter->__offset; 491 pgoffset = miter->piter.sg_pgoffset;
498 len = miter->__sg->length - miter->__offset;
499 492
500 miter->page = nth_page(sg_page(miter->__sg), off >> PAGE_SHIFT); 493 miter->__offset = pgoffset ? 0 : sg->offset;
501 off &= ~PAGE_MASK; 494 miter->__remaining = sg->offset + sg->length -
502 miter->length = min_t(unsigned int, len, PAGE_SIZE - off); 495 (pgoffset << PAGE_SHIFT) - miter->__offset;
503 miter->consumed = miter->length; 496 miter->__remaining = min_t(unsigned long, miter->__remaining,
497 PAGE_SIZE - miter->__offset);
498 }
499 miter->page = miter->piter.page;
500 miter->consumed = miter->length = miter->__remaining;
504 501
505 if (miter->__flags & SG_MITER_ATOMIC) 502 if (miter->__flags & SG_MITER_ATOMIC)
506 miter->addr = kmap_atomic(miter->page) + off; 503 miter->addr = kmap_atomic(miter->page) + miter->__offset;
507 else 504 else
508 miter->addr = kmap(miter->page) + off; 505 miter->addr = kmap(miter->page) + miter->__offset;
509 506
510 return true; 507 return true;
511} 508}
@@ -532,6 +529,7 @@ void sg_miter_stop(struct sg_mapping_iter *miter)
532 /* drop resources from the last iteration */ 529 /* drop resources from the last iteration */
533 if (miter->addr) { 530 if (miter->addr) {
534 miter->__offset += miter->consumed; 531 miter->__offset += miter->consumed;
532 miter->__remaining -= miter->consumed;
535 533
536 if (miter->__flags & SG_MITER_TO_SG) 534 if (miter->__flags & SG_MITER_TO_SG)
537 flush_kernel_dcache_page(miter->page); 535 flush_kernel_dcache_page(miter->page);