Commit 4225fc85 authored by Imre Deak's avatar Imre Deak Committed by Linus Torvalds

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: default avatarImre 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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent a321e91b
...@@ -1453,7 +1453,7 @@ static void dw_mci_read_data_pio(struct dw_mci *host) ...@@ -1453,7 +1453,7 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
if (!sg_miter_next(sg_miter)) if (!sg_miter_next(sg_miter))
goto done; goto done;
host->sg = sg_miter->__sg; host->sg = sg_miter->piter.sg;
buf = sg_miter->addr; buf = sg_miter->addr;
remain = sg_miter->length; remain = sg_miter->length;
offset = 0; offset = 0;
...@@ -1508,7 +1508,7 @@ static void dw_mci_write_data_pio(struct dw_mci *host) ...@@ -1508,7 +1508,7 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
if (!sg_miter_next(sg_miter)) if (!sg_miter_next(sg_miter))
goto done; goto done;
host->sg = sg_miter->__sg; host->sg = sg_miter->piter.sg;
buf = sg_miter->addr; buf = sg_miter->addr;
remain = sg_miter->length; remain = sg_miter->length;
offset = 0; offset = 0;
......
...@@ -293,11 +293,11 @@ struct sg_mapping_iter { ...@@ -293,11 +293,11 @@ struct sg_mapping_iter {
void *addr; /* pointer to the mapped area */ void *addr; /* pointer to the mapped area */
size_t length; /* length of the mapped area */ size_t length; /* length of the mapped area */
size_t consumed; /* number of consumed bytes */ size_t consumed; /* number of consumed bytes */
struct sg_page_iter piter; /* page iterator */
/* these are internal states, keep away */ /* these are internal states, keep away */
struct scatterlist *__sg; /* current entry */ unsigned int __offset; /* offset within page */
unsigned int __nents; /* nr of remaining entries */ unsigned int __remaining; /* remaining bytes on page */
unsigned int __offset; /* offset within sg */
unsigned int __flags; unsigned int __flags;
}; };
......
...@@ -449,9 +449,7 @@ void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl, ...@@ -449,9 +449,7 @@ void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl,
{ {
memset(miter, 0, sizeof(struct sg_mapping_iter)); memset(miter, 0, sizeof(struct sg_mapping_iter));
miter->__sg = sgl; __sg_page_iter_start(&miter->piter, sgl, nents, 0);
miter->__nents = nents;
miter->__offset = 0;
WARN_ON(!(flags & (SG_MITER_TO_SG | SG_MITER_FROM_SG))); WARN_ON(!(flags & (SG_MITER_TO_SG | SG_MITER_FROM_SG)));
miter->__flags = flags; miter->__flags = flags;
} }
...@@ -476,36 +474,35 @@ EXPORT_SYMBOL(sg_miter_start); ...@@ -476,36 +474,35 @@ EXPORT_SYMBOL(sg_miter_start);
*/ */
bool sg_miter_next(struct sg_mapping_iter *miter) 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); sg_miter_stop(miter);
/* get to the next sg if necessary. __offset is adjusted by stop */ /*
while (miter->__offset == miter->__sg->length) { * Get to the next page if necessary.
if (--miter->__nents) { * __remaining, __offset is adjusted by sg_miter_stop
miter->__sg = sg_next(miter->__sg); */
miter->__offset = 0; if (!miter->__remaining) {
} else struct scatterlist *sg;
unsigned long pgoffset;
if (!__sg_page_iter_next(&miter->piter))
return false; return false;
}
/* map the next page */ sg = miter->piter.sg;
off = miter->__sg->offset + miter->__offset; pgoffset = miter->piter.sg_pgoffset;
len = miter->__sg->length - miter->__offset;
miter->page = nth_page(sg_page(miter->__sg), off >> PAGE_SHIFT); miter->__offset = pgoffset ? 0 : sg->offset;
off &= ~PAGE_MASK; miter->__remaining = sg->offset + sg->length -
miter->length = min_t(unsigned int, len, PAGE_SIZE - off); (pgoffset << PAGE_SHIFT) - miter->__offset;
miter->consumed = miter->length; miter->__remaining = min_t(unsigned long, miter->__remaining,
PAGE_SIZE - miter->__offset);
}
miter->page = miter->piter.page;
miter->consumed = miter->length = miter->__remaining;
if (miter->__flags & SG_MITER_ATOMIC) if (miter->__flags & SG_MITER_ATOMIC)
miter->addr = kmap_atomic(miter->page) + off; miter->addr = kmap_atomic(miter->page) + miter->__offset;
else else
miter->addr = kmap(miter->page) + off; miter->addr = kmap(miter->page) + miter->__offset;
return true; return true;
} }
...@@ -532,6 +529,7 @@ void sg_miter_stop(struct sg_mapping_iter *miter) ...@@ -532,6 +529,7 @@ void sg_miter_stop(struct sg_mapping_iter *miter)
/* drop resources from the last iteration */ /* drop resources from the last iteration */
if (miter->addr) { if (miter->addr) {
miter->__offset += miter->consumed; miter->__offset += miter->consumed;
miter->__remaining -= miter->consumed;
if (miter->__flags & SG_MITER_TO_SG) if (miter->__flags & SG_MITER_TO_SG)
flush_kernel_dcache_page(miter->page); flush_kernel_dcache_page(miter->page);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment