deinterlace: fix CMA layout adaptation di_cma_reserved [1/1]
authorwenfeng.guo <wenfeng.guo@amlogic.com>
Tue, 20 Nov 2018 11:38:43 +0000 (19:38 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Mon, 26 Nov 2018 02:15:21 +0000 (18:15 -0800)
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 <wenfeng.guo@amlogic.com>
drivers/amlogic/media/deinterlace/deinterlace.c
drivers/amlogic/media/deinterlace/deinterlace.h
drivers/amlogic/media/deinterlace/deinterlace_hw.c
drivers/amlogic/media/deinterlace/deinterlace_hw.h

index 8f167bd..a61298e 100644 (file)
@@ -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)
index 0878ee3..0e38fdd 100644 (file)
@@ -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);
index 3e2257f..cc70cdc 100644 (file)
@@ -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;
index b173b93..8d8b95d 100644 (file)
@@ -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