diff options
| author | Rebecca Schultz Zavin <rebecca@android.com> | 2012-10-23 10:47:04 -0700 |
|---|---|---|
| committer | Arve Hjønnevåg <arve@android.com> | 2013-07-01 14:16:12 -0700 |
| commit | e2486d0bcf39fcfeddb75009fb225cbfe36aa938 (patch) | |
| tree | 96a468aab9322d04420f3d1ddfefe8712372f806 /drivers/gpu | |
| parent | a4194824b16da15d76d5bd94089ec1124ef2369c (diff) | |
| download | olio-linux-3.10-e2486d0bcf39fcfeddb75009fb225cbfe36aa938.tar.xz olio-linux-3.10-e2486d0bcf39fcfeddb75009fb225cbfe36aa938.zip | |
gpu: ion: Fix bug in ion_system_heap map_user
When the requested mmap length was not an integer number of
chunks or the buffer, or if an offset was provided, a bug
would cause extra or incorrect pages of the buffer to be mapped.
Change-Id: I2766763d86048f026eeef0e0388b7de0e25c2093
Signed-off-by: Rebecca Schultz Zavin <rebecca@android.com>
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/ion/ion_system_heap.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c index 26e6bbcda70..dfa9543ab79 100644 --- a/drivers/gpu/ion/ion_system_heap.c +++ b/drivers/gpu/ion/ion_system_heap.c @@ -292,18 +292,27 @@ int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, { struct sg_table *table = buffer->priv_virt; unsigned long addr = vma->vm_start; - unsigned long offset = vma->vm_pgoff; + unsigned long offset = vma->vm_pgoff * PAGE_SIZE; struct scatterlist *sg; int i; for_each_sg(table->sgl, sg, table->nents, i) { - if (offset) { - offset--; + struct page *page = sg_page(sg); + unsigned long remainder = vma->vm_end - addr; + unsigned long len = sg_dma_len(sg); + + if (offset >= sg_dma_len(sg)) { + offset -= sg_dma_len(sg); continue; + } else if (offset) { + page += offset / PAGE_SIZE; + len = sg_dma_len(sg) - offset; + offset = 0; } - remap_pfn_range(vma, addr, page_to_pfn(sg_page(sg)), - sg_dma_len(sg), vma->vm_page_prot); - addr += sg_dma_len(sg); + len = min(len, remainder); + remap_pfn_range(vma, addr, page_to_pfn(page), len, + vma->vm_page_prot); + addr += len; if (addr >= vma->vm_end) return 0; } |