di: pretect reg unreg flow [1/1]
authorYong Qin <yong.qin@amlogic.com>
Wed, 6 Mar 2019 10:51:42 +0000 (18:51 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Fri, 15 Mar 2019 10:50:43 +0000 (02:50 -0800)
PD#SWPL-4918

Problem:
when reg unreg event called too fast, di cause system crash

Solution:
pretect reg and unreg flow

Verify:
tl1

Change-Id: I9b3e28c2b0b709d4f53f60b1f044a390933117ce
Signed-off-by: Yong Qin <yong.qin@amlogic.com>
drivers/amlogic/media/deinterlace/deinterlace.c

index aefef18..9aa429d 100644 (file)
@@ -129,7 +129,7 @@ static di_dev_t *de_devp;
 static dev_t di_devno;
 static struct class *di_clsp;
 
-static const char version_s[] = "2019-03-14a";
+static const char version_s[] = "2019-03-14b";
 
 static int bypass_state = 1;
 static int bypass_all;
@@ -266,6 +266,8 @@ static long same_field_bot_count;
 static int post_hold_line = 8; /*2019-01-10: from VLSI feijun from 17 to 8*/
 static int post_urgent = 1;
 
+static struct mutex di_event_mutex;
+
 /*pre process speed debug */
 static int pre_process_time;
 static int di_receiver_event_fun(int type, void *data, void *arg);
@@ -3460,8 +3462,14 @@ static unsigned char pre_de_buf_config(void)
        bool bit10_pack_patch = false;
        unsigned int width_roundup = 2;
 
-       if (di_blocking || !atomic_read(&de_devp->mem_flag))
+       if (di_blocking || !atomic_read(&de_devp->mem_flag)
+               || di_pre_stru.unreg_req_flag) {
+               if (di_pre_stru.unreg_req_flag)
+                       pr_info("DI: %s fail unreg_req_flag=%d\n", __func__,
+                       di_pre_stru.unreg_req_flag);
                return 0;
+       }
+
        if ((list_count(QUEUE_IN_FREE) < 2 && (!di_pre_stru.di_inp_buf_next)) ||
            (queue_empty(QUEUE_LOCAL_FREE)))
                return 0;
@@ -5984,6 +5992,8 @@ static void di_unreg_process_irq(void)
        ulong flags = 0;
        spin_lock_irqsave(&plist_lock, flags);
 #endif
+
+       pr_info("DI: %s S\n", __func__);
        init_flag = 0;
        mirror_disable = get_blackout_policy();
        di_lock_irqfiq_save(irq_flag2);
@@ -6048,6 +6058,7 @@ static void di_unreg_process_irq(void)
                up(&di_sema);
        }
 #endif
+       pr_info("DI: %s E\n", __func__);
 }
 
 static void di_reg_process(void)
@@ -6223,7 +6234,6 @@ static void di_reg_process_irq(void)
        if (pre_run_flag == DI_RUN_FLAG_STEP)
                pre_run_flag = DI_RUN_FLAG_STEP_DONE;
 
-
        vframe = vf_peek(VFM_NAME);
 
        if (vframe) {
@@ -6596,7 +6606,10 @@ static void di_pre_process_irq(struct di_pre_stru_s *pre_stru_p)
        }
 
        for (i = 0; i < 2; i++) {
-               if (active_flag)
+               if (active_flag && (!pre_stru_p->unreg_req_flag_irq
+                       && !pre_stru_p->unreg_req_flag
+                       && !pre_stru_p->reg_req_flag_irq
+                       && !pre_stru_p->reg_req_flag))
                        di_process();
        }
        log_buffer_state("pro");
