diff options
Diffstat (limited to 'lib/scatterlist.c')
-rw-r--r-- | lib/scatterlist.c | 48 |
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 | */ |
477 | bool sg_miter_next(struct sg_mapping_iter *miter) | 475 | bool 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); |