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>
This commit is contained in:

committed by
Linus Torvalds

parent
a321e91b6d
commit
4225fc8555
@@ -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,35 @@ 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;
|
||||
|
||||
sg = miter->piter.sg;
|
||||
pgoffset = miter->piter.sg_pgoffset;
|
||||
|
||||
miter->__offset = pgoffset ? 0 : sg->offset;
|
||||
miter->__remaining = sg->offset + sg->length -
|
||||
(pgoffset << PAGE_SHIFT) - miter->__offset;
|
||||
miter->__remaining = min_t(unsigned long, miter->__remaining,
|
||||
PAGE_SIZE - miter->__offset);
|
||||
}
|
||||
|
||||
/* map the next page */
|
||||
off = miter->__sg->offset + miter->__offset;
|
||||
len = miter->__sg->length - miter->__offset;
|
||||
|
||||
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->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 +529,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);
|
||||
|
Reference in New Issue
Block a user