From 759eaa8274284f5595d602a103a71f1c71e3b657 Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Thu, 7 Jul 2022 14:33:26 +0800 Subject: [PATCH] video: rockchip: rga3: Remove useless memory maps Update driver version to 1.2.16 Signed-off-by: Yu Qiaowei Change-Id: I655c4cbc7dcf91769a978ad61700c43fb0e97d90 --- drivers/video/rockchip/rga3/include/rga_drv.h | 3 +- drivers/video/rockchip/rga3/include/rga_mm.h | 7 +- drivers/video/rockchip/rga3/rga_debugger.c | 53 +- drivers/video/rockchip/rga3/rga_mm.c | 616 +++++++++--------- 4 files changed, 333 insertions(+), 346 deletions(-) diff --git a/drivers/video/rockchip/rga3/include/rga_drv.h b/drivers/video/rockchip/rga3/include/rga_drv.h index 004e94f6d445..ec2f2a61fc37 100644 --- a/drivers/video/rockchip/rga3/include/rga_drv.h +++ b/drivers/video/rockchip/rga3/include/rga_drv.h @@ -86,7 +86,7 @@ #define DRIVER_MAJOR_VERISON 1 #define DRIVER_MINOR_VERSION 2 -#define DRIVER_REVISION_VERSION 15 +#define DRIVER_REVISION_VERSION 16 #define DRIVER_VERSION (STR(DRIVER_MAJOR_VERISON) "." STR(DRIVER_MINOR_VERSION) \ "." STR(DRIVER_REVISION_VERSION)) @@ -185,7 +185,6 @@ struct rga_virt_addr { struct rga_internal_buffer { /* DMA buffer */ struct rga_dma_buffer *dma_buffer; - uint32_t dma_buffer_size; /* virtual address */ struct rga_virt_addr *virt_addr; diff --git a/drivers/video/rockchip/rga3/include/rga_mm.h b/drivers/video/rockchip/rga3/include/rga_mm.h index 376301dcf835..15ed5b2ecfc6 100644 --- a/drivers/video/rockchip/rga3/include/rga_mm.h +++ b/drivers/video/rockchip/rga3/include/rga_mm.h @@ -37,13 +37,16 @@ struct rga_mm { static inline bool rga_mm_is_invalid_dma_buffer(struct rga_dma_buffer *buffer) { + if (buffer == NULL) + return true; + return buffer->scheduler == NULL ? true : false; } struct rga_internal_buffer *rga_mm_lookup_handle(struct rga_mm *mm_session, uint32_t handle); int rga_mm_lookup_flag(struct rga_mm *mm_session, uint64_t handle); -dma_addr_t rga_mm_lookup_iova(struct rga_internal_buffer *buffer, int core); -struct sg_table *rga_mm_lookup_sgt(struct rga_internal_buffer *buffer, int core); +dma_addr_t rga_mm_lookup_iova(struct rga_internal_buffer *buffer); +struct sg_table *rga_mm_lookup_sgt(struct rga_internal_buffer *buffer); void rga_mm_dump_buffer(struct rga_internal_buffer *dump_buffer); void rga_mm_dump_info(struct rga_mm *session); diff --git a/drivers/video/rockchip/rga3/rga_debugger.c b/drivers/video/rockchip/rga3/rga_debugger.c index 0881bd2bedf4..2fa51f5ebfba 100644 --- a/drivers/video/rockchip/rga3/rga_debugger.c +++ b/drivers/video/rockchip/rga3/rga_debugger.c @@ -235,7 +235,7 @@ static int rga_scheduler_show(struct seq_file *m, void *data) static int rga_mm_session_show(struct seq_file *m, void *data) { - int id, i; + int id; struct rga_mm *mm_session = NULL; struct rga_internal_buffer *dump_buffer; @@ -255,36 +255,45 @@ static int rga_mm_session_show(struct seq_file *m, void *data) switch (dump_buffer->type) { case RGA_DMA_BUFFER: case RGA_DMA_BUFFER_PTR: - seq_puts(m, "dma_buffer:\n"); - for (i = 0; i < dump_buffer->dma_buffer_size; i++) { - if (rga_mm_is_invalid_dma_buffer(&dump_buffer->dma_buffer[i])) - continue; + if (rga_mm_is_invalid_dma_buffer(dump_buffer->dma_buffer)) + break; + + seq_puts(m, "dma_buffer:\n"); + seq_printf(m, "\t dma_buf = %p, iova = 0x%lxsgt = 0x%p, size = %ld, map_core = 0x%x\n", + dump_buffer->dma_buffer->dma_buf, + (unsigned long)dump_buffer->dma_buffer->iova, + dump_buffer->dma_buffer->sgt, + dump_buffer->dma_buffer->size, + dump_buffer->dma_buffer->scheduler->core); + + if (dump_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) + seq_printf(m, "\t is contiguous, pa = 0x%lx\n", + (unsigned long)dump_buffer->phys_addr); - seq_printf(m, "\t core %d:\n", - dump_buffer->dma_buffer[i].scheduler->core); - seq_printf(m, "\t\t dma_buf = %p, iova = 0x%lx\n", - dump_buffer->dma_buffer[i].dma_buf, - (unsigned long)dump_buffer->dma_buffer[i].iova); - } break; case RGA_VIRTUAL_ADDRESS: + if (dump_buffer->virt_addr == NULL) + break; seq_puts(m, "virtual address:\n"); - seq_printf(m, "\t va = 0x%lx, pages = %p, size = %ld\n", + seq_printf(m, "\t va = 0x%lx, pages = 0x%p, size = %ld\n", (unsigned long)dump_buffer->virt_addr->addr, dump_buffer->virt_addr->pages, dump_buffer->virt_addr->size); - for (i = 0; i < dump_buffer->dma_buffer_size; i++) { - if (rga_mm_is_invalid_dma_buffer(&dump_buffer->dma_buffer[i])) - continue; + if (rga_mm_is_invalid_dma_buffer(dump_buffer->dma_buffer)) + break; + + seq_printf(m, "\t iova = 0x%lx, offset = 0x%lx, sgt = 0x%p, size = %ld, map_core = 0x%x\n", + (unsigned long)dump_buffer->dma_buffer->iova, + (unsigned long)dump_buffer->dma_buffer->offset, + dump_buffer->dma_buffer->sgt, + dump_buffer->dma_buffer->size, + dump_buffer->dma_buffer->scheduler->core); + + if (dump_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) + seq_printf(m, "\t is contiguous, pa = 0x%lx\n", + (unsigned long)dump_buffer->phys_addr); - seq_printf(m, "\t core %d:\n", - dump_buffer->dma_buffer[i].scheduler->core); - seq_printf(m, "\t\t iova = 0x%lx, sgt = %p, size = %ld\n", - (unsigned long)dump_buffer->dma_buffer[i].iova, - dump_buffer->dma_buffer[i].sgt, - dump_buffer->dma_buffer[i].size); - } break; case RGA_PHYSICAL_ADDRESS: seq_puts(m, "physical address:\n"); diff --git a/drivers/video/rockchip/rga3/rga_mm.c b/drivers/video/rockchip/rga3/rga_mm.c index 3d135bc452e7..fbc0aaf898fe 100644 --- a/drivers/video/rockchip/rga3/rga_mm.c +++ b/drivers/video/rockchip/rga3/rga_mm.c @@ -155,47 +155,43 @@ static int rga_get_user_pages(struct page **pages, unsigned long Memory, return ret; } -static void rga_free_sgt(struct rga_dma_buffer *virt_dma_buf) +static void rga_free_sgt(struct sg_table **sgt_ptr) { - if (virt_dma_buf->sgt == NULL) + if (sgt_ptr == NULL || *sgt_ptr == NULL) return; - sg_free_table(virt_dma_buf->sgt); - kfree(virt_dma_buf->sgt); - virt_dma_buf->sgt = NULL; + sg_free_table(*sgt_ptr); + kfree(*sgt_ptr); + *sgt_ptr = NULL; } -static int rga_alloc_sgt(struct rga_virt_addr *virt_addr, - struct rga_dma_buffer *virt_dma_buf) +static struct sg_table *rga_alloc_sgt(struct rga_virt_addr *virt_addr) { int ret; struct sg_table *sgt = NULL; - sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); if (sgt == NULL) { pr_err("%s alloc sgt error!\n", __func__); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } /* get sg form pages. */ - if (sg_alloc_table_from_pages(sgt, virt_addr->pages, - virt_addr->page_count, 0, - virt_addr->size, GFP_KERNEL)) { + ret = sg_alloc_table_from_pages(sgt, virt_addr->pages, + virt_addr->page_count, + 0, virt_addr->size, + GFP_KERNEL); + if (ret) { pr_err("sg_alloc_table_from_pages failed"); - ret = -ENOMEM; goto out_free_sgt; } - virt_dma_buf->sgt = sgt; - virt_dma_buf->size = virt_addr->size; - virt_dma_buf->offset = virt_addr->offset; - - return 0; + return sgt; out_free_sgt: kfree(sgt); - return ret; + return ERR_PTR(ret); } static void rga_free_virt_addr(struct rga_virt_addr **virt_addr_p) @@ -341,20 +337,14 @@ static inline bool rga_mm_check_contiguous_sgt(struct sg_table *sgt) static void rga_mm_unmap_dma_buffer(struct rga_internal_buffer *internal_buffer) { - int i; + if (rga_mm_is_invalid_dma_buffer(internal_buffer->dma_buffer)) + return; - for (i = 0; i < internal_buffer->dma_buffer_size; i++) { - if (rga_mm_is_invalid_dma_buffer(&internal_buffer->dma_buffer[i])) - continue; + rga_dma_unmap_buf(internal_buffer->dma_buffer); - rga_dma_unmap_buf(&internal_buffer->dma_buffer[i]); - - if (i == 0 && - internal_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS && - internal_buffer->phys_addr > 0) { - internal_buffer->phys_addr = 0; - } - } + if (internal_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS && + internal_buffer->phys_addr > 0) + internal_buffer->phys_addr = 0; kfree(internal_buffer->dma_buffer); internal_buffer->dma_buffer = NULL; @@ -364,110 +354,112 @@ static int rga_mm_map_dma_buffer(struct rga_external_buffer *external_buffer, struct rga_internal_buffer *internal_buffer, struct rga_job *job) { - int ret, i; - struct rga_scheduler_t *scheduler = NULL; + int ret; + struct rga_dma_buffer *buffer; + struct device *map_dev; + struct rga_scheduler_t *scheduler; - internal_buffer->dma_buffer_size = job ? 1 : rga_drvdata->num_of_scheduler; - internal_buffer->dma_buffer = kcalloc(internal_buffer->dma_buffer_size, - sizeof(struct rga_dma_buffer), GFP_KERNEL); - if (internal_buffer->dma_buffer == NULL) { + scheduler = job ? job->scheduler : + rga_drvdata->scheduler[rga_drvdata->map_scheduler_index]; + if (scheduler == NULL) { + pr_err("Invalid scheduler device!\n"); + return -EINVAL; + } + + /* + * dma-buf api needs to use default_domain of main dev, + * and not IOMMU for devices without iommu_info ptr. + */ + map_dev = scheduler->iommu_info ? scheduler->iommu_info->default_dev : scheduler->dev; + + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (buffer == NULL) { pr_err("%s alloc internal_buffer error!\n", __func__); return -ENOMEM; } - for (i = 0; i < internal_buffer->dma_buffer_size; i++) { - scheduler = job ? job->scheduler : rga_drvdata->scheduler[i]; - - /* If the physical address is greater than 4G, there is no need to map RAG_MMU. */ - if (i != 0) - if (!rga_mm_check_memory_limit(scheduler, internal_buffer->mm_flag)) - continue; - - if (scheduler->data->mmu == RGA_MMU && - ~internal_buffer->mm_flag & RGA_MEM_UNDER_4G && - i != 0) - continue; - - if (external_buffer->type == RGA_DMA_BUFFER) - ret = rga_dma_map_fd((int)external_buffer->memory, - &internal_buffer->dma_buffer[i], - DMA_BIDIRECTIONAL, - scheduler->dev); - else if (external_buffer->type == RGA_DMA_BUFFER_PTR) - ret = rga_dma_map_buf((struct dma_buf *) - u64_to_user_ptr(external_buffer->memory), - &internal_buffer->dma_buffer[i], - DMA_BIDIRECTIONAL, - scheduler->dev); - else - ret = -EFAULT; - if (ret < 0) { - pr_err("%s core[%d] map dma buffer error!\n", - __func__, scheduler->core); - goto FREE_RGA_DMA_BUF; - } - - internal_buffer->dma_buffer[i].scheduler = scheduler; - - /* At first, check whether the physical address. */ - if (i == 0) { - if (rga_mm_check_range_sgt(internal_buffer->dma_buffer[0].sgt)) - internal_buffer->mm_flag |= RGA_MEM_UNDER_4G; - - /* - * If it's physically contiguous, then the RGA_MMU can - * directly use the physical address. - */ - if (rga_mm_check_contiguous_sgt(internal_buffer->dma_buffer[0].sgt)) { - internal_buffer->mm_flag |= RGA_MEM_PHYSICAL_CONTIGUOUS; - internal_buffer->phys_addr = - sg_phys(internal_buffer->dma_buffer[0].sgt->sgl); - if (internal_buffer->phys_addr == 0) { - pr_err("%s get physical address error!", __func__); - goto FREE_RGA_DMA_BUF; - } - } - } + switch (external_buffer->type) { + case RGA_DMA_BUFFER: + ret = rga_dma_map_fd((int)external_buffer->memory, + buffer, DMA_BIDIRECTIONAL, + map_dev); + break; + case RGA_DMA_BUFFER_PTR: + ret = rga_dma_map_buf((struct dma_buf *)u64_to_user_ptr(external_buffer->memory), + buffer, DMA_BIDIRECTIONAL, + map_dev); + break; + default: + ret = -EFAULT; + break; } + if (ret < 0) { + pr_err("%s core[%d] map dma buffer error!\n", + __func__, scheduler->core); + goto free_buffer; + } + + buffer->scheduler = scheduler; + + if (rga_mm_check_range_sgt(buffer->sgt)) + internal_buffer->mm_flag |= RGA_MEM_UNDER_4G; + + /* + * If it's physically contiguous, then the RGA_MMU can + * directly use the physical address. + */ + if (rga_mm_check_contiguous_sgt(buffer->sgt)) { + internal_buffer->phys_addr = sg_phys(buffer->sgt->sgl); + if (internal_buffer->phys_addr == 0) { + pr_err("%s get physical address error!", __func__); + goto unmap_buffer; + } + + internal_buffer->mm_flag |= RGA_MEM_PHYSICAL_CONTIGUOUS; + } + + internal_buffer->dma_buffer = buffer; return 0; -FREE_RGA_DMA_BUF: - rga_mm_unmap_dma_buffer(internal_buffer); +unmap_buffer: + rga_dma_unmap_buf(buffer); + +free_buffer: + kfree(buffer); return ret; } static void rga_mm_unmap_virt_addr(struct rga_internal_buffer *internal_buffer) { - int i; - WARN_ON(internal_buffer->dma_buffer == NULL || internal_buffer->virt_addr == NULL); - for (i = 0; i < internal_buffer->dma_buffer_size; i++) { - if (rga_mm_is_invalid_dma_buffer(&internal_buffer->dma_buffer[i])) - continue; + if (rga_mm_is_invalid_dma_buffer(internal_buffer->dma_buffer)) + return; - switch (internal_buffer->dma_buffer[i].scheduler->data->mmu) { - case RGA_IOMMU: - rga_iommu_unmap(&internal_buffer->dma_buffer[i]); - break; - case RGA_MMU: - dma_unmap_sg(internal_buffer->dma_buffer[i].scheduler->dev, - internal_buffer->dma_buffer[i].sgt->sgl, - internal_buffer->dma_buffer[i].sgt->orig_nents, - DMA_BIDIRECTIONAL); - break; - default: - break; - } + switch (internal_buffer->dma_buffer->scheduler->data->mmu) { + case RGA_IOMMU: + rga_iommu_unmap(internal_buffer->dma_buffer); + break; + case RGA_MMU: + dma_unmap_sg(internal_buffer->dma_buffer->scheduler->dev, + internal_buffer->dma_buffer->sgt->sgl, + internal_buffer->dma_buffer->sgt->orig_nents, + DMA_BIDIRECTIONAL); + break; + default: + break; } - for (i = 0; i < internal_buffer->dma_buffer_size; i++) - rga_free_sgt(&internal_buffer->dma_buffer[i]); + if (internal_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS && + internal_buffer->phys_addr > 0) + internal_buffer->phys_addr = 0; + + rga_free_sgt(&internal_buffer->dma_buffer->sgt); + kfree(internal_buffer->dma_buffer); internal_buffer->dma_buffer = NULL; - internal_buffer->dma_buffer_size = 0; rga_free_virt_addr(&internal_buffer->virt_addr); @@ -480,9 +472,20 @@ static int rga_mm_map_virt_addr(struct rga_external_buffer *external_buffer, struct rga_internal_buffer *internal_buffer, struct rga_job *job, int write_flag) { - int i; int ret; - struct rga_scheduler_t *scheduler = NULL; + uint32_t mm_flag = 0; + phys_addr_t phys_addr = 0; + struct sg_table *sgt; + struct rga_virt_addr *virt_addr; + struct rga_dma_buffer *buffer; + struct rga_scheduler_t *scheduler; + + scheduler = job ? job->scheduler : + rga_drvdata->scheduler[rga_drvdata->map_scheduler_index]; + if (scheduler == NULL) { + pr_err("Invalid scheduler device!\n"); + return -EINVAL; + } internal_buffer->current_mm = current->mm; if (internal_buffer->current_mm == NULL) { @@ -492,7 +495,7 @@ static int rga_mm_map_virt_addr(struct rga_external_buffer *external_buffer, mmgrab(internal_buffer->current_mm); mmget(internal_buffer->current_mm); - ret = rga_alloc_virt_addr(&internal_buffer->virt_addr, + ret = rga_alloc_virt_addr(&virt_addr, external_buffer->memory, &internal_buffer->memory_parm, write_flag, internal_buffer->current_mm); @@ -502,105 +505,86 @@ static int rga_mm_map_virt_addr(struct rga_external_buffer *external_buffer, goto put_current_mm; } - internal_buffer->dma_buffer_size = job ? 1 : rga_drvdata->num_of_scheduler; - internal_buffer->dma_buffer = kcalloc(internal_buffer->dma_buffer_size, - sizeof(struct rga_dma_buffer), GFP_KERNEL); - if (internal_buffer->dma_buffer == NULL) { - pr_err("%s alloc internal_buffer->dma_buffer error!\n", __func__); - ret = -ENOMEM; + sgt = rga_alloc_sgt(virt_addr); + if (IS_ERR(sgt)) { + pr_err("alloc sgt error!\n"); + ret = PTR_ERR(sgt); goto free_virt_addr; } - for (i = 0; i < internal_buffer->dma_buffer_size; i++) { - scheduler = job ? job->scheduler : rga_drvdata->scheduler[i]; + if (rga_mm_check_range_sgt(sgt)) + mm_flag |= RGA_MEM_UNDER_4G; - /* If the physical address is greater than 4G, there is no need to map RGA_MMU. */ - if (scheduler->data->mmu == RGA_MMU && - ~internal_buffer->mm_flag & RGA_MEM_UNDER_4G && - i != 0) - continue; + if (rga_mm_check_contiguous_sgt(sgt)) { + phys_addr = sg_phys(sgt->sgl); + if (phys_addr == 0) { + pr_err("%s get physical address error!", __func__); + goto free_sgt; + } - ret = rga_alloc_sgt(internal_buffer->virt_addr, - &internal_buffer->dma_buffer[i]); + mm_flag |= RGA_MEM_PHYSICAL_CONTIGUOUS; + } + + if (!rga_mm_check_memory_limit(scheduler, mm_flag)) { + pr_err("scheduler core[%d] unsupported mm_flag[0x%x]!\n", + scheduler->core, mm_flag); + ret = -EINVAL; + goto free_sgt; + } + + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (buffer == NULL) { + pr_err("%s alloc internal dma_buffer error!\n", __func__); + ret = -ENOMEM; + goto free_sgt; + } + + switch (scheduler->data->mmu) { + case RGA_IOMMU: + ret = rga_iommu_map_sgt(sgt, virt_addr->size, buffer, scheduler->dev); if (ret < 0) { - pr_err("%s core[%d] alloc sgt error!\n", __func__, - scheduler->core); - goto free_sgt_and_dma_buffer; + pr_err("%s core[%d] iommu_map virtual address error!\n", + __func__, scheduler->core); + goto free_dma_buffer; } + break; + case RGA_MMU: + ret = dma_map_sg(scheduler->dev, sgt->sgl, sgt->orig_nents, DMA_BIDIRECTIONAL); + if (ret == 0) { + pr_err("%s core[%d] dma_map_sgt error! va = 0x%lx, nents = %d\n", + __func__, scheduler->core, + (unsigned long)virt_addr->addr, sgt->orig_nents); + ret = -EINVAL; + goto free_dma_buffer; + } + break; + default: + if (mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) + break; - if (i == 0) - if (rga_mm_check_range_sgt(internal_buffer->dma_buffer[0].sgt)) - internal_buffer->mm_flag |= RGA_MEM_UNDER_4G; + pr_err("Current RGA mmu[%d] cannot support virtual address!\n", + scheduler->data->mmu); + goto free_dma_buffer; } - for (i = 0; i < internal_buffer->dma_buffer_size; i++) { - scheduler = job ? job->scheduler : rga_drvdata->scheduler[i]; + buffer->sgt = sgt; + buffer->offset = virt_addr->offset; + buffer->size = virt_addr->size; + buffer->scheduler = scheduler; - if (!rga_mm_check_memory_limit(scheduler, internal_buffer->mm_flag)) - continue; - - switch (scheduler->data->mmu) { - case RGA_IOMMU: - ret = rga_iommu_map_sgt(internal_buffer->dma_buffer[i].sgt, - internal_buffer->dma_buffer[i].size, - &internal_buffer->dma_buffer[i], - scheduler->dev); - if (ret < 0) { - pr_err("%s core[%d] iommu_map virtual address error!\n", - __func__, scheduler->core); - goto unmap_virt_addr; - } - break; - case RGA_MMU: - ret = dma_map_sg(scheduler->dev, - internal_buffer->dma_buffer[i].sgt->sgl, - internal_buffer->dma_buffer[i].sgt->orig_nents, - DMA_BIDIRECTIONAL); - if (ret == 0) { - pr_err("%s core[%d] dma_map_sgt error! va = 0x%lx, nents = %d\n", - __func__, scheduler->core, - (unsigned long)internal_buffer->virt_addr->addr, - internal_buffer->dma_buffer[i].sgt->orig_nents); - ret = -EINVAL; - goto unmap_virt_addr; - } - break; - default: - pr_err("Current RGA mmu[%d] cannot support virtual address!\n", - scheduler->data->mmu); - goto free_sgt_and_dma_buffer; - } - - internal_buffer->dma_buffer[i].scheduler = scheduler; - } + internal_buffer->virt_addr = virt_addr; + internal_buffer->dma_buffer = buffer; + internal_buffer->mm_flag = mm_flag; + internal_buffer->phys_addr = phys_addr ? phys_addr : 0; return 0; -unmap_virt_addr: - for (i = 0; i < internal_buffer->dma_buffer_size; i++) { - if (rga_mm_is_invalid_dma_buffer(&internal_buffer->dma_buffer[i])) - continue; - - switch (internal_buffer->dma_buffer[i].scheduler->data->mmu) { - case RGA_IOMMU: - rga_iommu_unmap(&internal_buffer->dma_buffer[i]); - break; - case RGA_MMU: - dma_unmap_sg(internal_buffer->dma_buffer[i].scheduler->dev, - internal_buffer->dma_buffer[i].sgt->sgl, - internal_buffer->dma_buffer[i].sgt->orig_nents, - DMA_BIDIRECTIONAL); - break; - default: - break; - } - } -free_sgt_and_dma_buffer: - for (i = 0; i < internal_buffer->dma_buffer_size; i++) - rga_free_sgt(&internal_buffer->dma_buffer[i]); - kfree(internal_buffer->dma_buffer); +free_dma_buffer: + kfree(buffer); +free_sgt: + rga_free_sgt(&sgt); free_virt_addr: - rga_free_virt_addr(&internal_buffer->virt_addr); + rga_free_virt_addr(&virt_addr); put_current_mm: mmput(internal_buffer->current_mm); mmdrop(internal_buffer->current_mm); @@ -611,82 +595,83 @@ put_current_mm: static void rga_mm_unmap_phys_addr(struct rga_internal_buffer *internal_buffer) { - int i; - WARN_ON(internal_buffer->dma_buffer == NULL); - for (i = 0; i < internal_buffer->dma_buffer_size; i++) { - if (rga_mm_is_invalid_dma_buffer(&internal_buffer->dma_buffer[i])) - continue; + if (rga_mm_is_invalid_dma_buffer(internal_buffer->dma_buffer)) + return; - if (internal_buffer->dma_buffer[i].scheduler->data->mmu == RGA_IOMMU) - rga_iommu_unmap(&internal_buffer->dma_buffer[i]); - } - - internal_buffer->phys_addr = 0; + if (internal_buffer->dma_buffer->scheduler->data->mmu == RGA_IOMMU) + rga_iommu_unmap(internal_buffer->dma_buffer); kfree(internal_buffer->dma_buffer); internal_buffer->dma_buffer = NULL; - internal_buffer->dma_buffer_size = 0; + internal_buffer->phys_addr = 0; + internal_buffer->size = 0; } static int rga_mm_map_phys_addr(struct rga_external_buffer *external_buffer, struct rga_internal_buffer *internal_buffer, struct rga_job *job) { - int ret, i; - struct rga_scheduler_t *scheduler = NULL; + int ret; + phys_addr_t phys_addr; + int buffer_size; + uint32_t mm_flag = 0; + struct rga_dma_buffer *buffer; + struct rga_scheduler_t *scheduler; - internal_buffer->dma_buffer_size = job ? 1 : rga_drvdata->num_of_scheduler; - internal_buffer->dma_buffer = kcalloc(internal_buffer->dma_buffer_size, - sizeof(struct rga_dma_buffer), GFP_KERNEL); - if (internal_buffer->dma_buffer == NULL) { - pr_err("%s alloc internal_buffer error!\n", __func__); + scheduler = job ? job->scheduler : + rga_drvdata->scheduler[rga_drvdata->map_scheduler_index]; + if (scheduler == NULL) { + pr_err("Invalid scheduler device!\n"); + return -EINVAL; + } + + if (internal_buffer->memory_parm.size) + buffer_size = internal_buffer->memory_parm.size; + else + buffer_size = rga_image_size_cal(internal_buffer->memory_parm.width, + internal_buffer->memory_parm.height, + internal_buffer->memory_parm.format, + NULL, NULL, NULL); + if (buffer_size <= 0) { + pr_err("Fault to get phys addr size!\n"); + return buffer_size == 0 ? -EINVAL : buffer_size; + } + + phys_addr = external_buffer->memory; + mm_flag |= RGA_MEM_PHYSICAL_CONTIGUOUS; + if (rga_mm_check_range_phys_addr(phys_addr, buffer_size)) + mm_flag |= RGA_MEM_UNDER_4G; + + if (!rga_mm_check_memory_limit(scheduler, mm_flag)) { + pr_err("scheduler core[%d] unsupported mm_flag[0x%x]!\n", + scheduler->core, mm_flag); + return -EINVAL; + } + + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (buffer == NULL) { + pr_err("%s alloc internal dma buffer error!\n", __func__); return -ENOMEM; } - internal_buffer->phys_addr = external_buffer->memory; - - if (internal_buffer->memory_parm.size) - internal_buffer->size = internal_buffer->memory_parm.size; - else - internal_buffer->size = - rga_image_size_cal(internal_buffer->memory_parm.width, - internal_buffer->memory_parm.height, - internal_buffer->memory_parm.format, - NULL, NULL, NULL); - - internal_buffer->mm_flag |= RGA_MEM_PHYSICAL_CONTIGUOUS; - if (rga_mm_check_range_phys_addr(internal_buffer->phys_addr, internal_buffer->size)) - internal_buffer->mm_flag |= RGA_MEM_UNDER_4G; - - for (i = 0; i < internal_buffer->dma_buffer_size; i++) { - scheduler = job ? job->scheduler : rga_drvdata->scheduler[i]; - - if (!rga_mm_check_memory_limit(scheduler, internal_buffer->mm_flag)) - continue; - - if (scheduler->data->mmu == RGA_IOMMU) { - ret = rga_iommu_map(internal_buffer->phys_addr, - internal_buffer->size, - &internal_buffer->dma_buffer[i], - scheduler->dev); - if (ret < 0) { - pr_err("%s core[%d] map phys_addr error!\n", - __func__, scheduler->core); - goto UNMAP_PHYS_ADDR; - } + if (scheduler->data->mmu == RGA_IOMMU) { + ret = rga_iommu_map(phys_addr, buffer_size, buffer, scheduler->dev); + if (ret < 0) { + pr_err("%s core[%d] map phys_addr error!\n", __func__, scheduler->core); + return ret; } - - internal_buffer->dma_buffer[i].scheduler = scheduler; } + buffer->scheduler = scheduler; + + internal_buffer->phys_addr = phys_addr; + internal_buffer->size = buffer_size; + internal_buffer->mm_flag = mm_flag; + internal_buffer->dma_buffer = buffer; + return 0; - -UNMAP_PHYS_ADDR: - rga_mm_unmap_phys_addr(internal_buffer); - - return ret; } static int rga_mm_unmap_buffer(struct rga_internal_buffer *internal_buffer) @@ -886,40 +871,24 @@ int rga_mm_lookup_flag(struct rga_mm *mm_session, uint64_t handle) return output_buffer->mm_flag; } -dma_addr_t rga_mm_lookup_iova(struct rga_internal_buffer *buffer, int core) +dma_addr_t rga_mm_lookup_iova(struct rga_internal_buffer *buffer) { - int i; + if (rga_mm_is_invalid_dma_buffer(buffer->dma_buffer)) + return 0; - for (i = 0; i < buffer->dma_buffer_size; i++) { - if (rga_mm_is_invalid_dma_buffer(&buffer->dma_buffer[i])) - continue; - - if (buffer->dma_buffer[i].scheduler->core == core) - return buffer->dma_buffer[i].iova + buffer->dma_buffer[i].offset; - } - - return 0; + return buffer->dma_buffer->iova + buffer->dma_buffer->offset; } -struct sg_table *rga_mm_lookup_sgt(struct rga_internal_buffer *buffer, int core) +struct sg_table *rga_mm_lookup_sgt(struct rga_internal_buffer *buffer) { - int i; + if (rga_mm_is_invalid_dma_buffer(buffer->dma_buffer)) + return NULL; - for (i = 0; i < buffer->dma_buffer_size; i++) { - if (rga_mm_is_invalid_dma_buffer(&buffer->dma_buffer[i])) - continue; - - if (buffer->dma_buffer[i].scheduler->core == core) - return buffer->dma_buffer[i].sgt; - } - - return NULL; + return buffer->dma_buffer->sgt; } void rga_mm_dump_buffer(struct rga_internal_buffer *dump_buffer) { - int i; - pr_info("handle = %d refcount = %d mm_flag = 0x%x\n", dump_buffer->handle, kref_read(&dump_buffer->refcount), dump_buffer->mm_flag); @@ -927,37 +896,44 @@ void rga_mm_dump_buffer(struct rga_internal_buffer *dump_buffer) switch (dump_buffer->type) { case RGA_DMA_BUFFER: case RGA_DMA_BUFFER_PTR: - pr_info("dma_buffer:\n"); - for (i = 0; i < dump_buffer->dma_buffer_size; i++) { - if (rga_mm_is_invalid_dma_buffer(&dump_buffer->dma_buffer[i])) - continue; + if (rga_mm_is_invalid_dma_buffer(dump_buffer->dma_buffer)) + break; - pr_info("core %d: dma_buf = %p, iova = 0x%lx\n", - dump_buffer->dma_buffer[i].scheduler->core, - dump_buffer->dma_buffer[i].dma_buf, - (unsigned long)dump_buffer->dma_buffer[i].iova); - } + pr_info("dma_buffer:\n"); + pr_info("dma_buf = %p, iova = 0x%lx, sgt = %p, size = %ld, map_core = 0x%x\n", + dump_buffer->dma_buffer->dma_buf, + (unsigned long)dump_buffer->dma_buffer->iova, + dump_buffer->dma_buffer->sgt, + dump_buffer->dma_buffer->size, + dump_buffer->dma_buffer->scheduler->core); if (dump_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) pr_info("is contiguous, pa = 0x%lx\n", (unsigned long)dump_buffer->phys_addr); break; case RGA_VIRTUAL_ADDRESS: - pr_info("virtual address: va = 0x%lx, pages = %p, size = %ld\n", + if (dump_buffer->virt_addr == NULL) + break; + + pr_info("virtual address:\n"); + pr_info("va = 0x%lx, pages = %p, size = %ld\n", (unsigned long)dump_buffer->virt_addr->addr, dump_buffer->virt_addr->pages, dump_buffer->virt_addr->size); - for (i = 0; i < dump_buffer->dma_buffer_size; i++) { - if (rga_mm_is_invalid_dma_buffer(&dump_buffer->dma_buffer[i])) - continue; + if (rga_mm_is_invalid_dma_buffer(dump_buffer->dma_buffer)) + break; - pr_info("core %d: iova = 0x%lx, sgt = %p, size = %ld\n", - dump_buffer->dma_buffer[i].scheduler->core, - (unsigned long)dump_buffer->dma_buffer[i].iova, - dump_buffer->dma_buffer[i].sgt, - dump_buffer->dma_buffer[i].size); - } + pr_info("iova = 0x%lx, offset = 0x%lx, sgt = %p, size = %ld, map_core = 0x%x\n", + (unsigned long)dump_buffer->dma_buffer->iova, + (unsigned long)dump_buffer->dma_buffer->offset, + dump_buffer->dma_buffer->sgt, + dump_buffer->dma_buffer->size, + dump_buffer->dma_buffer->scheduler->core); + + if (dump_buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) + pr_info("is contiguous, pa = 0x%lx\n", + (unsigned long)dump_buffer->phys_addr); break; case RGA_PHYSICAL_ADDRESS: pr_info("physical address: pa = 0x%lx\n", (unsigned long)dump_buffer->phys_addr); @@ -1152,7 +1128,7 @@ static int rga_mm_set_mmu_base(struct rga_job *job, mutex_unlock(&rga_drvdata->lock); } - sgt = rga_mm_lookup_sgt(job_buf->y_addr, job->core); + sgt = rga_mm_lookup_sgt(job_buf->y_addr); if (sgt == NULL) { pr_err("rga2 cannot get sgt from internal buffer!\n"); ret = -EINVAL; @@ -1160,7 +1136,7 @@ static int rga_mm_set_mmu_base(struct rga_job *job, } rga_mm_sgt_to_page_table(sgt, page_table, yrgb_count, false); - sgt = rga_mm_lookup_sgt(job_buf->uv_addr, job->core); + sgt = rga_mm_lookup_sgt(job_buf->uv_addr); if (sgt == NULL) { pr_err("rga2 cannot get sgt from internal buffer!\n"); ret = -EINVAL; @@ -1168,7 +1144,7 @@ static int rga_mm_set_mmu_base(struct rga_job *job, } rga_mm_sgt_to_page_table(sgt, page_table + yrgb_count, uv_count, false); - sgt = rga_mm_lookup_sgt(job_buf->v_addr, job->core); + sgt = rga_mm_lookup_sgt(job_buf->v_addr); if (sgt == NULL) { pr_err("rga2 cannot get sgt from internal buffer!\n"); ret = -EINVAL; @@ -1211,7 +1187,7 @@ static int rga_mm_set_mmu_base(struct rga_job *job, mutex_unlock(&rga_drvdata->lock); } - sgt = rga_mm_lookup_sgt(job_buf->addr, job->core); + sgt = rga_mm_lookup_sgt(job_buf->addr); if (sgt == NULL) { pr_err("rga2 cannot get sgt from internal buffer!\n"); ret = -EINVAL; @@ -1242,20 +1218,20 @@ static int rga_mm_sync_dma_sg_for_device(struct rga_internal_buffer *buffer, struct sg_table *sgt; struct rga_scheduler_t *scheduler; - scheduler = rga_job_get_scheduler(job); - if (scheduler == NULL) { - pr_err("%s(%d), failed to get scheduler, core = 0x%x\n", - __func__, __LINE__, job->core); - return -EFAULT; - } - - sgt = rga_mm_lookup_sgt(buffer, job->core); + sgt = rga_mm_lookup_sgt(buffer); if (sgt == NULL) { pr_err("%s(%d), failed to get sgt, core = 0x%x\n", __func__, __LINE__, job->core); return -EINVAL; } + scheduler = buffer->dma_buffer->scheduler; + if (scheduler == NULL) { + pr_err("%s(%d), failed to get scheduler, core = 0x%x\n", + __func__, __LINE__, job->core); + return -EFAULT; + } + dma_sync_sg_for_device(scheduler->dev, sgt->sgl, sgt->orig_nents, dir); return 0; @@ -1268,20 +1244,20 @@ static int rga_mm_sync_dma_sg_for_cpu(struct rga_internal_buffer *buffer, struct sg_table *sgt; struct rga_scheduler_t *scheduler; - scheduler = rga_job_get_scheduler(job); - if (scheduler == NULL) { - pr_err("%s(%d), failed to get scheduler, core = 0x%x\n", - __func__, __LINE__, job->core); - return -EFAULT; - } - - sgt = rga_mm_lookup_sgt(buffer, job->core); + sgt = rga_mm_lookup_sgt(buffer); if (sgt == NULL) { pr_err("%s(%d), failed to get sgt, core = 0x%x\n", __func__, __LINE__, job->core); return -EINVAL; } + scheduler = buffer->dma_buffer->scheduler; + if (scheduler == NULL) { + pr_err("%s(%d), failed to get scheduler, core = 0x%x\n", + __func__, __LINE__, job->core); + return -EFAULT; + } + dma_sync_sg_for_cpu(scheduler->dev, sgt->sgl, sgt->orig_nents, dir); return 0; @@ -1295,7 +1271,7 @@ static int rga_mm_get_buffer_info(struct rga_job *job, switch (job->scheduler->data->mmu) { case RGA_IOMMU: - addr = rga_mm_lookup_iova(internal_buffer, job->core); + addr = rga_mm_lookup_iova(internal_buffer); if (addr == 0) { pr_err("core[%d] lookup buffer_type[0x%x] iova error!\n", job->core, internal_buffer->type);