/* ION CMA heap operations functions */ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long len, unsigned long align, unsigned long flags) { struct ion_cma_heap *cma_heap = to_cma_heap(heap); struct device *dev = cma_heap->dev; struct ion_cma_buffer_info *info; dev_dbg(dev, "Request buffer allocation len %ld\n", len); info = kzalloc(sizeof(struct ion_cma_buffer_info), GFP_KERNEL); if (!info) { dev_err(dev, "Can't allocate buffer info\n"); return ION_CMA_ALLOCATE_FAILED; } #ifdef ION_CMA_SPLIT_DMA_ALLOC info->handle = cma_alloc_phys(len); if (!info->handle) { dev_err(dev, "Fail to allocate buffer, cma_alloc_phys err!\n"); goto err; } info->cpu_addr = NULL; #else info->cpu_addr = dma_alloc_coherent(dev, len, &(info->handle), GFP_HIGHUSER | __GFP_ZERO); if (!info->cpu_addr) { dev_err(dev, "Fail to allocate buffer\n"); goto err; } #endif info->table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); if (!info->table) { dev_err(dev, "Fail to allocate sg table\n"); goto free_mem; } if (ion_cma_get_sgtable (dev, info->table, info->cpu_addr, info->handle, len)) goto free_table; /* keep this for memory release */ buffer->priv_virt = info; dev_dbg(dev, "Allocate buffer %p\n", buffer); return 0; free_table: kfree(info->table); free_mem: #ifdef ION_CMA_SPLIT_DMA_ALLOC cma_free_phys(info->handle, len); #else dma_free_coherent(dev, len, info->cpu_addr, info->handle); #endif err: kfree(info); return ION_CMA_ALLOCATE_FAILED; }
static int ion_cma_mmap(struct ion_heap *mapper, struct ion_buffer *buffer, struct vm_area_struct *vma) { struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap); struct device *dev = cma_heap->dev; struct ion_cma_buffer_info *info = buffer->priv_virt; return dma_mmap_coherent(dev, vma, info->cpu_addr, info->handle, buffer->size); }
static void ion_cma_free(struct ion_buffer *buffer) { struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap); struct device *dev = cma_heap->dev; struct ion_cma_buffer_info *info = buffer->priv_virt; dev_dbg(dev, "Release buffer %p\n", buffer); /* release memory */ dma_free_coherent(dev, buffer->size, info->cpu_addr, info->handle); /* release sg table */ sg_free_table(info->table); kfree(info->table); kfree(info); }
/* return physical address in addr */ static int ion_cma_phys(struct ion_heap *heap, struct ion_buffer *buffer, ion_phys_addr_t *addr, size_t *len) { struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap); struct device *dev = cma_heap->dev; struct ion_cma_buffer_info *info = buffer->priv_virt; dev_dbg(dev, "Return buffer %p physical address 0x%pa\n", buffer, &info->handle); *addr = info->handle; *len = buffer->size; return 0; }
/* ION CMA heap operations functions */ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long len, unsigned long align, unsigned long flags) { struct ion_cma_heap *cma_heap = to_cma_heap(heap); struct device *dev = cma_heap->dev; struct ion_cma_buffer_info *info; dev_dbg(dev, "Request buffer allocation len %ld\n", len); if (buffer->flags & ION_FLAG_CACHED) return -EINVAL; if (align > PAGE_SIZE) return -EINVAL; info = kzalloc(sizeof(struct ion_cma_buffer_info), GFP_KERNEL); if (!info) return ION_CMA_ALLOCATE_FAILED; info->cpu_addr = dma_alloc_coherent(dev, len, &(info->handle), GFP_HIGHUSER | __GFP_ZERO); if (!info->cpu_addr) { dev_err(dev, "Fail to allocate buffer\n"); goto err; } info->table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); if (!info->table) goto free_mem; if (dma_common_get_sgtable (dev, info->table, info->cpu_addr, info->handle, len)) goto free_table; /* keep this for memory release */ buffer->priv_virt = info; dev_dbg(dev, "Allocate buffer %p\n", buffer); return 0; free_table: kfree(info->table); free_mem: dma_free_coherent(dev, len, info->cpu_addr, info->handle); err: kfree(info); return ION_CMA_ALLOCATE_FAILED; }
static void ion_cma_free(struct ion_buffer *buffer) { struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap); struct device *dev = cma_heap->dev; struct ion_cma_buffer_info *info = buffer->priv_virt; dev_dbg(dev, "Release buffer %p\n", buffer); /* release memory */ #ifdef ION_CMA_SPLIT_DMA_ALLOC cma_free_phys((u32)info->handle, buffer->size); #else dma_free_coherent(dev, buffer->size, info->cpu_addr, info->handle); #endif /* release sg table */ sg_free_table(info->table); kfree(info->table); kfree(info); }
/* ION CMA heap operations functions */ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long len, unsigned long align, unsigned long flags) { struct ion_cma_heap *cma_heap = to_cma_heap(heap); struct device *dev = cma_heap->dev; struct ion_cma_buffer_info *info; struct page *cma_pages = NULL; unsigned long long sBegin,sEnd; unsigned long sEnd_nanosec; printk(KERN_ERR "%s: enter\n", __FUNCTION__); dev_dbg(dev, "Request buffer allocation len %ld\n", len); if (align > PAGE_SIZE) { pr_err("%s error: return EINVAL!\n", __func__); BUG(); return -EINVAL; } info = kzalloc(sizeof(struct ion_cma_buffer_info), GFP_KERNEL); if (!info) { dev_err(dev, "Can't allocate buffer info\n"); return ION_CMA_ALLOCATE_FAILED; } sBegin = cpu_clock(smp_processor_id()); if (buffer->flags & ION_FLAG_CACHED) { cma_pages = dma_alloc_from_contiguous(NULL,(PAGE_ALIGN(len)>>PAGE_SHIFT), align); if(cma_pages== NULL) { dev_err(dev, "handle Fail to allocate buffer\n"); goto err; } info->handle = page_to_phys(cma_pages); } else {
void ion_cma_heap_destroy(struct ion_heap *heap) { struct ion_cma_heap *cma_heap = to_cma_heap(heap); kfree(cma_heap); }
/* ION CMA heap operations functions */ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long len, unsigned long align, unsigned long flags) { struct ion_cma_heap *cma_heap = to_cma_heap(heap); struct device *dev = cma_heap->dev; struct ion_cma_buffer_info *info; dev_dbg(dev, "Request buffer allocation len %ld\n", len); if (buffer->flags & ION_FLAG_CACHED) return -EINVAL; if (align > PAGE_SIZE) return -EINVAL; if (!ion_is_heap_available(heap, flags, NULL)) return -EPERM; info = kzalloc(sizeof(struct ion_cma_buffer_info), GFP_KERNEL); if (!info) { dev_err(dev, "Can't allocate buffer info\n"); return ION_CMA_ALLOCATE_FAILED; } info->cpu_addr = dma_alloc_coherent(dev, len, &(info->handle), GFP_HIGHUSER | __GFP_ZERO); if (!info->cpu_addr) { dev_err(dev, "Fail to allocate buffer\n"); goto err; } info->table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); if (!info->table) { dev_err(dev, "Fail to allocate sg table\n"); goto free_mem; } if (ion_cma_get_sgtable (dev, info->table, info->cpu_addr, info->handle, len)) goto free_table; /* keep this for memory release */ buffer->priv_virt = info; #ifdef CONFIG_ARM64 if (!ion_buffer_cached(buffer) && !(buffer->flags & ION_FLAG_PROTECTED)) { if (ion_buffer_need_flush_all(buffer)) flush_all_cpu_caches(); else __flush_dcache_area(page_address(sg_page(info->table->sgl)), len); } #else if (!ion_buffer_cached(buffer) && !(buffer->flags & ION_FLAG_PROTECTED)) { if (ion_buffer_need_flush_all(buffer)) flush_all_cpu_caches(); else dmac_flush_range(page_address(sg_page(info->table->sgl), len, DMA_BIDIRECTIONAL)); } #endif if ((buffer->flags & ION_FLAG_PROTECTED) && ion_secure_protect(heap)) goto free_table; dev_dbg(dev, "Allocate buffer %p\n", buffer); return 0; free_table: kfree(info->table); free_mem: dma_free_coherent(dev, len, info->cpu_addr, info->handle); err: kfree(info); return ION_CMA_ALLOCATE_FAILED; }