From bbba44d9e03d148bca384486da5de6c35a56787e Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Sat, 2 Feb 2019 18:00:28 +0800 Subject: [PATCH] ge2d: unmap ge2d dma_buf after ge2d process finished [1/1] PD#SWPL-4839 Problem: have risk of unmap ge2d dma_buf Solution: unmap ge2d dma_buf after ge2d process finished Verify: verify by w400 Change-Id: Ia84786b297f8e95cc9efc038300917c98d6b73f6 Signed-off-by: Pengcheng Chen Signed-off-by: Jian Cao gdc: unmap gdc dma_buf after gdc process stop [2/2] PD#SWPL-4839 Problem: have risk of unmap gdc dma_buf Solution: unmap gdc dma_buf after gdc process stop Verify: verify by w400 Change-Id: If86ac881fd85a5c4b3583567c9748e87149c1d78 Signed-off-by: Pengcheng Chen --- drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c | 4 +- drivers/amlogic/media/common/ge2d/ge2d_wq.c | 111 +++++++++++++++++++----- drivers/amlogic/media/gdc/app/gdc_dmabuf.c | 1 - drivers/amlogic/media/gdc/app/gdc_module.c | 75 +++++++++------- drivers/amlogic/media/gdc/inc/gdc/gdc_config.h | 10 ++- include/linux/amlogic/media/ge2d/ge2d.h | 15 ++++ 6 files changed, 163 insertions(+), 53 deletions(-) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c index 5225e72..046cb1e 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c @@ -515,6 +515,7 @@ int ge2d_dma_buffer_map(struct aml_dma_cfg *cfg) cfg->attach = d_att; cfg->vaddr = vaddr; cfg->sg = sg; + ge2d_log_dbg("%s\n", __func__); return ret; vmap_err: @@ -549,7 +550,6 @@ int ge2d_dma_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr) *addr = PFN_PHYS(page_to_pfn(page)); ret = 0; } - ge2d_dma_buffer_unmap(cfg); return ret; } @@ -586,6 +586,8 @@ void ge2d_dma_buffer_unmap(struct aml_dma_cfg *cfg) dma_buf_detach(dbuf, d_att); dma_buf_put(dbuf); + + ge2d_log_dbg("%s\n", __func__); } void ge2d_dma_buffer_dma_flush(struct device *dev, int fd) diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.c b/drivers/amlogic/media/common/ge2d/ge2d_wq.c index ae4816d..e2c4209 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.c @@ -389,7 +389,25 @@ static int ge2d_process_work_queue(struct ge2d_context_s *wq) pos = pos->next; list_move_tail(&pitem->list, &wq->free_queue); spin_unlock(&wq->lock); - + /* if dma buf detach it */ + if (pitem->config.src_dma_cfg.dma_used) { + ge2d_dma_buffer_unmap((struct aml_dma_cfg * + )pitem->config.src_dma_cfg.dma_cfg); + pitem->config.src_dma_cfg.dma_used = 0; + kfree(pitem->config.src_dma_cfg.dma_cfg); + } + if (pitem->config.src2_dma_cfg.dma_used) { + ge2d_dma_buffer_unmap((struct aml_dma_cfg * + )pitem->config.src2_dma_cfg.dma_cfg); + pitem->config.src2_dma_cfg.dma_used = 0; + kfree(pitem->config.src2_dma_cfg.dma_cfg); + } + if (pitem->config.dst_dma_cfg.dma_used) { + ge2d_dma_buffer_unmap((struct aml_dma_cfg * + )pitem->config.dst_dma_cfg.dma_cfg); + pitem->config.dst_dma_cfg.dma_used = 0; + kfree(pitem->config.dst_dma_cfg.dma_cfg); + } pitem = (struct ge2d_queue_item_s *)pos; } while (pos != head); ge2d_manager.last_wq = wq; @@ -406,6 +424,29 @@ static irqreturn_t ge2d_wq_handle(int irq_number, void *para) return IRQ_HANDLED; } +struct ge2d_dma_cfg_s *ge2d_wq_get_dma_cfg(struct ge2d_context_s *wq, + unsigned int data_type) +{ + struct ge2d_dma_cfg_s *dma_cfg = NULL; + + switch (data_type) { + case AML_GE2D_SRC: + dma_cfg = &wq->config.src_dma_cfg; + break; + case AML_GE2D_SRC2: + dma_cfg = &wq->config.src2_dma_cfg; + break; + case AML_GE2D_DST: + dma_cfg = &wq->config.dst_dma_cfg; + break; + default: + ge2d_log_err("wrong data_type\n"); + break; + } + + return dma_cfg; +} + struct ge2d_src1_data_s *ge2d_wq_get_src_data(struct ge2d_context_s *wq) { return &wq->config.src1_data; @@ -984,11 +1025,13 @@ static int build_ge2d_addr_config_ion( } static int build_ge2d_addr_config_dma( + struct ge2d_context_s *context, struct config_planes_ion_s *plane, unsigned int format, unsigned int *addr, unsigned int *stride, - unsigned int dir + unsigned int dir, + unsigned int data_type ) { int ret = -1; @@ -1000,12 +1043,19 @@ static int build_ge2d_addr_config_dma( bpp_value); if (plane) { if (plane[0].shared_fd) { - struct aml_dma_cfg cfg; + struct ge2d_dma_cfg_s *cfg = NULL; + struct aml_dma_cfg *dma_cfg = NULL; - cfg.fd = plane[0].shared_fd; - cfg.dev = &(ge2d_manager.pdev->dev); - cfg.dir = dir; - ret = ge2d_dma_buffer_get_phys(&cfg, &addr_temp); + cfg = ge2d_wq_get_dma_cfg(context, data_type); + if (!cfg) + return -1; + cfg->dma_used = 1; + dma_cfg = kzalloc(sizeof(*dma_cfg), GFP_KERNEL); + dma_cfg->fd = plane[0].shared_fd; + dma_cfg->dev = &(ge2d_manager.pdev->dev); + dma_cfg->dir = dir; + cfg->dma_cfg = dma_cfg; + ret = ge2d_dma_buffer_get_phys(dma_cfg, &addr_temp); if (ret != 0) return ret; } @@ -1164,12 +1214,14 @@ static int build_ge2d_config_ex_ion(struct config_planes_ion_s *plane, } return ret; } -static int build_ge2d_config_ex_dma(struct config_planes_ion_s *plane, +static int build_ge2d_config_ex_dma(struct ge2d_context_s *context, + struct config_planes_ion_s *plane, unsigned int format, unsigned int *canvas_index, int index, unsigned int *r_offset, - unsigned int dir) + unsigned int dir, + unsigned int data_type) { int bpp_value = bpp(format); int ret = -1; @@ -1179,12 +1231,19 @@ static int build_ge2d_config_ex_dma(struct config_planes_ion_s *plane, index &= 0xff; if (plane) { if (plane[0].shared_fd) { - struct aml_dma_cfg cfg; + struct ge2d_dma_cfg_s *cfg = NULL; + struct aml_dma_cfg *dma_cfg = NULL; - cfg.fd = plane[0].shared_fd; - cfg.dev = &(ge2d_manager.pdev->dev); - cfg.dir = dir; - ret = ge2d_dma_buffer_get_phys(&cfg, &addr); + cfg = ge2d_wq_get_dma_cfg(context, data_type); + if (!cfg) + return -1; + cfg->dma_used = 1; + dma_cfg = kzalloc(sizeof(*dma_cfg), GFP_KERNEL); + dma_cfg->fd = plane[0].shared_fd; + dma_cfg->dev = &(ge2d_manager.pdev->dev); + dma_cfg->dir = dir; + cfg->dma_cfg = dma_cfg; + ret = ge2d_dma_buffer_get_phys(dma_cfg, &addr); ge2d_log_info("phys: addr=%lx\n", addr); if (ret != 0) return ret; @@ -2071,11 +2130,13 @@ int ge2d_context_config_ex_mem(struct ge2d_context_s *context, } else if (ge2d_config_mem->src1_mem_alloc_type == AML_GE2D_MEM_DMABUF) { if (build_ge2d_addr_config_dma( + context, &ge2d_config->src_planes[0], ge2d_config->src_para.format, &src_addr, &src_stride, - DMA_TO_DEVICE) < 0) + DMA_TO_DEVICE, + AML_GE2D_SRC) < 0) return -1; ge2d_log_dbg("ge2d dma alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", src_addr, @@ -2099,13 +2160,15 @@ int ge2d_context_config_ex_mem(struct ge2d_context_s *context, } else if (ge2d_config_mem->src1_mem_alloc_type == AML_GE2D_MEM_DMABUF) { if (build_ge2d_config_ex_dma( + context, &ge2d_config->src_planes[0], ge2d_config->src_para.format, &index, ALLOC_CANVAS_INDEX + alloc_canvas_offset, &alloc_canvas_offset, - DMA_TO_DEVICE) < 0) + DMA_TO_DEVICE, + AML_GE2D_SRC) < 0) return -1; ge2d_config->src_para.canvas_index = index; ge2d_log_dbg("ge2d dma alloc canvas index:0x%x, format:0x%x\n", @@ -2180,11 +2243,13 @@ int ge2d_context_config_ex_mem(struct ge2d_context_s *context, } else if (ge2d_config_mem->src2_mem_alloc_type == AML_GE2D_MEM_DMABUF) { if (build_ge2d_addr_config_dma( + context, &ge2d_config->src2_planes[0], ge2d_config->src2_para.format, &src2_addr, &src2_stride, - DMA_TO_DEVICE) < 0) + DMA_TO_DEVICE, + AML_GE2D_SRC2) < 0) return -1; ge2d_log_dbg("ge2d dma alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", src2_addr, @@ -2208,13 +2273,15 @@ int ge2d_context_config_ex_mem(struct ge2d_context_s *context, } else if (ge2d_config_mem->src2_mem_alloc_type == AML_GE2D_MEM_DMABUF) { if (build_ge2d_config_ex_dma( + context, &ge2d_config->src2_planes[0], ge2d_config->src2_para.format, &index, ALLOC_CANVAS_INDEX + alloc_canvas_offset, &alloc_canvas_offset, - DMA_TO_DEVICE) < 0) + DMA_TO_DEVICE, + AML_GE2D_SRC2) < 0) return -1; ge2d_config->src2_para.canvas_index = index; ge2d_log_dbg("ge2d src2 dma alloc, canvas index:0x%x,format:0x%x\n", @@ -2292,11 +2359,13 @@ int ge2d_context_config_ex_mem(struct ge2d_context_s *context, } else if (ge2d_config_mem->dst_mem_alloc_type == AML_GE2D_MEM_DMABUF) { if (build_ge2d_addr_config_dma( + context, &ge2d_config->dst_planes[0], ge2d_config->dst_para.format, &dst_addr, &dst_stride, - DMA_FROM_DEVICE) < 0) + DMA_FROM_DEVICE, + AML_GE2D_DST) < 0) return -1; ge2d_log_dbg("ge2d dma alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", dst_addr, @@ -2320,13 +2389,15 @@ int ge2d_context_config_ex_mem(struct ge2d_context_s *context, } else if (ge2d_config_mem->dst_mem_alloc_type == AML_GE2D_MEM_DMABUF) { if (build_ge2d_config_ex_dma( + context, &ge2d_config->dst_planes[0], ge2d_config->dst_para.format, &index, ALLOC_CANVAS_INDEX + alloc_canvas_offset, &alloc_canvas_offset, - DMA_FROM_DEVICE) < 0) + DMA_FROM_DEVICE, + AML_GE2D_DST) < 0) return -1; ge2d_config->dst_para.canvas_index = index; ge2d_log_dbg("ge2d: dst dma alloc, index:0x%x, format:0x%x\n", diff --git a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c index 1ade0e4..390874a 100644 --- a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c +++ b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c @@ -552,7 +552,6 @@ int gdc_dma_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr) *addr = PFN_PHYS(page_to_pfn(page)); ret = 0; } - gdc_dma_buffer_unmap(cfg); return ret; } diff --git a/drivers/amlogic/media/gdc/app/gdc_module.c b/drivers/amlogic/media/gdc/app/gdc_module.c index e0f1dad..e698baf 100644 --- a/drivers/amlogic/media/gdc/app/gdc_module.c +++ b/drivers/amlogic/media/gdc/app/gdc_module.c @@ -520,7 +520,7 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, { long ret = -1; unsigned long addr; - struct aml_dma_cfg cfg; + struct aml_dma_cfg *cfg = NULL; struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; struct gdc_config_s *gc = &gdc_cmd->gdc_config; @@ -532,10 +532,12 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, switch (gc->format) { case NV12: if (gs_ex->input_buffer.plane_number == 1) { - cfg.fd = gs_ex->input_buffer.y_base_fd; - cfg.dev = &fh->gdev->pdev->dev; - cfg.dir = DMA_TO_DEVICE; - ret = gdc_dma_buffer_get_phys(&cfg, &addr); + cfg = &fh->dma_cfg.input_cfg_plane1; + cfg->fd = gs_ex->input_buffer.y_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_TO_DEVICE; + + ret = gdc_dma_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, "dma import input fd %d failed\n", @@ -550,10 +552,11 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, gdc_log(LOG_INFO, "1 plane get input addr=%x\n", gdc_cmd->y_base_addr); } else if (gs_ex->input_buffer.plane_number == 2) { - cfg.fd = gs_ex->input_buffer.y_base_fd; - cfg.dev = &fh->gdev->pdev->dev; - cfg.dir = DMA_TO_DEVICE; - ret = gdc_dma_buffer_get_phys(&cfg, &addr); + cfg = &fh->dma_cfg.input_cfg_plane1; + cfg->fd = gs_ex->input_buffer.y_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, "dma import input fd %d failed\n", @@ -561,11 +564,11 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, return -EINVAL; } gdc_cmd->y_base_addr = addr; - - cfg.fd = gs_ex->input_buffer.uv_base_fd; - cfg.dev = &fh->gdev->pdev->dev; - cfg.dir = DMA_TO_DEVICE; - ret = gdc_dma_buffer_get_phys(&cfg, &addr); + cfg = &fh->dma_cfg.input_cfg_plane2; + cfg->fd = gs_ex->input_buffer.uv_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, "dma import input fd %d failed\n", @@ -580,10 +583,11 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, } break; case Y_GREY: - cfg.fd = gs_ex->input_buffer.y_base_fd; - cfg.dev = &(fh->gdev->pdev->dev); - cfg.dir = DMA_TO_DEVICE; - ret = gdc_dma_buffer_get_phys(&cfg, &addr); + cfg = &fh->dma_cfg.input_cfg_plane1; + cfg->fd = gs_ex->input_buffer.y_base_fd; + cfg->dev = &(fh->gdev->pdev->dev); + cfg->dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, "dma import input fd %d failed\n", @@ -606,7 +610,7 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, long ret; unsigned long addr = 0; size_t len; - struct aml_dma_cfg cfg; + struct aml_dma_cfg *cfg = NULL; struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; if (fh == NULL || gs_ex == NULL) { @@ -628,10 +632,11 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, } } else if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { /* dma alloc */ - cfg.fd = gs_ex->output_buffer.y_base_fd; - cfg.dev = &(gdc_manager.gdc_dev->pdev->dev); - cfg.dir = DMA_FROM_DEVICE; - ret = gdc_dma_buffer_get_phys(&cfg, &addr); + cfg = &fh->dma_cfg.output_cfg; + cfg->fd = gs_ex->output_buffer.y_base_fd; + cfg->dev = &(gdc_manager.gdc_dev->pdev->dev); + cfg->dir = DMA_FROM_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, "dma import out fd %d failed\n", gs_ex->output_buffer.y_base_fd); @@ -655,10 +660,11 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, } } else if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { /* dma alloc */ - cfg.fd = gs_ex->config_buffer.y_base_fd; - cfg.dev = &(gdc_manager.gdc_dev->pdev->dev); - cfg.dir = DMA_TO_DEVICE; - ret = gdc_dma_buffer_get_phys(&cfg, &addr); + cfg = &fh->dma_cfg.config_cfg; + cfg->fd = gs_ex->config_buffer.y_base_fd; + cfg->dev = &(gdc_manager.gdc_dev->pdev->dev); + cfg->dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, "dma import config fd %d failed\n", gs_ex->config_buffer.shared_fd); @@ -690,10 +696,10 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, gdc_log(LOG_INFO, "%s, input addr=%x\n", __func__, fh->gdc_cmd.y_base_addr); mutex_lock(&fh->gdev->d_mutext); - #if 1 + if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) gdc_buffer_dma_flush(gs_ex->config_buffer.shared_fd); - #endif + ret = gdc_run(gdc_cmd); if (ret < 0) gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); @@ -704,11 +710,20 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, gdc_log(LOG_ERR, "gdc timeout\n"); gdc_stop(gdc_cmd); + mutex_unlock(&fh->gdev->d_mutext); #if 0 if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) gdc_buffer_cache_flush(gs_ex->output_buffer.shared_fd); #endif - mutex_unlock(&fh->gdev->d_mutext); + if (gs_ex->input_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { + gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane1); + if (gs_ex->input_buffer.plane_number == 2) + gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane2); + } + if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) + gdc_dma_buffer_unmap(&fh->dma_cfg.config_cfg); + if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) + gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg); return 0; } diff --git a/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h b/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h index 9cab803..dbf7300 100644 --- a/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h +++ b/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h @@ -25,7 +25,7 @@ #include #include "system_gdc_io.h" #include "gdc_api.h" - +#include "gdc_dmabuf.h" struct gdc_cmd_s; struct gdc_manager_s { @@ -45,6 +45,13 @@ struct meson_gdc_dev_t { struct miscdevice misc_dev; }; +struct gdc_dma_cfg_t { + struct aml_dma_cfg input_cfg_plane1; + struct aml_dma_cfg input_cfg_plane2; + struct aml_dma_cfg config_cfg; + struct aml_dma_cfg output_cfg; +}; + struct mgdc_fh_s { struct list_head list; wait_queue_head_t irq_queue; @@ -64,6 +71,7 @@ struct mgdc_fh_s { unsigned long c_len; struct gdc_dma_cfg y_dma_cfg; struct gdc_dma_cfg uv_dma_cfg; + struct gdc_dma_cfg_t dma_cfg; }; irqreturn_t interrupt_handler_next(int irq, void *param); diff --git a/include/linux/amlogic/media/ge2d/ge2d.h b/include/linux/amlogic/media/ge2d/ge2d.h index 92e541e..c6fa127 100644 --- a/include/linux/amlogic/media/ge2d/ge2d.h +++ b/include/linux/amlogic/media/ge2d/ge2d.h @@ -616,6 +616,11 @@ struct ge2d_cmd_s { unsigned char hang_flag; }; +struct ge2d_dma_cfg_s { + int dma_used; + void *dma_cfg; +}; + struct ge2d_config_s { struct ge2d_gen_s gen; struct ge2d_src1_data_s src1_data; @@ -626,6 +631,9 @@ struct ge2d_config_s { unsigned int v_scale_coef_type; unsigned int h_scale_coef_type; unsigned int update_flag; + struct ge2d_dma_cfg_s src_dma_cfg; + struct ge2d_dma_cfg_s src2_dma_cfg; + struct ge2d_dma_cfg_s dst_dma_cfg; }; struct ge2d_dma_buf_s { @@ -634,6 +642,13 @@ struct ge2d_dma_buf_s { int len; }; +enum ge2d_data_type_e { + AML_GE2D_SRC, + AML_GE2D_SRC2, + AML_GE2D_DST, + AML_GE2D_TYPE_INVALID, +}; + enum ge2d_src_dst_e { OSD0_OSD0 = 0, OSD0_OSD1, -- 2.7.4