2 * drivers/gpu/ion/ion_system_heap.c
4 * Copyright (C) 2011 Google, Inc.
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <linux/err.h>
18 #include <linux/ion.h>
20 #include <linux/scatterlist.h>
21 #include <linux/slab.h>
22 #include <linux/vmalloc.h>
25 static int ion_system_heap_allocate(struct ion_heap *heap,
26 struct ion_buffer *buffer,
27 unsigned long size, unsigned long align,
30 buffer->priv_virt = vmalloc_user(size);
31 if (!buffer->priv_virt)
36 void ion_system_heap_free(struct ion_buffer *buffer)
38 vfree(buffer->priv_virt);
41 struct scatterlist *ion_system_heap_map_dma(struct ion_heap *heap,
42 struct ion_buffer *buffer)
44 struct scatterlist *sglist;
47 int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE;
48 void *vaddr = buffer->priv_virt;
50 sglist = vmalloc(npages * sizeof(struct scatterlist));
52 return ERR_PTR(-ENOMEM);
53 memset(sglist, 0, npages * sizeof(struct scatterlist));
54 sg_init_table(sglist, npages);
55 for (i = 0; i < npages; i++) {
56 page = vmalloc_to_page(vaddr);
59 sg_set_page(&sglist[i], page, PAGE_SIZE, 0);
62 /* XXX do cache maintenance for dma? */
69 void ion_system_heap_unmap_dma(struct ion_heap *heap,
70 struct ion_buffer *buffer)
72 /* XXX undo cache maintenance for dma? */
74 vfree(buffer->sglist);
77 void *ion_system_heap_map_kernel(struct ion_heap *heap,
78 struct ion_buffer *buffer)
80 return buffer->priv_virt;
83 void ion_system_heap_unmap_kernel(struct ion_heap *heap,
84 struct ion_buffer *buffer)
88 int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
89 struct vm_area_struct *vma)
91 return remap_vmalloc_range(vma, buffer->priv_virt, vma->vm_pgoff);
94 static struct ion_heap_ops vmalloc_ops = {
95 .allocate = ion_system_heap_allocate,
96 .free = ion_system_heap_free,
97 .map_dma = ion_system_heap_map_dma,
98 .unmap_dma = ion_system_heap_unmap_dma,
99 .map_kernel = ion_system_heap_map_kernel,
100 .unmap_kernel = ion_system_heap_unmap_kernel,
101 .map_user = ion_system_heap_map_user,
104 struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused)
106 struct ion_heap *heap;
108 heap = kzalloc(sizeof(struct ion_heap), GFP_KERNEL);
110 return ERR_PTR(-ENOMEM);
111 heap->ops = &vmalloc_ops;
112 heap->type = ION_HEAP_TYPE_SYSTEM;
116 void ion_system_heap_destroy(struct ion_heap *heap)
121 static int ion_system_contig_heap_allocate(struct ion_heap *heap,
122 struct ion_buffer *buffer,
127 buffer->priv_virt = kzalloc(len, GFP_KERNEL);
128 if (!buffer->priv_virt)
133 void ion_system_contig_heap_free(struct ion_buffer *buffer)
135 kfree(buffer->priv_virt);
138 static int ion_system_contig_heap_phys(struct ion_heap *heap,
139 struct ion_buffer *buffer,
140 ion_phys_addr_t *addr, size_t *len)
142 *addr = virt_to_phys(buffer->priv_virt);
147 struct scatterlist *ion_system_contig_heap_map_dma(struct ion_heap *heap,
148 struct ion_buffer *buffer)
150 struct scatterlist *sglist;
152 sglist = vmalloc(sizeof(struct scatterlist));
154 return ERR_PTR(-ENOMEM);
155 sg_init_table(sglist, 1);
156 sg_set_page(sglist, virt_to_page(buffer->priv_virt), buffer->size, 0);
160 int ion_system_contig_heap_map_user(struct ion_heap *heap,
161 struct ion_buffer *buffer,
162 struct vm_area_struct *vma)
164 unsigned long pfn = __phys_to_pfn(virt_to_phys(buffer->priv_virt));
165 return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff,
166 vma->vm_end - vma->vm_start,
171 static struct ion_heap_ops kmalloc_ops = {
172 .allocate = ion_system_contig_heap_allocate,
173 .free = ion_system_contig_heap_free,
174 .phys = ion_system_contig_heap_phys,
175 .map_dma = ion_system_contig_heap_map_dma,
176 .unmap_dma = ion_system_heap_unmap_dma,
177 .map_kernel = ion_system_heap_map_kernel,
178 .unmap_kernel = ion_system_heap_unmap_kernel,
179 .map_user = ion_system_contig_heap_map_user,
182 struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *unused)
184 struct ion_heap *heap;
186 heap = kzalloc(sizeof(struct ion_heap), GFP_KERNEL);
188 return ERR_PTR(-ENOMEM);
189 heap->ops = &kmalloc_ops;
190 heap->type = ION_HEAP_TYPE_SYSTEM_CONTIG;
194 void ion_system_contig_heap_destroy(struct ion_heap *heap)