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 <yong.qin@amlogic.com>
This commit is contained in:
Yong Qin
2019-03-06 18:51:42 +08:00
committed by Jianxin Pan
parent bdee9fadcb
commit edc1970398

View File

@@ -129,7 +129,7 @@ static di_dev_t *de_devp;
static dev_t di_devno; static dev_t di_devno;
static struct class *di_clsp; 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_state = 1;
static int bypass_all; 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_hold_line = 8; /*2019-01-10: from VLSI feijun from 17 to 8*/
static int post_urgent = 1; static int post_urgent = 1;
static struct mutex di_event_mutex;
/*pre process speed debug */ /*pre process speed debug */
static int pre_process_time; static int pre_process_time;
static int di_receiver_event_fun(int type, void *data, void *arg); 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; bool bit10_pack_patch = false;
unsigned int width_roundup = 2; 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; return 0;
}
if ((list_count(QUEUE_IN_FREE) < 2 && (!di_pre_stru.di_inp_buf_next)) || if ((list_count(QUEUE_IN_FREE) < 2 && (!di_pre_stru.di_inp_buf_next)) ||
(queue_empty(QUEUE_LOCAL_FREE))) (queue_empty(QUEUE_LOCAL_FREE)))
return 0; return 0;
@@ -5984,6 +5992,8 @@ static void di_unreg_process_irq(void)
ulong flags = 0; ulong flags = 0;
spin_lock_irqsave(&plist_lock, flags); spin_lock_irqsave(&plist_lock, flags);
#endif #endif
pr_info("DI: %s S\n", __func__);
init_flag = 0; init_flag = 0;
mirror_disable = get_blackout_policy(); mirror_disable = get_blackout_policy();
di_lock_irqfiq_save(irq_flag2); di_lock_irqfiq_save(irq_flag2);
@@ -6048,6 +6058,7 @@ static void di_unreg_process_irq(void)
up(&di_sema); up(&di_sema);
} }
#endif #endif
pr_info("DI: %s E\n", __func__);
} }
static void di_reg_process(void) 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) if (pre_run_flag == DI_RUN_FLAG_STEP)
pre_run_flag = DI_RUN_FLAG_STEP_DONE; pre_run_flag = DI_RUN_FLAG_STEP_DONE;
vframe = vf_peek(VFM_NAME); vframe = vf_peek(VFM_NAME);
if (vframe) { 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++) { 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(); di_process();
} }
log_buffer_state("pro"); log_buffer_state("pro");
@@ -6629,19 +6642,45 @@ static int di_receiver_event_fun(int type, void *data, void *arg)
{ {
int i; int i;
ulong flags; ulong flags;
char *provider_name = (char *)data;
u32 sts = 0;
if (type == VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR) { if (type == VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR) {
sts = di_pre_stru.vdin2nr;
return di_pre_stru.vdin2nr; return di_pre_stru.vdin2nr;
} else if (type == VFRAME_EVENT_PROVIDER_UNREG) { } 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", pr_dbg("%s , is_bypass() %d trick_mode %d bypass_all %d\n",
__func__, is_bypass(NULL), trick_mode, bypass_all); __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);
di_pre_stru.unreg_req_flag = 1; 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; 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;
trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_UNREG); trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_UNREG);
/*check unreg process*/
di_pre_stru.unreg_req_flag_cnt = 0; di_pre_stru.unreg_req_flag_cnt = 0;
while (di_pre_stru.unreg_req_flag) { while (di_pre_stru.unreg_req_flag) {
/*waitting di_unreg_process_irq finish*/
usleep_range(10000, 10001); usleep_range(10000, 10001);
if (di_pre_stru.unreg_req_flag_cnt++ > if (di_pre_stru.unreg_req_flag_cnt++ >
di_reg_unreg_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) if (di_pre_stru.vdin_source)
DI_Wr_reg_bits(VDIN_WR_CTRL, 0x3, 24, 3); DI_Wr_reg_bits(VDIN_WR_CTRL, 0x3, 24, 3);
#endif #endif
mutex_unlock(&di_event_mutex);
pr_info("DI:ureg f\n");
} else if (type == VFRAME_EVENT_PROVIDER_RESET) { } else if (type == VFRAME_EVENT_PROVIDER_RESET) {
di_blocking = 1; 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) if (is_bypass(NULL)
|| bypass_state || bypass_state
|| di_pre_stru.bypass_flag) { || 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) { } else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) {
di_blocking = 1; 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: light_unreg:
spin_lock_irqsave(&plist_lock, flags); spin_lock_irqsave(&plist_lock, flags);
@@ -6701,7 +6742,7 @@ light_unreg:
} else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME) { } else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME) {
unsigned char vf_put_flag = 0; unsigned char vf_put_flag = 0;
pr_dbg( pr_info(
"%s:VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME\n", "%s:VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME\n",
__func__); __func__);
/* /*
@@ -6829,29 +6870,52 @@ light_unreg:
} }
#endif #endif
} else if (type == VFRAME_EVENT_PROVIDER_REG) { } else if (type == VFRAME_EVENT_PROVIDER_REG) {
char *provider_name = (char *)data; /*char *provider_name = (char *)data;*/
char *receiver_name = NULL; char *receiver_name = NULL;
mutex_lock(&di_event_mutex);
if (de_devp->flags & DI_SUSPEND_FLAG) { if (de_devp->flags & DI_SUSPEND_FLAG) {
pr_err("[DI] reg event device hasn't resumed\n"); pr_err("[DI] reg event device hasn't resumed\n");
mutex_unlock(&di_event_mutex);
return -1; return -1;
} }
if (reg_flag) { if (reg_flag) {
pr_err("[DI] no muti instance.\n"); pr_err("[DI] no muti instance.\n");
mutex_unlock(&di_event_mutex);
return -1; return -1;
} }
pr_info("%s: vframe provider reg %s\n", __func__, pr_info("DI: %s: reg\n", __func__);
provider_name); pr_info("DI: provider name:%s\n", provider_name);
bypass_state = 0; 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); 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; di_pre_stru.reg_req_flag_cnt = 0;
while (di_pre_stru.reg_req_flag) { while (di_pre_stru.reg_req_flag) {
usleep_range(10000, 10001); usleep_range(10000, 10001);
if (di_pre_stru.reg_req_flag_cnt++ > di_reg_unreg_cnt) { if (di_pre_stru.reg_req_flag_cnt++ > di_reg_unreg_cnt) {
reg_unreg_timeout_cnt++; reg_unreg_timeout_cnt++;
pr_dbg("%s:reg_req_flag timeout!!!\n", pr_err("%s:reg_req_flag timeout!!!\n",
__func__); __func__);
break; break;
} }
@@ -6876,6 +6940,8 @@ light_unreg:
} else { } else {
pr_info("%s error receiver is null.\n", __func__); pr_info("%s error receiver is null.\n", __func__);
} }
mutex_unlock(&di_event_mutex);
pr_info("DI:reg f\n");
} }
#ifdef DET3D #ifdef DET3D
else if (type == VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE) { else if (type == VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE) {
@@ -6892,9 +6958,9 @@ light_unreg:
VFRAME_EVENT_PROVIDER_FR_END_HINT, data); VFRAME_EVENT_PROVIDER_FR_END_HINT, data);
} }
return 0; return sts;
} }
#if 0
static void fast_process(void) static void fast_process(void)
{ {
int i; int i;
@@ -6951,6 +7017,7 @@ static void fast_process(void)
} }
} }
} }
#endif
static vframe_t *di_vf_peek(void *arg) static vframe_t *di_vf_peek(void *arg)
{ {
@@ -6969,7 +7036,7 @@ static vframe_t *di_vf_peek(void *arg)
log_buffer_state("pek"); log_buffer_state("pek");
fast_process(); /*fast_process(); qy temp */
#ifdef SUPPORT_START_FRAME_HOLD #ifdef SUPPORT_START_FRAME_HOLD
if ((disp_frame_count == 0) && (is_bypass(NULL) == 0)) { if ((disp_frame_count == 0) && (is_bypass(NULL) == 0)) {
int ready_count = list_count(QUEUE_POST_READY); 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); device_create_file(di_devp->dev, &dev_attr_tvp_region);
pd_device_files_add(di_devp->dev); pd_device_files_add(di_devp->dev);
nr_drv_init(di_devp->dev); nr_drv_init(di_devp->dev);
mutex_init(&di_event_mutex);
init_flag = 0; init_flag = 0;
reg_flag = 0; reg_flag = 0;