From edc197039887da2a9ea7c48e447e7113a7a3b8d3 Mon Sep 17 00:00:00 2001 From: Yong Qin Date: Wed, 6 Mar 2019 18:51:42 +0800 Subject: [PATCH] di: pretect reg unreg flow [1/1] 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 --- drivers/amlogic/media/deinterlace/deinterlace.c | 102 ++++++++++++++++++++---- 1 file changed, 85 insertions(+), 17 deletions(-) diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index aefef18..9aa429d 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -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; -- 2.7.4