Loading dsp/msm_audio_ion_vm.c +134 −187 Original line number Diff line number Diff line Loading @@ -12,7 +12,6 @@ #include <linux/mutex.h> #include <linux/list.h> #include <linux/dma-mapping.h> #include <linux/dma-contiguous.h> #include <linux/dma-buf.h> #include <linux/iommu.h> #include <linux/platform_device.h> Loading @@ -21,7 +20,6 @@ #include <linux/ion.h> #include <ipc/apr.h> #include <dsp/msm_audio_ion.h> #include <soc/qcom/secure_buffer.h> #include <linux/habmm.h> #define MSM_AUDIO_ION_PROBED (1 << 0) Loading @@ -33,11 +31,6 @@ #define MSM_AUDIO_SMMU_VM_CMD_UNMAP 0x00000002 #define MSM_AUDIO_SMMU_VM_HAB_MINOR_ID 1 enum msm_audio_mem_type{ MSM_AUDIO_MEM_TYPE_ION, MSM_AUDIO_MEM_TYPE_DMA, }; struct msm_audio_ion_private { bool smmu_enabled; struct device *cb_dev; Loading @@ -49,12 +42,10 @@ struct msm_audio_ion_private { struct msm_audio_alloc_data { size_t len; void *vaddr; void *handle; struct dma_buf *dma_buf; struct dma_buf_attachment *attach; struct sg_table *table; struct list_head list; dma_addr_t *paddr; enum msm_audio_mem_type type; u32 export_id; }; Loading Loading @@ -96,30 +87,7 @@ static void msm_audio_ion_add_allocation( mutex_unlock(&(msm_audio_ion_data->list_mutex)); } static int msm_audio_dma_buf_map(void *handle, void *vaddr, dma_addr_t *paddr, size_t *len) { struct msm_audio_alloc_data *alloc_data; /* Data required per buffer mapping */ alloc_data = kzalloc(sizeof(*alloc_data), GFP_KERNEL); if (!alloc_data) return -ENOMEM; alloc_data->handle = handle; alloc_data->len = *len; alloc_data->vaddr = vaddr; alloc_data->paddr = paddr; alloc_data->type = MSM_AUDIO_MEM_TYPE_DMA; msm_audio_ion_add_allocation(&msm_audio_ion_data, alloc_data); return 0; } static int msm_audio_ion_dma_buf_map(struct dma_buf *dma_buf, static int msm_audio_dma_buf_map(struct dma_buf *dma_buf, dma_addr_t *addr, size_t *len) { Loading @@ -135,13 +103,13 @@ static int msm_audio_ion_dma_buf_map(struct dma_buf *dma_buf, if (!alloc_data) return -ENOMEM; alloc_data->handle = (void*)dma_buf; alloc_data->dma_buf = dma_buf; alloc_data->len = dma_buf->size; alloc_data->type = MSM_AUDIO_MEM_TYPE_ION; *len = dma_buf->size; /* Attach the dma_buf to context bank device */ alloc_data->attach = dma_buf_attach(dma_buf, cb_dev); alloc_data->attach = dma_buf_attach(alloc_data->dma_buf, cb_dev); if (IS_ERR(alloc_data->attach)) { rc = PTR_ERR(alloc_data->attach); dev_err(cb_dev, Loading @@ -151,7 +119,7 @@ static int msm_audio_ion_dma_buf_map(struct dma_buf *dma_buf, } /* For uncached buffers, avoid cache maintanance */ rc = dma_buf_get_flags(dma_buf, &ionflag); rc = dma_buf_get_flags(alloc_data->dma_buf, &ionflag); if (rc) { dev_err(cb_dev, "%s: dma_buf_get_flags failed: %d\n", __func__, rc); Loading Loading @@ -179,46 +147,21 @@ static int msm_audio_ion_dma_buf_map(struct dma_buf *dma_buf, /* physical address from mapping */ *addr = MSM_AUDIO_ION_PHYS_ADDR(alloc_data); alloc_data->paddr = addr; msm_audio_ion_add_allocation(&msm_audio_ion_data, alloc_data); return rc; detach_dma_buf: dma_buf_detach(dma_buf, alloc_data->attach); dma_buf_detach(alloc_data->dma_buf, alloc_data->attach); free_alloc_data: kfree(alloc_data); return rc; } static int msm_audio_ion_unmap_kernel(void *vaddr, void *handle) { int rc = 0; struct device *cb_dev = msm_audio_ion_data.cb_dev; if (!vaddr) { dev_err(cb_dev, "%s: cannot find allocation for handle %pK\n", __func__, handle); rc = -EINVAL; goto err; } dma_buf_vunmap((struct dma_buf*)handle, vaddr); rc = dma_buf_end_cpu_access((struct dma_buf*)handle, DMA_BIDIRECTIONAL); if (rc) { dev_err(cb_dev, "%s: kmap dma_buf_end_cpu_access fail\n", __func__); goto err; } err: return rc; } static int msm_audio_dma_buf_unmap(void *handle) static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf) { int rc = 0; struct msm_audio_alloc_data *alloc_data = NULL; Loading @@ -232,68 +175,41 @@ static int msm_audio_dma_buf_unmap(void *handle) * on adding elements to the list. */ mutex_lock(&(msm_audio_ion_data.list_mutex)); list_for_each_safe(ptr, next, &(msm_audio_ion_data.alloc_list)) { alloc_data = list_entry(ptr, struct msm_audio_alloc_data, list); if(alloc_data->type == MSM_AUDIO_MEM_TYPE_ION) { if (alloc_data->handle == handle) { rc = msm_audio_ion_unmap_kernel( alloc_data->vaddr, handle); if(rc) { pr_err("%s: Unable to unmap ion mem rc: %d\n", __func__, rc); mutex_unlock(&(msm_audio_ion_data.list_mutex)); return rc; } list_for_each_safe(ptr, next, &(msm_audio_ion_data.alloc_list)) { alloc_data = list_entry(ptr, struct msm_audio_alloc_data, list); if (alloc_data->dma_buf == dma_buf) { found = true; dma_buf_unmap_attachment(alloc_data->attach, alloc_data->table, DMA_BIDIRECTIONAL); dma_buf_detach((struct dma_buf*) alloc_data->handle, dma_buf_detach(alloc_data->dma_buf, alloc_data->attach); dma_buf_put((struct dma_buf*) alloc_data->handle); dma_buf_put(alloc_data->dma_buf); list_del(&(alloc_data->list)); kfree(alloc_data); break; } } else { alloc_data = list_entry(ptr, struct msm_audio_alloc_data, list); if (alloc_data->handle == handle) { found = true; dma_free_coherent(cb_dev, alloc_data->len, alloc_data->vaddr, *(alloc_data->paddr)); list_del(&(alloc_data->list)); kfree(alloc_data); break; } } } mutex_unlock(&(msm_audio_ion_data.list_mutex)); if (!found) { dev_err(cb_dev, "%s: cannot find allocation, handle %pK", __func__, handle); "%s: cannot find allocation, dma_buf %pK", __func__, dma_buf); rc = -EINVAL; } return rc; } static int msm_audio_ion_smmu_map(void *handle, static int msm_audio_ion_smmu_map(struct dma_buf *dma_buf, dma_addr_t *paddr, size_t *len) { int rc; Loading @@ -306,20 +222,20 @@ static int msm_audio_ion_smmu_map(void *handle, struct msm_audio_alloc_data *alloc_data = NULL; unsigned long delay = jiffies + (HZ / 2); *len = ((struct dma_buf*)handle)->size; *len = dma_buf->size; mutex_lock(&(msm_audio_ion_data.list_mutex)); list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list), list) { if (alloc_data->handle == handle) { if (alloc_data->dma_buf == dma_buf) { found = true; /* Export the buffer to physical VM */ rc = habmm_export(msm_audio_ion_hab_handle, handle, *len, rc = habmm_export(msm_audio_ion_hab_handle, dma_buf, *len, &export_id, HABMM_EXPIMP_FLAGS_DMABUF); if (rc) { pr_err("%s: habmm_export failed handle = %pK, len = %zd, rc = %d\n", __func__, handle, *len, rc); pr_err("%s: habmm_export failed dma_buf = %pK, len = %zd, rc = %d\n", __func__, dma_buf, *len, rc); goto err; } Loading Loading @@ -373,7 +289,7 @@ static int msm_audio_ion_smmu_map(void *handle, mutex_unlock(&(msm_audio_ion_data.list_mutex)); if (!found) { pr_err("%s: cannot find allocation, handle %pK\n", __func__, handle); pr_err("%s: cannot find allocation, dma_buf %pK", __func__, dma_buf); return -EINVAL; } Loading @@ -387,7 +303,7 @@ static int msm_audio_ion_smmu_map(void *handle, return rc; } static int msm_audio_ion_smmu_unmap(void *handle) static int msm_audio_ion_smmu_unmap(struct dma_buf *dma_buf) { int rc; bool found = false; Loading @@ -406,7 +322,7 @@ static int msm_audio_ion_smmu_unmap(void *handle) list_for_each_entry_safe(alloc_data, next, &(msm_audio_ion_data.alloc_list), list) { if (alloc_data->handle == handle) { if (alloc_data->dma_buf == dma_buf) { found = true; smmu_unmap_cmd.cmd_id = MSM_AUDIO_SMMU_VM_CMD_UNMAP; smmu_unmap_cmd.export_id = alloc_data->export_id; Loading Loading @@ -462,7 +378,7 @@ static int msm_audio_ion_smmu_unmap(void *handle) mutex_unlock(&(msm_audio_ion_data.list_mutex)); if (!found) { pr_err("%s: cannot find allocation, handle %pK\n", __func__, handle); pr_err("%s: cannot find allocation, dma_buf %pK\n", __func__, dma_buf); rc = -EINVAL; } Loading @@ -485,32 +401,31 @@ static int msm_audio_ion_get_phys(struct dma_buf *dma_buf, { int rc = 0; rc = msm_audio_ion_dma_buf_map(dma_buf, addr, len); rc = msm_audio_dma_buf_map(dma_buf, addr, len); if (rc) { pr_err("%s: failed to map DMA buf, err = %d\n", __func__, rc); goto err; } pr_debug("phys=%pK, len=%zd, rc=%d\n", addr, *len, rc); pr_debug("phys=%pK, len=%zd, rc=%d\n", &(*addr), *len, rc); err: return rc; } static void *msm_audio_ion_map_kernel(void *handle) static void *msm_audio_ion_map_kernel(struct dma_buf *dma_buf) { int rc = 0; void *addr = NULL; struct msm_audio_alloc_data *alloc_data = NULL; rc = dma_buf_begin_cpu_access((struct dma_buf*)handle, DMA_BIDIRECTIONAL); rc = dma_buf_begin_cpu_access(dma_buf, DMA_BIDIRECTIONAL); if (rc) { pr_err("%s: kmap dma_buf_begin_cpu_access fail\n", __func__); goto exit; } addr = dma_buf_vmap((struct dma_buf*)handle); addr = dma_buf_vmap(dma_buf); if (!addr) { pr_err("%s: kernel mapping of dma_buf failed\n", __func__); Loading @@ -524,7 +439,7 @@ static void *msm_audio_ion_map_kernel(void *handle) mutex_lock(&(msm_audio_ion_data.list_mutex)); list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list), list) { if (alloc_data->handle == handle) { if (alloc_data->dma_buf == dma_buf) { alloc_data->vaddr = addr; break; } Loading @@ -535,12 +450,54 @@ static void *msm_audio_ion_map_kernel(void *handle) return addr; } static int msm_audio_ion_map_buf(void *handle, dma_addr_t *paddr, static int msm_audio_ion_unmap_kernel(struct dma_buf *dma_buf) { int rc = 0; void *vaddr = NULL; struct msm_audio_alloc_data *alloc_data = NULL; struct device *cb_dev = msm_audio_ion_data.cb_dev; /* * TBD: remove the below section once new API * for unmapping kernel virtual address is available. */ mutex_lock(&(msm_audio_ion_data.list_mutex)); list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list), list) { if (alloc_data->dma_buf == dma_buf) { vaddr = alloc_data->vaddr; break; } } mutex_unlock(&(msm_audio_ion_data.list_mutex)); if (!vaddr) { dev_err(cb_dev, "%s: cannot find allocation for dma_buf %pK", __func__, dma_buf); rc = -EINVAL; goto err; } dma_buf_vunmap(dma_buf, vaddr); rc = dma_buf_end_cpu_access(dma_buf, DMA_BIDIRECTIONAL); if (rc) { dev_err(cb_dev, "%s: kmap dma_buf_end_cpu_access fail\n", __func__); goto err; } err: return rc; } static int msm_audio_ion_map_buf(struct dma_buf *dma_buf, dma_addr_t *paddr, size_t *plen, void **vaddr) { int rc = 0; rc = msm_audio_ion_get_phys((struct dma_buf*) handle, paddr, plen); rc = msm_audio_ion_get_phys(dma_buf, paddr, plen); if (rc) { pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n", __func__, rc); Loading @@ -548,7 +505,7 @@ static int msm_audio_ion_map_buf(void *handle, dma_addr_t *paddr, goto err; } *vaddr = msm_audio_ion_map_kernel(handle); *vaddr = msm_audio_ion_map_kernel(dma_buf); if (IS_ERR_OR_NULL(*vaddr)) { pr_err("%s: ION memory mapping for AUDIO failed\n", __func__); rc = -ENOMEM; Loading @@ -557,11 +514,11 @@ static int msm_audio_ion_map_buf(void *handle, dma_addr_t *paddr, } if (msm_audio_ion_data.smmu_enabled) { rc = msm_audio_ion_smmu_map(handle, paddr, plen); rc = msm_audio_ion_smmu_map(dma_buf, paddr, plen); if (rc) { pr_err("%s: failed to do smmu map, err = %d\n", __func__, rc); msm_audio_dma_buf_unmap((struct dma_buf *) handle); msm_audio_dma_buf_unmap(dma_buf); goto err; } } Loading @@ -573,8 +530,7 @@ static int msm_audio_ion_map_buf(void *handle, dma_addr_t *paddr, * msm_audio_ion_alloc - * Allocs ION memory for given client name * * @handle: generic handle to the memory allocation * dma_buf for the system heap memory. vaddr for audio heap memory. * @dma_buf: dma_buf for the ION memory * @bufsz: buffer size * @paddr: Physical address to be assigned with allocated region * @plen: length of allocated region to be assigned Loading @@ -582,7 +538,7 @@ static int msm_audio_ion_map_buf(void *handle, dma_addr_t *paddr, * * Returns 0 on success or error on failure */ int msm_audio_ion_alloc(void **handle, size_t bufsz, int msm_audio_ion_alloc(struct dma_buf **dma_buf, size_t bufsz, dma_addr_t *paddr, size_t *plen, void **vaddr) { int rc = -EINVAL; Loading @@ -592,54 +548,41 @@ int msm_audio_ion_alloc(void **handle, size_t bufsz, pr_debug("%s:probe is not done, deferred\n", __func__); return -EPROBE_DEFER; } if (!handle || !paddr || !vaddr || !bufsz || !plen) { if (!dma_buf || !paddr || !vaddr || !bufsz || !plen) { pr_err("%s: Invalid params\n", __func__); return -EINVAL; } if (msm_audio_ion_data.smmu_enabled == true) { pr_debug("%s: system heap is used\n", __func__); *handle = ion_alloc(bufsz, ION_HEAP(ION_SYSTEM_HEAP_ID), 0); *dma_buf = ion_alloc(bufsz, ION_HEAP(ION_SYSTEM_HEAP_ID), 0); } else { pr_debug("%s: audio heap is used\n", __func__); *vaddr = *handle = dma_alloc_coherent( msm_audio_ion_data.cb_dev, bufsz, paddr, GFP_KERNEL); if(*vaddr != NULL) { pr_err("%s: vaddr = %pK, size=%zd\n", __func__, *vaddr, bufsz); rc = 0; } } if (IS_ERR_OR_NULL((void *)(*handle))) { if (IS_ERR((void *)(*handle))) err_ion_ptr = PTR_ERR((int *)(*handle)); *dma_buf = ion_alloc(bufsz, ION_HEAP(ION_AUDIO_HEAP_ID), 0); } if (IS_ERR_OR_NULL((void *)(*dma_buf))) { if (IS_ERR((void *)(*dma_buf))) err_ion_ptr = PTR_ERR((int *)(*dma_buf)); pr_err("%s: ION alloc fail err ptr=%ld, smmu_enabled=%d\n", __func__, err_ion_ptr, msm_audio_ion_data.smmu_enabled); rc = -ENOMEM; goto err; } if (msm_audio_ion_data.smmu_enabled) { rc = msm_audio_ion_map_buf(*handle, paddr, plen, vaddr); if (rc) { pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc); } } else { rc = msm_audio_dma_buf_map(*handle, *vaddr, paddr, &bufsz); rc = msm_audio_ion_map_buf(*dma_buf, paddr, plen, vaddr); if (rc) { pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc); dma_free_coherent(msm_audio_ion_data.cb_dev, bufsz, vaddr, *paddr); } pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc); goto err_dma_buf; } pr_debug("%s: mapped address = %pK, size=%zd\n", __func__, *vaddr, bufsz); memset(*vaddr, 0, bufsz); return rc; err_dma_buf: dma_buf_put(*dma_buf); err: return rc; } Loading Loading @@ -674,8 +617,7 @@ EXPORT_SYMBOL(msm_audio_is_hypervisor_supported); * msm_audio_ion_import- * Import ION buffer with given file descriptor * * @handle: generic handle to the memory allocation * dma_buf for the system heap memory. vaddr for audio heap memory. * @dma_buf: dma_buf for the ION memory * @fd: file descriptor for the ION memory * @ionflag: flags associated with ION buffer * @bufsz: buffer size Loading @@ -685,7 +627,7 @@ EXPORT_SYMBOL(msm_audio_is_hypervisor_supported); * * Returns 0 on success or error on failure */ int msm_audio_ion_import(void **handle, int fd, int msm_audio_ion_import(struct dma_buf **dma_buf, int fd, unsigned long *ionflag, size_t bufsz, dma_addr_t *paddr, size_t *plen, void **vaddr) { Loading @@ -696,22 +638,22 @@ int msm_audio_ion_import(void **handle, int fd, return -EPROBE_DEFER; } if (!handle || !paddr || !vaddr || !plen) { if (!dma_buf || !paddr || !vaddr || !plen) { pr_err("%s: Invalid params\n", __func__); return -EINVAL; } /* bufsz should be 0 and fd shouldn't be 0 as of now */ *handle = dma_buf_get(fd); pr_debug("%s: handle =%pK, fd=%d\n", __func__, *handle, fd); if (IS_ERR_OR_NULL((void *)(*handle))) { *dma_buf = dma_buf_get(fd); pr_debug("%s: dma_buf =%pK, fd=%d\n", __func__, *dma_buf, fd); if (IS_ERR_OR_NULL((void *)(*dma_buf))) { pr_err("%s: dma_buf_get failed\n", __func__); rc = -EINVAL; goto err; } if (ionflag != NULL) { rc = dma_buf_get_flags((struct dma_buf*)*handle, ionflag); rc = dma_buf_get_flags(*dma_buf, ionflag); if (rc) { pr_err("%s: could not get flags for the dma_buf\n", __func__); Loading @@ -719,7 +661,7 @@ int msm_audio_ion_import(void **handle, int fd, } } rc = msm_audio_ion_map_buf(*handle, paddr, plen, vaddr); rc = msm_audio_ion_map_buf(*dma_buf, paddr, plen, vaddr); if (rc) { pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc); goto err; Loading @@ -730,9 +672,9 @@ int msm_audio_ion_import(void **handle, int fd, return 0; err_ion_flag: dma_buf_put((struct dma_buf*) *handle); dma_buf_put(*dma_buf); err: *handle = NULL; *dma_buf = NULL; return rc; } EXPORT_SYMBOL(msm_audio_ion_import); Loading @@ -741,28 +683,31 @@ EXPORT_SYMBOL(msm_audio_ion_import); * msm_audio_ion_free - * fress ION memory for given client and handle * * @handle: generic handle to the memory allocation * dma_buf for the system heap memory. vaddr for audio heap memory. * @dma_buf: dma_buf for the ION memory * * Returns 0 on success or error on failure */ int msm_audio_ion_free(void *handle) int msm_audio_ion_free(struct dma_buf *dma_buf) { int ret = 0; if (!handle) { pr_err("%s: handle invalid\n", __func__); if (!dma_buf) { pr_err("%s: dma_buf invalid\n", __func__); return -EINVAL; } ret = msm_audio_ion_unmap_kernel(dma_buf); if (ret) return ret; if (msm_audio_ion_data.smmu_enabled) { ret = msm_audio_ion_smmu_unmap(handle); ret = msm_audio_ion_smmu_unmap(dma_buf); if (ret) pr_err("%s: smmu unmap failed with ret %d\n", __func__, ret); } msm_audio_dma_buf_unmap(handle); msm_audio_dma_buf_unmap(dma_buf); return 0; } Loading Loading @@ -794,7 +739,7 @@ int msm_audio_ion_mmap(struct audio_buffer *abuff, mutex_lock(&(msm_audio_ion_data.list_mutex)); list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list), list) { if (alloc_data->handle == abuff->mem_handle) { if (alloc_data->dma_buf == abuff->dma_buf) { found = true; table = alloc_data->table; break; Loading @@ -805,7 +750,7 @@ int msm_audio_ion_mmap(struct audio_buffer *abuff, if (!found) { dev_err(cb_dev, "%s: cannot find allocation, dma_buf %pK", __func__, abuff->mem_handle); __func__, abuff->dma_buf); return -EINVAL; } /* uncached */ Loading Loading @@ -911,13 +856,14 @@ static int msm_audio_ion_probe(struct platform_device *pdev) dev_info(dev, "%s: msm_audio_ion_hab_handle %x\n", __func__, msm_audio_ion_hab_handle); INIT_LIST_HEAD(&msm_audio_ion_data.alloc_list); mutex_init(&(msm_audio_ion_data.list_mutex)); exit: if (!rc) msm_audio_ion_data.device_status |= MSM_AUDIO_ION_PROBED; msm_audio_ion_data.cb_dev = dev; INIT_LIST_HEAD(&msm_audio_ion_data.alloc_list); mutex_init(&(msm_audio_ion_data.list_mutex)); return rc; } Loading @@ -927,10 +873,11 @@ static int msm_audio_ion_remove(struct platform_device *pdev) if (msm_audio_ion_data.smmu_enabled) { if (msm_audio_ion_hab_handle) habmm_socket_close(msm_audio_ion_hab_handle); mutex_destroy(&(msm_audio_ion_data.list_mutex)); } msm_audio_ion_data.smmu_enabled = 0; msm_audio_ion_data.device_status = 0; mutex_destroy(&(msm_audio_ion_data.list_mutex)); return 0; } Loading Loading
dsp/msm_audio_ion_vm.c +134 −187 Original line number Diff line number Diff line Loading @@ -12,7 +12,6 @@ #include <linux/mutex.h> #include <linux/list.h> #include <linux/dma-mapping.h> #include <linux/dma-contiguous.h> #include <linux/dma-buf.h> #include <linux/iommu.h> #include <linux/platform_device.h> Loading @@ -21,7 +20,6 @@ #include <linux/ion.h> #include <ipc/apr.h> #include <dsp/msm_audio_ion.h> #include <soc/qcom/secure_buffer.h> #include <linux/habmm.h> #define MSM_AUDIO_ION_PROBED (1 << 0) Loading @@ -33,11 +31,6 @@ #define MSM_AUDIO_SMMU_VM_CMD_UNMAP 0x00000002 #define MSM_AUDIO_SMMU_VM_HAB_MINOR_ID 1 enum msm_audio_mem_type{ MSM_AUDIO_MEM_TYPE_ION, MSM_AUDIO_MEM_TYPE_DMA, }; struct msm_audio_ion_private { bool smmu_enabled; struct device *cb_dev; Loading @@ -49,12 +42,10 @@ struct msm_audio_ion_private { struct msm_audio_alloc_data { size_t len; void *vaddr; void *handle; struct dma_buf *dma_buf; struct dma_buf_attachment *attach; struct sg_table *table; struct list_head list; dma_addr_t *paddr; enum msm_audio_mem_type type; u32 export_id; }; Loading Loading @@ -96,30 +87,7 @@ static void msm_audio_ion_add_allocation( mutex_unlock(&(msm_audio_ion_data->list_mutex)); } static int msm_audio_dma_buf_map(void *handle, void *vaddr, dma_addr_t *paddr, size_t *len) { struct msm_audio_alloc_data *alloc_data; /* Data required per buffer mapping */ alloc_data = kzalloc(sizeof(*alloc_data), GFP_KERNEL); if (!alloc_data) return -ENOMEM; alloc_data->handle = handle; alloc_data->len = *len; alloc_data->vaddr = vaddr; alloc_data->paddr = paddr; alloc_data->type = MSM_AUDIO_MEM_TYPE_DMA; msm_audio_ion_add_allocation(&msm_audio_ion_data, alloc_data); return 0; } static int msm_audio_ion_dma_buf_map(struct dma_buf *dma_buf, static int msm_audio_dma_buf_map(struct dma_buf *dma_buf, dma_addr_t *addr, size_t *len) { Loading @@ -135,13 +103,13 @@ static int msm_audio_ion_dma_buf_map(struct dma_buf *dma_buf, if (!alloc_data) return -ENOMEM; alloc_data->handle = (void*)dma_buf; alloc_data->dma_buf = dma_buf; alloc_data->len = dma_buf->size; alloc_data->type = MSM_AUDIO_MEM_TYPE_ION; *len = dma_buf->size; /* Attach the dma_buf to context bank device */ alloc_data->attach = dma_buf_attach(dma_buf, cb_dev); alloc_data->attach = dma_buf_attach(alloc_data->dma_buf, cb_dev); if (IS_ERR(alloc_data->attach)) { rc = PTR_ERR(alloc_data->attach); dev_err(cb_dev, Loading @@ -151,7 +119,7 @@ static int msm_audio_ion_dma_buf_map(struct dma_buf *dma_buf, } /* For uncached buffers, avoid cache maintanance */ rc = dma_buf_get_flags(dma_buf, &ionflag); rc = dma_buf_get_flags(alloc_data->dma_buf, &ionflag); if (rc) { dev_err(cb_dev, "%s: dma_buf_get_flags failed: %d\n", __func__, rc); Loading Loading @@ -179,46 +147,21 @@ static int msm_audio_ion_dma_buf_map(struct dma_buf *dma_buf, /* physical address from mapping */ *addr = MSM_AUDIO_ION_PHYS_ADDR(alloc_data); alloc_data->paddr = addr; msm_audio_ion_add_allocation(&msm_audio_ion_data, alloc_data); return rc; detach_dma_buf: dma_buf_detach(dma_buf, alloc_data->attach); dma_buf_detach(alloc_data->dma_buf, alloc_data->attach); free_alloc_data: kfree(alloc_data); return rc; } static int msm_audio_ion_unmap_kernel(void *vaddr, void *handle) { int rc = 0; struct device *cb_dev = msm_audio_ion_data.cb_dev; if (!vaddr) { dev_err(cb_dev, "%s: cannot find allocation for handle %pK\n", __func__, handle); rc = -EINVAL; goto err; } dma_buf_vunmap((struct dma_buf*)handle, vaddr); rc = dma_buf_end_cpu_access((struct dma_buf*)handle, DMA_BIDIRECTIONAL); if (rc) { dev_err(cb_dev, "%s: kmap dma_buf_end_cpu_access fail\n", __func__); goto err; } err: return rc; } static int msm_audio_dma_buf_unmap(void *handle) static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf) { int rc = 0; struct msm_audio_alloc_data *alloc_data = NULL; Loading @@ -232,68 +175,41 @@ static int msm_audio_dma_buf_unmap(void *handle) * on adding elements to the list. */ mutex_lock(&(msm_audio_ion_data.list_mutex)); list_for_each_safe(ptr, next, &(msm_audio_ion_data.alloc_list)) { alloc_data = list_entry(ptr, struct msm_audio_alloc_data, list); if(alloc_data->type == MSM_AUDIO_MEM_TYPE_ION) { if (alloc_data->handle == handle) { rc = msm_audio_ion_unmap_kernel( alloc_data->vaddr, handle); if(rc) { pr_err("%s: Unable to unmap ion mem rc: %d\n", __func__, rc); mutex_unlock(&(msm_audio_ion_data.list_mutex)); return rc; } list_for_each_safe(ptr, next, &(msm_audio_ion_data.alloc_list)) { alloc_data = list_entry(ptr, struct msm_audio_alloc_data, list); if (alloc_data->dma_buf == dma_buf) { found = true; dma_buf_unmap_attachment(alloc_data->attach, alloc_data->table, DMA_BIDIRECTIONAL); dma_buf_detach((struct dma_buf*) alloc_data->handle, dma_buf_detach(alloc_data->dma_buf, alloc_data->attach); dma_buf_put((struct dma_buf*) alloc_data->handle); dma_buf_put(alloc_data->dma_buf); list_del(&(alloc_data->list)); kfree(alloc_data); break; } } else { alloc_data = list_entry(ptr, struct msm_audio_alloc_data, list); if (alloc_data->handle == handle) { found = true; dma_free_coherent(cb_dev, alloc_data->len, alloc_data->vaddr, *(alloc_data->paddr)); list_del(&(alloc_data->list)); kfree(alloc_data); break; } } } mutex_unlock(&(msm_audio_ion_data.list_mutex)); if (!found) { dev_err(cb_dev, "%s: cannot find allocation, handle %pK", __func__, handle); "%s: cannot find allocation, dma_buf %pK", __func__, dma_buf); rc = -EINVAL; } return rc; } static int msm_audio_ion_smmu_map(void *handle, static int msm_audio_ion_smmu_map(struct dma_buf *dma_buf, dma_addr_t *paddr, size_t *len) { int rc; Loading @@ -306,20 +222,20 @@ static int msm_audio_ion_smmu_map(void *handle, struct msm_audio_alloc_data *alloc_data = NULL; unsigned long delay = jiffies + (HZ / 2); *len = ((struct dma_buf*)handle)->size; *len = dma_buf->size; mutex_lock(&(msm_audio_ion_data.list_mutex)); list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list), list) { if (alloc_data->handle == handle) { if (alloc_data->dma_buf == dma_buf) { found = true; /* Export the buffer to physical VM */ rc = habmm_export(msm_audio_ion_hab_handle, handle, *len, rc = habmm_export(msm_audio_ion_hab_handle, dma_buf, *len, &export_id, HABMM_EXPIMP_FLAGS_DMABUF); if (rc) { pr_err("%s: habmm_export failed handle = %pK, len = %zd, rc = %d\n", __func__, handle, *len, rc); pr_err("%s: habmm_export failed dma_buf = %pK, len = %zd, rc = %d\n", __func__, dma_buf, *len, rc); goto err; } Loading Loading @@ -373,7 +289,7 @@ static int msm_audio_ion_smmu_map(void *handle, mutex_unlock(&(msm_audio_ion_data.list_mutex)); if (!found) { pr_err("%s: cannot find allocation, handle %pK\n", __func__, handle); pr_err("%s: cannot find allocation, dma_buf %pK", __func__, dma_buf); return -EINVAL; } Loading @@ -387,7 +303,7 @@ static int msm_audio_ion_smmu_map(void *handle, return rc; } static int msm_audio_ion_smmu_unmap(void *handle) static int msm_audio_ion_smmu_unmap(struct dma_buf *dma_buf) { int rc; bool found = false; Loading @@ -406,7 +322,7 @@ static int msm_audio_ion_smmu_unmap(void *handle) list_for_each_entry_safe(alloc_data, next, &(msm_audio_ion_data.alloc_list), list) { if (alloc_data->handle == handle) { if (alloc_data->dma_buf == dma_buf) { found = true; smmu_unmap_cmd.cmd_id = MSM_AUDIO_SMMU_VM_CMD_UNMAP; smmu_unmap_cmd.export_id = alloc_data->export_id; Loading Loading @@ -462,7 +378,7 @@ static int msm_audio_ion_smmu_unmap(void *handle) mutex_unlock(&(msm_audio_ion_data.list_mutex)); if (!found) { pr_err("%s: cannot find allocation, handle %pK\n", __func__, handle); pr_err("%s: cannot find allocation, dma_buf %pK\n", __func__, dma_buf); rc = -EINVAL; } Loading @@ -485,32 +401,31 @@ static int msm_audio_ion_get_phys(struct dma_buf *dma_buf, { int rc = 0; rc = msm_audio_ion_dma_buf_map(dma_buf, addr, len); rc = msm_audio_dma_buf_map(dma_buf, addr, len); if (rc) { pr_err("%s: failed to map DMA buf, err = %d\n", __func__, rc); goto err; } pr_debug("phys=%pK, len=%zd, rc=%d\n", addr, *len, rc); pr_debug("phys=%pK, len=%zd, rc=%d\n", &(*addr), *len, rc); err: return rc; } static void *msm_audio_ion_map_kernel(void *handle) static void *msm_audio_ion_map_kernel(struct dma_buf *dma_buf) { int rc = 0; void *addr = NULL; struct msm_audio_alloc_data *alloc_data = NULL; rc = dma_buf_begin_cpu_access((struct dma_buf*)handle, DMA_BIDIRECTIONAL); rc = dma_buf_begin_cpu_access(dma_buf, DMA_BIDIRECTIONAL); if (rc) { pr_err("%s: kmap dma_buf_begin_cpu_access fail\n", __func__); goto exit; } addr = dma_buf_vmap((struct dma_buf*)handle); addr = dma_buf_vmap(dma_buf); if (!addr) { pr_err("%s: kernel mapping of dma_buf failed\n", __func__); Loading @@ -524,7 +439,7 @@ static void *msm_audio_ion_map_kernel(void *handle) mutex_lock(&(msm_audio_ion_data.list_mutex)); list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list), list) { if (alloc_data->handle == handle) { if (alloc_data->dma_buf == dma_buf) { alloc_data->vaddr = addr; break; } Loading @@ -535,12 +450,54 @@ static void *msm_audio_ion_map_kernel(void *handle) return addr; } static int msm_audio_ion_map_buf(void *handle, dma_addr_t *paddr, static int msm_audio_ion_unmap_kernel(struct dma_buf *dma_buf) { int rc = 0; void *vaddr = NULL; struct msm_audio_alloc_data *alloc_data = NULL; struct device *cb_dev = msm_audio_ion_data.cb_dev; /* * TBD: remove the below section once new API * for unmapping kernel virtual address is available. */ mutex_lock(&(msm_audio_ion_data.list_mutex)); list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list), list) { if (alloc_data->dma_buf == dma_buf) { vaddr = alloc_data->vaddr; break; } } mutex_unlock(&(msm_audio_ion_data.list_mutex)); if (!vaddr) { dev_err(cb_dev, "%s: cannot find allocation for dma_buf %pK", __func__, dma_buf); rc = -EINVAL; goto err; } dma_buf_vunmap(dma_buf, vaddr); rc = dma_buf_end_cpu_access(dma_buf, DMA_BIDIRECTIONAL); if (rc) { dev_err(cb_dev, "%s: kmap dma_buf_end_cpu_access fail\n", __func__); goto err; } err: return rc; } static int msm_audio_ion_map_buf(struct dma_buf *dma_buf, dma_addr_t *paddr, size_t *plen, void **vaddr) { int rc = 0; rc = msm_audio_ion_get_phys((struct dma_buf*) handle, paddr, plen); rc = msm_audio_ion_get_phys(dma_buf, paddr, plen); if (rc) { pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n", __func__, rc); Loading @@ -548,7 +505,7 @@ static int msm_audio_ion_map_buf(void *handle, dma_addr_t *paddr, goto err; } *vaddr = msm_audio_ion_map_kernel(handle); *vaddr = msm_audio_ion_map_kernel(dma_buf); if (IS_ERR_OR_NULL(*vaddr)) { pr_err("%s: ION memory mapping for AUDIO failed\n", __func__); rc = -ENOMEM; Loading @@ -557,11 +514,11 @@ static int msm_audio_ion_map_buf(void *handle, dma_addr_t *paddr, } if (msm_audio_ion_data.smmu_enabled) { rc = msm_audio_ion_smmu_map(handle, paddr, plen); rc = msm_audio_ion_smmu_map(dma_buf, paddr, plen); if (rc) { pr_err("%s: failed to do smmu map, err = %d\n", __func__, rc); msm_audio_dma_buf_unmap((struct dma_buf *) handle); msm_audio_dma_buf_unmap(dma_buf); goto err; } } Loading @@ -573,8 +530,7 @@ static int msm_audio_ion_map_buf(void *handle, dma_addr_t *paddr, * msm_audio_ion_alloc - * Allocs ION memory for given client name * * @handle: generic handle to the memory allocation * dma_buf for the system heap memory. vaddr for audio heap memory. * @dma_buf: dma_buf for the ION memory * @bufsz: buffer size * @paddr: Physical address to be assigned with allocated region * @plen: length of allocated region to be assigned Loading @@ -582,7 +538,7 @@ static int msm_audio_ion_map_buf(void *handle, dma_addr_t *paddr, * * Returns 0 on success or error on failure */ int msm_audio_ion_alloc(void **handle, size_t bufsz, int msm_audio_ion_alloc(struct dma_buf **dma_buf, size_t bufsz, dma_addr_t *paddr, size_t *plen, void **vaddr) { int rc = -EINVAL; Loading @@ -592,54 +548,41 @@ int msm_audio_ion_alloc(void **handle, size_t bufsz, pr_debug("%s:probe is not done, deferred\n", __func__); return -EPROBE_DEFER; } if (!handle || !paddr || !vaddr || !bufsz || !plen) { if (!dma_buf || !paddr || !vaddr || !bufsz || !plen) { pr_err("%s: Invalid params\n", __func__); return -EINVAL; } if (msm_audio_ion_data.smmu_enabled == true) { pr_debug("%s: system heap is used\n", __func__); *handle = ion_alloc(bufsz, ION_HEAP(ION_SYSTEM_HEAP_ID), 0); *dma_buf = ion_alloc(bufsz, ION_HEAP(ION_SYSTEM_HEAP_ID), 0); } else { pr_debug("%s: audio heap is used\n", __func__); *vaddr = *handle = dma_alloc_coherent( msm_audio_ion_data.cb_dev, bufsz, paddr, GFP_KERNEL); if(*vaddr != NULL) { pr_err("%s: vaddr = %pK, size=%zd\n", __func__, *vaddr, bufsz); rc = 0; } } if (IS_ERR_OR_NULL((void *)(*handle))) { if (IS_ERR((void *)(*handle))) err_ion_ptr = PTR_ERR((int *)(*handle)); *dma_buf = ion_alloc(bufsz, ION_HEAP(ION_AUDIO_HEAP_ID), 0); } if (IS_ERR_OR_NULL((void *)(*dma_buf))) { if (IS_ERR((void *)(*dma_buf))) err_ion_ptr = PTR_ERR((int *)(*dma_buf)); pr_err("%s: ION alloc fail err ptr=%ld, smmu_enabled=%d\n", __func__, err_ion_ptr, msm_audio_ion_data.smmu_enabled); rc = -ENOMEM; goto err; } if (msm_audio_ion_data.smmu_enabled) { rc = msm_audio_ion_map_buf(*handle, paddr, plen, vaddr); if (rc) { pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc); } } else { rc = msm_audio_dma_buf_map(*handle, *vaddr, paddr, &bufsz); rc = msm_audio_ion_map_buf(*dma_buf, paddr, plen, vaddr); if (rc) { pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc); dma_free_coherent(msm_audio_ion_data.cb_dev, bufsz, vaddr, *paddr); } pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc); goto err_dma_buf; } pr_debug("%s: mapped address = %pK, size=%zd\n", __func__, *vaddr, bufsz); memset(*vaddr, 0, bufsz); return rc; err_dma_buf: dma_buf_put(*dma_buf); err: return rc; } Loading Loading @@ -674,8 +617,7 @@ EXPORT_SYMBOL(msm_audio_is_hypervisor_supported); * msm_audio_ion_import- * Import ION buffer with given file descriptor * * @handle: generic handle to the memory allocation * dma_buf for the system heap memory. vaddr for audio heap memory. * @dma_buf: dma_buf for the ION memory * @fd: file descriptor for the ION memory * @ionflag: flags associated with ION buffer * @bufsz: buffer size Loading @@ -685,7 +627,7 @@ EXPORT_SYMBOL(msm_audio_is_hypervisor_supported); * * Returns 0 on success or error on failure */ int msm_audio_ion_import(void **handle, int fd, int msm_audio_ion_import(struct dma_buf **dma_buf, int fd, unsigned long *ionflag, size_t bufsz, dma_addr_t *paddr, size_t *plen, void **vaddr) { Loading @@ -696,22 +638,22 @@ int msm_audio_ion_import(void **handle, int fd, return -EPROBE_DEFER; } if (!handle || !paddr || !vaddr || !plen) { if (!dma_buf || !paddr || !vaddr || !plen) { pr_err("%s: Invalid params\n", __func__); return -EINVAL; } /* bufsz should be 0 and fd shouldn't be 0 as of now */ *handle = dma_buf_get(fd); pr_debug("%s: handle =%pK, fd=%d\n", __func__, *handle, fd); if (IS_ERR_OR_NULL((void *)(*handle))) { *dma_buf = dma_buf_get(fd); pr_debug("%s: dma_buf =%pK, fd=%d\n", __func__, *dma_buf, fd); if (IS_ERR_OR_NULL((void *)(*dma_buf))) { pr_err("%s: dma_buf_get failed\n", __func__); rc = -EINVAL; goto err; } if (ionflag != NULL) { rc = dma_buf_get_flags((struct dma_buf*)*handle, ionflag); rc = dma_buf_get_flags(*dma_buf, ionflag); if (rc) { pr_err("%s: could not get flags for the dma_buf\n", __func__); Loading @@ -719,7 +661,7 @@ int msm_audio_ion_import(void **handle, int fd, } } rc = msm_audio_ion_map_buf(*handle, paddr, plen, vaddr); rc = msm_audio_ion_map_buf(*dma_buf, paddr, plen, vaddr); if (rc) { pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc); goto err; Loading @@ -730,9 +672,9 @@ int msm_audio_ion_import(void **handle, int fd, return 0; err_ion_flag: dma_buf_put((struct dma_buf*) *handle); dma_buf_put(*dma_buf); err: *handle = NULL; *dma_buf = NULL; return rc; } EXPORT_SYMBOL(msm_audio_ion_import); Loading @@ -741,28 +683,31 @@ EXPORT_SYMBOL(msm_audio_ion_import); * msm_audio_ion_free - * fress ION memory for given client and handle * * @handle: generic handle to the memory allocation * dma_buf for the system heap memory. vaddr for audio heap memory. * @dma_buf: dma_buf for the ION memory * * Returns 0 on success or error on failure */ int msm_audio_ion_free(void *handle) int msm_audio_ion_free(struct dma_buf *dma_buf) { int ret = 0; if (!handle) { pr_err("%s: handle invalid\n", __func__); if (!dma_buf) { pr_err("%s: dma_buf invalid\n", __func__); return -EINVAL; } ret = msm_audio_ion_unmap_kernel(dma_buf); if (ret) return ret; if (msm_audio_ion_data.smmu_enabled) { ret = msm_audio_ion_smmu_unmap(handle); ret = msm_audio_ion_smmu_unmap(dma_buf); if (ret) pr_err("%s: smmu unmap failed with ret %d\n", __func__, ret); } msm_audio_dma_buf_unmap(handle); msm_audio_dma_buf_unmap(dma_buf); return 0; } Loading Loading @@ -794,7 +739,7 @@ int msm_audio_ion_mmap(struct audio_buffer *abuff, mutex_lock(&(msm_audio_ion_data.list_mutex)); list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list), list) { if (alloc_data->handle == abuff->mem_handle) { if (alloc_data->dma_buf == abuff->dma_buf) { found = true; table = alloc_data->table; break; Loading @@ -805,7 +750,7 @@ int msm_audio_ion_mmap(struct audio_buffer *abuff, if (!found) { dev_err(cb_dev, "%s: cannot find allocation, dma_buf %pK", __func__, abuff->mem_handle); __func__, abuff->dma_buf); return -EINVAL; } /* uncached */ Loading Loading @@ -911,13 +856,14 @@ static int msm_audio_ion_probe(struct platform_device *pdev) dev_info(dev, "%s: msm_audio_ion_hab_handle %x\n", __func__, msm_audio_ion_hab_handle); INIT_LIST_HEAD(&msm_audio_ion_data.alloc_list); mutex_init(&(msm_audio_ion_data.list_mutex)); exit: if (!rc) msm_audio_ion_data.device_status |= MSM_AUDIO_ION_PROBED; msm_audio_ion_data.cb_dev = dev; INIT_LIST_HEAD(&msm_audio_ion_data.alloc_list); mutex_init(&(msm_audio_ion_data.list_mutex)); return rc; } Loading @@ -927,10 +873,11 @@ static int msm_audio_ion_remove(struct platform_device *pdev) if (msm_audio_ion_data.smmu_enabled) { if (msm_audio_ion_hab_handle) habmm_socket_close(msm_audio_ion_hab_handle); mutex_destroy(&(msm_audio_ion_data.list_mutex)); } msm_audio_ion_data.smmu_enabled = 0; msm_audio_ion_data.device_status = 0; mutex_destroy(&(msm_audio_ion_data.list_mutex)); return 0; } Loading