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. Signed-off-by: John Einar Reitan <john.reitan@xxxxxxxxxxxx> --- drivers/staging/android/ion/ion_heap.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index ca15a87..e83002dc 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++) @@ -79,7 +79,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; @@ -87,18 +86,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; } -- 2.7.3 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel