diff --git a/dsp/msm_audio_ion_vm.c b/dsp/msm_audio_ion_vm.c index 4f71703abc..1d3002985b 100644 --- a/dsp/msm_audio_ion_vm.c +++ b/dsp/msm_audio_ion_vm.c @@ -34,6 +34,7 @@ struct msm_audio_ion_private { bool smmu_enabled; struct device *cb_dev; + struct device *cb_cma_dev; u8 device_status; struct list_head alloc_list; struct mutex list_mutex; @@ -88,7 +89,8 @@ static void msm_audio_ion_add_allocation( } static int msm_audio_dma_buf_map(struct dma_buf *dma_buf, - dma_addr_t *addr, size_t *len) + dma_addr_t *addr, size_t *len, + bool cma_mem) { struct msm_audio_alloc_data *alloc_data; @@ -96,7 +98,10 @@ static int msm_audio_dma_buf_map(struct dma_buf *dma_buf, unsigned long ionflag = 0; int rc = 0; - cb_dev = msm_audio_ion_data.cb_dev; + if (cma_mem) + cb_dev = msm_audio_ion_data.cb_cma_dev; + else + cb_dev = msm_audio_ion_data.cb_dev; /* Data required per buffer mapping */ alloc_data = kzalloc(sizeof(*alloc_data), GFP_KERNEL); @@ -161,14 +166,19 @@ free_alloc_data: return rc; } -static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf) +static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf, bool cma_mem) { int rc = 0; struct msm_audio_alloc_data *alloc_data = NULL; struct list_head *ptr, *next; - struct device *cb_dev = msm_audio_ion_data.cb_dev; + struct device *cb_dev; bool found = false; + if (cma_mem) + cb_dev = msm_audio_ion_data.cb_cma_dev; + else + cb_dev = msm_audio_ion_data.cb_dev; + /* * Though list_for_each_safe is delete safe, lock * should be explicitly acquired to avoid race condition @@ -401,7 +411,7 @@ static int msm_audio_ion_get_phys(struct dma_buf *dma_buf, { int rc = 0; - rc = msm_audio_dma_buf_map(dma_buf, addr, len); + rc = msm_audio_dma_buf_map(dma_buf, addr, len, false); if (rc) { pr_err("%s: failed to map DMA buf, err = %d\n", __func__, rc); @@ -509,7 +519,7 @@ static int msm_audio_ion_map_buf(struct dma_buf *dma_buf, dma_addr_t *paddr, if (IS_ERR_OR_NULL(*vaddr)) { pr_err("%s: ION memory mapping for AUDIO failed\n", __func__); rc = -ENOMEM; - msm_audio_dma_buf_unmap(dma_buf); + msm_audio_dma_buf_unmap(dma_buf, false); goto err; } @@ -518,7 +528,7 @@ static int msm_audio_ion_map_buf(struct dma_buf *dma_buf, dma_addr_t *paddr, if (rc) { pr_err("%s: failed to do smmu map, err = %d\n", __func__, rc); - msm_audio_dma_buf_unmap(dma_buf); + msm_audio_dma_buf_unmap(dma_buf, false); goto err; } } @@ -623,7 +633,7 @@ EXPORT_SYMBOL(msm_audio_is_hypervisor_supported); * @bufsz: buffer size * @paddr: Physical address to be assigned with allocated region * @plen: length of allocated region to be assigned - * vaddr: virtual address to be assigned + * @vaddr: virtual address to be assigned * * Returns 0 on success or error on failure */ @@ -679,6 +689,67 @@ err: } EXPORT_SYMBOL(msm_audio_ion_import); +/** + * msm_audio_ion_import_cma- + * Import ION buffer with given file descriptor + * + * @dma_buf: dma_buf for the ION memory + * @fd: file descriptor for the ION memory + * @ionflag: flags associated with ION buffer + * @bufsz: buffer size + * @paddr: Physical address to be assigned with allocated region + * @plen: length of allocated region to be assigned + * @vaddr: virtual address to be assigned + * + * Returns 0 on success or error on failure + */ +int msm_audio_ion_import_cma(struct dma_buf **dma_buf, int fd, + unsigned long *ionflag, size_t bufsz, + dma_addr_t *paddr, size_t *plen, void **vaddr) +{ + int rc = 0; + + if (!(msm_audio_ion_data.device_status & MSM_AUDIO_ION_PROBED)) { + pr_debug("%s: probe is not done, deferred\n", __func__); + return -EPROBE_DEFER; + } + + if (!dma_buf || !paddr || !vaddr || !plen || + !msm_audio_ion_data.cb_cma_dev) { + pr_err("%s: Invalid params\n", __func__); + return -EINVAL; + } + + /* bufsz should be 0 and fd shouldn't be 0 as of now */ + *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(*dma_buf, ionflag); + if (rc) { + pr_err("%s: could not get flags for the dma_buf\n", + __func__); + goto err_ion_flag; + } + } + + msm_audio_dma_buf_map(*dma_buf, paddr, plen, true); + + return 0; + +err_ion_flag: + dma_buf_put(*dma_buf); +err: + *dma_buf = NULL; + return rc; +} +EXPORT_SYMBOL(msm_audio_ion_import_cma); + /** * msm_audio_ion_free - * fress ION memory for given client and handle @@ -707,12 +778,33 @@ int msm_audio_ion_free(struct dma_buf *dma_buf) __func__, ret); } - msm_audio_dma_buf_unmap(dma_buf); + msm_audio_dma_buf_unmap(dma_buf, false); return 0; } EXPORT_SYMBOL(msm_audio_ion_free); +/** + * msm_audio_ion_free_cma - + * fress ION memory for given client and handle + * + * @dma_buf: dma_buf for the ION memory + * + * Returns 0 on success or error on failure + */ +int msm_audio_ion_free_cma(struct dma_buf *dma_buf) +{ + if (!dma_buf) { + pr_err("%s: dma_buf invalid\n", __func__); + return -EINVAL; + } + + msm_audio_dma_buf_unmap(dma_buf, true); + + return 0; +} +EXPORT_SYMBOL(msm_audio_ion_free_cma); + /** * msm_audio_ion_mmap - * Audio ION memory map @@ -814,6 +906,7 @@ EXPORT_SYMBOL(msm_audio_populate_upper_32_bits); static const struct of_device_id msm_audio_ion_dt_match[] = { { .compatible = "qcom,msm-audio-ion" }, + { .compatible = "qcom,msm-audio-ion-cma"}, { } }; MODULE_DEVICE_TABLE(of, msm_audio_ion_dt_match); @@ -833,6 +926,11 @@ static int msm_audio_ion_probe(struct platform_device *pdev) return 0; } + if (of_device_is_compatible(dev->of_node, "qcom,msm-audio-ion-cma")) { + msm_audio_ion_data.cb_cma_dev = dev; + return 0; + } + smmu_enabled = of_property_read_bool(dev->of_node, msm_audio_ion_dt); msm_audio_ion_data.smmu_enabled = smmu_enabled;