aboutsummaryrefslogtreecommitdiffstats
path: root/lib/scatterlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/scatterlist.c')
-rw-r--r--lib/scatterlist.c48
1 files changed, 23 insertions, 25 deletions
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);