2 * drivers/gpu/ion/ion_cma_heap.c
4 * Copyright (C) Linaro 2012
5 * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
18 #include <linux/device.h>
19 #include <linux/slab.h>
20 #include <linux/errno.h>
21 #include <linux/err.h>
22 #include <linux/dma-mapping.h>
23 #include <linux/rockchip_ion.h>
24 #include <linux/rockchip-iovmm.h>
29 #define ION_CMA_ALLOCATE_FAILED -1
36 #define to_cma_heap(x) container_of(x, struct ion_cma_heap, heap)
38 struct ion_cma_buffer_info {
41 struct sg_table *table;
45 * Create scatter-list for the already allocated DMA buffer.
46 * This function could be replaced by dma_common_get_sgtable
47 * as soon as it will avalaible.
49 static int ion_cma_get_sgtable(struct device *dev, struct sg_table *sgt,
50 dma_addr_t handle, size_t size)
52 struct page *page = phys_to_page(handle);
55 ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
59 sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0);
63 /* ION CMA heap operations functions */
64 static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer,
65 unsigned long len, unsigned long align,
68 struct ion_cma_heap *cma_heap = to_cma_heap(heap);
69 struct device *dev = cma_heap->dev;
70 struct ion_cma_buffer_info *info;
71 DEFINE_DMA_ATTRS(attrs);
73 #ifdef CONFIG_ION_CMA_HIGHMEM
74 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
76 dev_dbg(dev, "Request buffer allocation len %ld\n", len);
78 if (buffer->flags & ION_FLAG_CACHED)
81 if (align > PAGE_SIZE)
84 info = kzalloc(sizeof(struct ion_cma_buffer_info), GFP_KERNEL);
86 dev_err(dev, "Can't allocate buffer info\n");
87 return ION_CMA_ALLOCATE_FAILED;
90 info->cpu_addr = dma_alloc_attrs(dev, len, &(info->handle),
91 GFP_HIGHUSER | __GFP_ZERO, &attrs);
93 if (!info->cpu_addr) {
94 dev_err(dev, "Fail to allocate(%lx) buffer\n", len);
98 info->table = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
100 dev_err(dev, "Fail to allocate sg table\n");
104 if (ion_cma_get_sgtable(dev, info->table, info->handle, len))
106 /* keep this for memory release */
107 buffer->priv_virt = info;
108 dev_dbg(dev, "Allocate buffer %p\n", buffer);
114 dma_free_attrs(dev, len, info->cpu_addr, info->handle, &attrs);
117 return ION_CMA_ALLOCATE_FAILED;
120 static void ion_cma_free(struct ion_buffer *buffer)
122 struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap);
123 struct device *dev = cma_heap->dev;
124 struct ion_cma_buffer_info *info = buffer->priv_virt;
125 DEFINE_DMA_ATTRS(attrs);
127 #ifdef CONFIG_ION_CMA_HIGHMEM
128 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
130 dev_dbg(dev, "Release buffer %p\n", buffer);
132 dma_free_attrs(dev, buffer->size, info->cpu_addr, info->handle, &attrs);
133 /* release sg table */
134 sg_free_table(info->table);
139 /* return physical address in addr */
140 static int ion_cma_phys(struct ion_heap *heap, struct ion_buffer *buffer,
141 ion_phys_addr_t *addr, size_t *len)
143 struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap);
144 struct device *dev = cma_heap->dev;
145 struct ion_cma_buffer_info *info = buffer->priv_virt;
147 dev_dbg(dev, "Return buffer %p physical address 0x%pa\n", buffer,
150 *addr = info->handle;
156 static struct sg_table *ion_cma_heap_map_dma(struct ion_heap *heap,
157 struct ion_buffer *buffer)
159 struct ion_cma_buffer_info *info = buffer->priv_virt;
164 static void ion_cma_heap_unmap_dma(struct ion_heap *heap,
165 struct ion_buffer *buffer)
170 static int ion_cma_mmap(struct ion_heap *mapper, struct ion_buffer *buffer,
171 struct vm_area_struct *vma)
173 struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap);
174 struct device *dev = cma_heap->dev;
175 struct ion_cma_buffer_info *info = buffer->priv_virt;
177 return dma_mmap_coherent(dev, vma, info->cpu_addr, info->handle,
181 #ifndef CONFIG_ION_CMA_HIGHMEM
182 static void *ion_cma_map_kernel(struct ion_heap *heap,
183 struct ion_buffer *buffer)
185 struct ion_cma_buffer_info *info = buffer->priv_virt;
186 /* kernel memory mapping has been done at allocation time */
187 return info->cpu_addr;
190 static void ion_cma_unmap_kernel(struct ion_heap *heap,
191 struct ion_buffer *buffer)
196 #ifdef CONFIG_ROCKCHIP_IOMMU
197 // get device's vaddr
198 static int ion_cma_map_iommu(struct ion_buffer *buffer,
199 struct device *iommu_dev,
200 struct ion_iommu_map *data,
201 unsigned long iova_length,
205 struct ion_cma_buffer_info *info = buffer->priv_virt;
207 data->iova_addr = rockchip_iovmm_map(iommu_dev, info->table->sgl, 0, iova_length);
208 pr_debug("%s: map %x -> %lx\n", __func__, info->table->sgl->dma_address,
210 if (IS_ERR_VALUE(data->iova_addr)) {
211 pr_err("%s: rockchip_iovmm_map() failed: %lx\n", __func__, data->iova_addr);
212 ret = data->iova_addr;
216 data->mapped_size = iova_length;
222 void ion_cma_unmap_iommu(struct device *iommu_dev, struct ion_iommu_map *data)
224 pr_debug("%s: unmap %x@%lx\n", __func__, data->mapped_size, data->iova_addr);
225 rockchip_iovmm_unmap(iommu_dev, data->iova_addr);
231 static struct ion_heap_ops ion_cma_ops = {
232 .allocate = ion_cma_allocate,
233 .free = ion_cma_free,
234 .map_dma = ion_cma_heap_map_dma,
235 .unmap_dma = ion_cma_heap_unmap_dma,
236 .phys = ion_cma_phys,
237 .map_user = ion_cma_mmap,
238 #ifdef CONFIG_ION_CMA_HIGHMEM
239 .map_kernel = ion_heap_map_kernel,
240 .unmap_kernel = ion_heap_unmap_kernel,
242 .map_kernel = ion_cma_map_kernel,
243 .unmap_kernel = ion_cma_unmap_kernel,
245 #ifdef CONFIG_ROCKCHIP_IOMMU
246 .map_iommu = ion_cma_map_iommu,
247 .unmap_iommu = ion_cma_unmap_iommu,
251 struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data)
253 struct ion_cma_heap *cma_heap;
255 cma_heap = kzalloc(sizeof(struct ion_cma_heap), GFP_KERNEL);
258 return ERR_PTR(-ENOMEM);
260 cma_heap->heap.ops = &ion_cma_ops;
261 /* get device from private heaps data, later it will be
262 * used to make the link with reserved CMA memory */
263 cma_heap->dev = data->priv;
264 cma_heap->heap.type = ION_HEAP_TYPE_DMA;
265 return &cma_heap->heap;
268 void ion_cma_heap_destroy(struct ion_heap *heap)
270 struct ion_cma_heap *cma_heap = to_cma_heap(heap);