@@ -6629,19 +6642,45 @@ static int di_receiver_event_fun(int type, void *data, void *arg)
 {
        int i;
        ulong flags;
+       char *provider_name = (char *)data;
+       u32 sts = 0;
 
        if (type == VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR) {
+               sts = di_pre_stru.vdin2nr;
                return di_pre_stru.vdin2nr;
        } else if (type == VFRAME_EVENT_PROVIDER_UNREG) {
+               mutex_lock(&di_event_mutex);
+
                pr_dbg("%s , is_bypass() %d trick_mode %d bypass_all %d\n",
                        __func__, is_bypass(NULL), trick_mode, bypass_all);
-               pr_info("%s: vf_notify_receiver unreg\n", __func__);
+               pr_info("DI: %s: unreg\n", __func__);
+               pr_info("DI: provider name:%s\n", provider_name);
+
+               if (di_pre_stru.reg_req_flag ||
+                       di_pre_stru.reg_req_flag_irq)
+                       pr_info("DI: warning reg_req_flag is %d,%d\n",
+                               di_pre_stru.reg_req_flag,
+                               di_pre_stru.reg_req_flag_irq);
+               di_pre_stru.vdin_source = false;
 
+               /*check reg process, and waiting reg*/
+               di_pre_stru.unreg_req_flag_cnt = 0;
+               while (di_pre_stru.reg_req_flag ||
+                       di_pre_stru.reg_req_flag_irq) {
+                       msleep(20);
+                       if (di_pre_stru.unreg_req_flag_cnt++ >
+                               di_reg_unreg_cnt) {
+                               pr_err("DI : reg to unreg timeout!!!\n");
+                               di_reg_process();
+                               break;
+                       }
+               }
                di_pre_stru.unreg_req_flag = 1;
-               di_pre_stru.vdin_source = false;
                trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_UNREG);
+               /*check unreg process*/
                di_pre_stru.unreg_req_flag_cnt = 0;
                while (di_pre_stru.unreg_req_flag) {
+                       /*waitting di_unreg_process_irq finish*/
                        usleep_range(10000, 10001);
                        if (di_pre_stru.unreg_req_flag_cnt++ >
                                di_reg_unreg_cnt) {
@@ -6669,10 +6708,12 @@ static int di_receiver_event_fun(int type, void *data, void *arg)
                if (di_pre_stru.vdin_source)
                        DI_Wr_reg_bits(VDIN_WR_CTRL, 0x3, 24, 3);
 #endif
+               mutex_unlock(&di_event_mutex);
+               pr_info("DI:ureg f\n");
        } else if (type == VFRAME_EVENT_PROVIDER_RESET) {
                di_blocking = 1;
 
-               pr_dbg("%s: VFRAME_EVENT_PROVIDER_RESET\n", __func__);
+               pr_info("%s: VFRAME_EVENT_PROVIDER_RESET\n", __func__);
                if (is_bypass(NULL)
                        || bypass_state
                        || di_pre_stru.bypass_flag) {
@@ -6685,7 +6726,7 @@ static int di_receiver_event_fun(int type, void *data, void *arg)
        } else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) {
                di_blocking = 1;
 
-               pr_dbg("%s: vf_notify_receiver ligth unreg\n", __func__);
+               pr_info("%s: vf_notify_receiver ligth unreg\n", __func__);
 
 light_unreg:
                spin_lock_irqsave(&plist_lock, flags);
@@ -6701,7 +6742,7 @@ light_unreg:
        } else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME) {
                unsigned char vf_put_flag = 0;
 
-               pr_dbg(
+               pr_info(
                        "%s:VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME\n",
                        __func__);
 /*
@@ -6829,29 +6870,52 @@ light_unreg:
                }
 #endif
        } else if (type == VFRAME_EVENT_PROVIDER_REG) {
-               char *provider_name = (char *)data;
+               /*char *provider_name = (char *)data;*/
                char *receiver_name = NULL;
+               mutex_lock(&di_event_mutex);
+
                if (de_devp->flags & DI_SUSPEND_FLAG) {
                        pr_err("[DI] reg event device hasn't resumed\n");
+                       mutex_unlock(&di_event_mutex);
                        return -1;
                }
                if (reg_flag) {
                        pr_err("[DI] no muti instance.\n");
+                       mutex_unlock(&di_event_mutex);
                        return -1;
                }
-               pr_info("%s: vframe provider reg %s\n", __func__,
-                       provider_name);
+               pr_info("DI: %s: reg\n", __func__);
+               pr_info("DI: provider name:%s\n", provider_name);
 
                bypass_state = 0;
-               di_pre_stru.reg_req_flag = 1;
+               if (di_pre_stru.unreg_req_flag ||
+                       di_pre_stru.unreg_req_flag_irq)
+                       pr_info("DI: warning unreg_req_flag is %d,%d\n",
+                               di_pre_stru.unreg_req_flag,
+                               di_pre_stru.unreg_req_flag_irq);
 
                trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_REG);
+               /*check unreg process*/
+               di_pre_stru.reg_req_flag_cnt = 0;
+               while (di_pre_stru.unreg_req_flag ||
+                       di_pre_stru.unreg_req_flag_irq) {
+                       msleep(20);
+                       if (di_pre_stru.reg_req_flag_cnt++ > di_reg_unreg_cnt) {
+                               pr_err("%s:unreg to reg timeout!!!\n",
+                                       __func__);
+                               di_unreg_process();
+                               break;
+                       }
+               }
+
+               di_pre_stru.reg_req_flag = 1;
+               /*check reg process*/
                di_pre_stru.reg_req_flag_cnt = 0;
                while (di_pre_stru.reg_req_flag) {
                        usleep_range(10000, 10001);
                        if (di_pre_stru.reg_req_flag_cnt++ > di_reg_unreg_cnt) {
                                reg_unreg_timeout_cnt++;
-                               pr_dbg("%s:reg_req_flag timeout!!!\n",
+                               pr_err("%s:reg_req_flag timeout!!!\n",
                                        __func__);
                                break;
                        }
@@ -6876,6 +6940,8 @@ light_unreg:
                } else {
                        pr_info("%s error receiver is null.\n", __func__);
                }
+               mutex_unlock(&di_event_mutex);
+               pr_info("DI:reg f\n");
        }
 #ifdef DET3D
        else if (type == VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE) {
@@ -6892,9 +6958,9 @@ light_unreg:
                        VFRAME_EVENT_PROVIDER_FR_END_HINT, data);
        }
 
-       return 0;
+       return sts;
 }
-
+#if 0
 static void fast_process(void)
 {
        int i;
@@ -6951,6 +7017,7 @@ static void fast_process(void)
                }
        }
 }
+#endif
 
 static vframe_t *di_vf_peek(void *arg)
 {
@@ -6969,7 +7036,7 @@ static vframe_t *di_vf_peek(void *arg)
 
        log_buffer_state("pek");
 
-       fast_process();
+       /*fast_process(); qy temp */
 #ifdef SUPPORT_START_FRAME_HOLD
        if ((disp_frame_count == 0) && (is_bypass(NULL) == 0)) {
                int ready_count = list_count(QUEUE_POST_READY);
@@ -7749,6 +7816,7 @@ static int di_probe(struct platform_device *pdev)
        device_create_file(di_devp->dev, &dev_attr_tvp_region);
        pd_device_files_add(di_devp->dev);
        nr_drv_init(di_devp->dev);
+       mutex_init(&di_event_mutex);
 
        init_flag = 0;
        reg_flag = 0;