diff options
author | John Einar Reitan <john.reitan@arm.com> | 2016-01-15 09:20:37 +0100 |
---|---|---|
committer | John Einar Reitan <john.reitan@arm.com> | 2016-01-15 11:04:39 +0100 |
commit | 8dce9eca3b34eb5996b50b05141a86fb2cbdb2ab (patch) | |
tree | c6ed4c98e407b3302a3f9f3f6914d2c0141e5668 | |
parent | e26299773ba3f0c5f5c0a6757f4dd2a51b5728a7 (diff) |
ion: scatterlist offset not used for user/kernel mapping
ION's default user/kernel page mapping code don't honor the offset
option for scatterlists. It uses sg_page and expect the whole page to be
mapped, while the offset could dictate an offset within a large page.
sg_phys correctly accounts for the offset, so should be used instead.
Change-Id: If8bebb0b6c294e18bddaceacf771af4d6846085b
Signed-off-by: John Einar Reitan <john.reitan@arm.com>
-rw-r--r-- | drivers/staging/android/ion/ion_heap.c | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 750b76af0cf..01abaf9c67e 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -47,7 +47,7 @@ void *ion_heap_map_kernel(struct ion_heap *heap, for_each_sg(table->sgl, sg, table->nents, i) { int npages_this_entry = PAGE_ALIGN(sg->length) / PAGE_SIZE; - struct page *page = sg_page(sg); + struct page *page = pfn_to_page(PFN_DOWN(sg_phys(sg))); BUG_ON(i >= npages); for (j = 0; j < npages_this_entry; j++) *(tmp++) = page++; @@ -78,7 +78,6 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, int ret; for_each_sg(table->sgl, sg, table->nents, i) { - struct page *page = sg_page(sg); unsigned long remainder = vma->vm_end - addr; unsigned long len = sg->length; @@ -86,18 +85,18 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, offset -= sg->length; continue; } else if (offset) { - page += offset / PAGE_SIZE; len = sg->length - offset; - offset = 0; } len = min(len, remainder); - ret = remap_pfn_range(vma, addr, page_to_pfn(page), len, - vma->vm_page_prot); + ret = remap_pfn_range(vma, addr, PFN_DOWN(sg_phys(sg) + offset), + len, vma->vm_page_prot); if (ret) return ret; addr += len; if (addr >= vma->vm_end) return 0; + + offset = 0; } return 0; } |