diff options
| author | Rebecca Schultz Zavin <rebecca@android.com> | 2012-11-15 10:43:46 -0800 |
|---|---|---|
| committer | Arve Hjønnevåg <arve@android.com> | 2013-07-01 14:16:16 -0700 |
| commit | ba660956c1f585a590c4de32d5a969e7762ce51c (patch) | |
| tree | b3e557949320b82e65de75b8b0beee6a734cf485 /drivers/gpu/ion/ion_heap.c | |
| parent | 98bdf10447930d3edbf6ed0f8678368fca9c8034 (diff) | |
| download | olio-linux-3.10-ba660956c1f585a590c4de32d5a969e7762ce51c.tar.xz olio-linux-3.10-ba660956c1f585a590c4de32d5a969e7762ce51c.zip | |
gpu: ion: Refactor common mapping functions out of system heap
The system heap contained several general purpose functions to map
buffers to the kernel and userspace. This patch refactors those
into ion_heap.c so they can be used by other heaps.
Change-Id: If64591798bdc2c248bf9064ace2c927909d7adb8
Signed-off-by: Rebecca Schultz Zavin <rebecca@android.com>
Diffstat (limited to 'drivers/gpu/ion/ion_heap.c')
| -rw-r--r-- | drivers/gpu/ion/ion_heap.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c index 8ce3c1907ba..b000eb39294 100644 --- a/drivers/gpu/ion/ion_heap.c +++ b/drivers/gpu/ion/ion_heap.c @@ -16,8 +16,83 @@ #include <linux/err.h> #include <linux/ion.h> +#include <linux/mm.h> +#include <linux/scatterlist.h> +#include <linux/vmalloc.h> #include "ion_priv.h" +void *ion_heap_map_kernel(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + struct scatterlist *sg; + int i, j; + void *vaddr; + pgprot_t pgprot; + struct sg_table *table = buffer->sg_table; + int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE; + struct page **pages = vmalloc(sizeof(struct page *) * npages); + struct page **tmp = pages; + + if (!pages) + return 0; + + if (buffer->flags & ION_FLAG_CACHED) + pgprot = PAGE_KERNEL; + else + pgprot = pgprot_writecombine(PAGE_KERNEL); + + for_each_sg(table->sgl, sg, table->nents, i) { + int npages_this_entry = PAGE_ALIGN(sg_dma_len(sg)) / PAGE_SIZE; + struct page *page = sg_page(sg); + BUG_ON(i >= npages); + for (j = 0; j < npages_this_entry; j++) { + *(tmp++) = page++; + } + } + vaddr = vmap(pages, npages, VM_MAP, pgprot); + vfree(pages); + + return vaddr; +} + +void ion_heap_unmap_kernel(struct ion_heap *heap, + struct ion_buffer *buffer) +{ + vunmap(buffer->vaddr); +} + +int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, + struct vm_area_struct *vma) +{ + struct sg_table *table = buffer->sg_table; + unsigned long addr = vma->vm_start; + unsigned long offset = vma->vm_pgoff * PAGE_SIZE; + struct scatterlist *sg; + int i; + + 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_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; + } + 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; + } + return 0; +} + struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) { struct ion_heap *heap = NULL; |