From 8860abb5e84dacf807c7130c33e9e353e5e47af0 Mon Sep 17 00:00:00 2001 From: "wenfeng.guo" Date: Tue, 20 Nov 2018 19:38:43 +0800 Subject: [PATCH] deinterlace: fix CMA layout adaptation di_cma_reserved [1/1] PD#SWPL-2308 Problem: CMA layout adaptation di_cma_reserved cause crash Solution: fix CMA layout adaptation di_cma_reserved Verify: P321 Change-Id: Ia24e811a02d47d70afa1c06361fd0852c357394c Signed-off-by: wenfeng.guo --- drivers/amlogic/media/deinterlace/deinterlace.c | 76 ++++++++++++++++++++-- drivers/amlogic/media/deinterlace/deinterlace.h | 2 + drivers/amlogic/media/deinterlace/deinterlace_hw.c | 19 +++++- drivers/amlogic/media/deinterlace/deinterlace_hw.h | 6 +- 4 files changed, 96 insertions(+), 7 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 8f167bd..a61298e 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -1243,7 +1243,61 @@ static bool is_in_queue(struct di_buf_s *di_buf, int queue_idx) } return ret; } +//--------------------------- +u8 *di_vmap(ulong addr, u32 size, bool *bflg) +{ + u8 *vaddr = NULL; + ulong phys = addr; + u32 offset = phys & ~PAGE_MASK; + u32 npages = PAGE_ALIGN(size) / PAGE_SIZE; + struct page **pages = NULL; + pgprot_t pgprot; + int i; + + if (!PageHighMem(phys_to_page(phys))) + return phys_to_virt(phys); + + if (offset) + npages++; + + pages = vmalloc(sizeof(struct page *) * npages); + if (!pages) + return NULL; + + for (i = 0; i < npages; i++) { + pages[i] = phys_to_page(phys); + phys += PAGE_SIZE; + } + + /*nocache*/ + pgprot = pgprot_writecombine(PAGE_KERNEL); + + vaddr = vmap(pages, npages, VM_MAP, pgprot); + if (!vaddr) { + pr_err("the phy(%lx) vmaped fail, size: %d\n", + addr - offset, npages << PAGE_SHIFT); + vfree(pages); + return NULL; + } + + vfree(pages); + +// if (debug_mode & 0x20) { +// di_print("[HIGH-MEM-MAP] %s, pa(%lx) to va(%p), size: %d\n", +// __func__, addr, vaddr + offset, npages << PAGE_SHIFT); +// } + *bflg = true; + return vaddr + offset; +} + +void di_unmap_phyaddr(u8 *vaddr) +{ + void *addr = (void *)(PAGE_MASK & (ulong)vaddr); + + vunmap(addr); +} +//------------------------- static ssize_t store_dump_mem(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) @@ -1260,6 +1314,7 @@ store_dump_mem(struct device *dev, struct device_attribute *attr, loff_t pos = 0; void *buff = NULL; mm_segment_t old_fs; + bool bflg_vmap = false; buf_orig = kstrdup(buf, GFP_KERNEL); ps = buf_orig; @@ -1306,10 +1361,18 @@ store_dump_mem(struct device *dev, struct device_attribute *attr, return len; } dump_state_flag = 1; - if (de_devp->flags & DI_MAP_FLAG) - buff = (void *)phys_to_virt(dump_adr); - else + if (de_devp->flags & DI_MAP_FLAG) { + //buff = (void *)phys_to_virt(dump_adr); + buff = di_vmap(dump_adr, nr_size, &bflg_vmap); + if (buff == NULL) { + pr_info("di_vap err\n"); + filp_close(filp, NULL); + return len; + + } + } else { buff = ioremap(dump_adr, nr_size); + } if (IS_ERR_OR_NULL(buff)) pr_err("%s: ioremap error.\n", __func__); vfs_write(filp, buff, nr_size, &pos); @@ -1333,6 +1396,10 @@ store_dump_mem(struct device *dev, struct device_attribute *attr, */ vfs_fsync(filp, 0); pr_info("write buffer 0x%lx to %s.\n", dump_adr, parm[1]); + if (bflg_vmap) + di_unmap_phyaddr(buff); + + if (!(de_devp->flags & DI_MAP_FLAG)) iounmap(buff); dump_state_flag = 0; @@ -4200,7 +4267,8 @@ static irqreturn_t de_irq(int irq, void *dev_instance) is_meson_txhd_cpu()) mc_pre_mv_irq(); calc_lmv_base_mcinfo((di_pre_stru.cur_height>>1), - di_pre_stru.di_wr_buf->mcinfo_adr); + di_pre_stru.di_wr_buf->mcinfo_adr, + di_pre_stru.mcinfo_size); } nr_process_in_irq(); if ((data32&0x200) && de_devp->nrds_enable) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.h b/drivers/amlogic/media/deinterlace/deinterlace.h index 0878ee3..0e38fdd 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.h +++ b/drivers/amlogic/media/deinterlace/deinterlace.h @@ -419,6 +419,8 @@ struct di_buf_s *get_di_recovery_log_di_buf(void); int get_di_video_peek_cnt(void); unsigned long get_di_reg_unreg_timeout_cnt(void); struct vframe_s **get_di_vframe_in(void); + + /*---------------------*/ struct di_buf_s *get_di_buf(int queue_idx, int *start_pos); diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index 3e2257f..cc70cdc 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -314,17 +314,29 @@ static struct mcinfo_lmv_s lines_mv[540]; static short offset_lmv = 100; module_param_named(offset_lmv, offset_lmv, short, 0644); -void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned long mcinfo_adr) +void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned long mcinfo_adr, + unsigned int mcinfo_size) { unsigned short i, top_str, bot_str, top_end, bot_end, j = 0; unsigned short *mcinfo_vadr = NULL, lck_num; unsigned short flg_m1 = 0, flg_i = 0, nLmvLckSt = 0; unsigned short lmv_lckstext[3] = {0, 0, 0}, nLmvLckEd; unsigned short lmv_lckedext[3] = {0, 0, 0}, nLmvLckNum; + bool bflg_vmap = false; + u8 *tmp; + + //mcinfo_vadr = (unsigned short *)phys_to_virt(mcinfo_adr); - mcinfo_vadr = (unsigned short *)phys_to_virt(mcinfo_adr); if (!lmv_lock_win_en) return; + + tmp = di_vmap(mcinfo_adr, mcinfo_size, &bflg_vmap); + if (tmp == NULL) { + di_print("err:di_vmap failed\n"); + return; + } + mcinfo_vadr = (unsigned short *)tmp; + for (i = 0; i < (vf_height>>1); i++) { lmvs_init(&lines_mv[i], *(mcinfo_vadr+i)); j = i + (vf_height>>1); @@ -337,6 +349,9 @@ void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned long mcinfo_adr) pr_info("\n"); } } + if (bflg_vmap) + di_unmap_phyaddr(tmp); + pr_mcinfo_cnt ? pr_mcinfo_cnt-- : (pr_mcinfo_cnt = 0); top_str = 0; top_end = offset_lmv; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.h b/drivers/amlogic/media/deinterlace/deinterlace_hw.h index b173b93..8d8b95d 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.h @@ -165,7 +165,8 @@ void enable_di_post_mif(enum gate_mode_e mode); void di_hw_uninit(void); void combing_pd22_window_config(unsigned int width, unsigned int height); void calc_lmv_init(void); -void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned long mcinfo_adr); +void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned long mcinfo_adr, + unsigned int mcinfo_size); void init_field_mode(unsigned short height); void film_mode_win_config(unsigned int width, unsigned int height); void pulldown_vof_win_config(struct pulldown_detected_s *wins); @@ -182,5 +183,8 @@ extern void afbc_reg_sw(bool on); extern void afbc_sw_trig(bool on); extern void dump_vd2_afbc(void); +extern u8 *di_vmap(ulong addr, u32 size, bool *bflg); +extern void di_unmap_phyaddr(u8 *vaddr); +extern int di_print(const char *fmt, ...); #endif -- 2.7.4