video: driver: handle race condition in msm_vidc_core_init
Core is moved to init state before completing full init sequence. So subsequent new open request assumes core is already inited and attempts to initiate a hfi_session with firmware, which is not correct and core_init is a sync cmd, so core->lock() is released, so that reverse thread can issue sys_init_done. But new session is acquiring core->lock() and corroupting core->init_done.task_list completion structure variable i.e leading to list_corruption issues. So added change to address these issues. Change-Id: I0b983a06b8ea58134ea93831246309c9ccbdf0d1 Signed-off-by: Govindaraj Rajagopal <grajagop@codeaurora.org>
Cette révision appartient à :
@@ -56,7 +56,8 @@ struct msm_vidc_core_power {
|
||||
|
||||
enum msm_vidc_core_state {
|
||||
MSM_VIDC_CORE_DEINIT = 0,
|
||||
MSM_VIDC_CORE_INIT = 1,
|
||||
MSM_VIDC_CORE_INIT_WAIT = 1,
|
||||
MSM_VIDC_CORE_INIT = 2,
|
||||
};
|
||||
|
||||
struct msm_vidc_core {
|
||||
|
@@ -280,6 +280,7 @@ struct msm_vidc_core_state_name {
|
||||
|
||||
static const struct msm_vidc_core_state_name core_state_name_arr[] = {
|
||||
{MSM_VIDC_CORE_DEINIT, "CORE_DEINIT" },
|
||||
{MSM_VIDC_CORE_INIT_WAIT, "CORE_INIT_WAIT" },
|
||||
{MSM_VIDC_CORE_INIT, "CORE_INIT" },
|
||||
};
|
||||
|
||||
@@ -3776,6 +3777,61 @@ unlock:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __fatal_error(struct msm_vidc_core *core, bool fatal)
|
||||
{
|
||||
return;
|
||||
fatal &= core->capabilities[HW_RESPONSE_TIMEOUT].value;
|
||||
MSM_VIDC_ERROR(fatal);
|
||||
}
|
||||
|
||||
static void __strict_check(struct msm_vidc_core *core)
|
||||
{
|
||||
__fatal_error(core, !mutex_is_locked(&core->lock));
|
||||
}
|
||||
|
||||
static int msm_vidc_core_init_wait(struct msm_vidc_core *core)
|
||||
{
|
||||
static const int interval = 40;
|
||||
int max_tries, count = 0, rc = 0;
|
||||
|
||||
if (!core || !core->capabilities) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
__strict_check(core);
|
||||
|
||||
if (core->state != MSM_VIDC_CORE_INIT_WAIT)
|
||||
return 0;
|
||||
|
||||
d_vpr_h("%s(): waiting for state change\n", __func__);
|
||||
max_tries = core->capabilities[HW_RESPONSE_TIMEOUT].value / interval;
|
||||
/**
|
||||
* attempt one more time to ensure triggering init_done
|
||||
* timeout sequence for 1st session, incase response not
|
||||
* received in reverse thread.
|
||||
*/
|
||||
while (count < max_tries + 1) {
|
||||
if (core->state != MSM_VIDC_CORE_INIT_WAIT)
|
||||
break;
|
||||
|
||||
core_unlock(core, __func__);
|
||||
msleep_interruptible(interval);
|
||||
core_lock(core, __func__);
|
||||
count++;
|
||||
}
|
||||
d_vpr_h("%s: state %s, interval %u, count %u, max_tries %u\n", __func__,
|
||||
core_state_name(core->state), interval, count, max_tries);
|
||||
|
||||
/* treat as fatal and fail session_open */
|
||||
if (core->state == MSM_VIDC_CORE_INIT_WAIT) {
|
||||
d_vpr_e("%s: state change failed\n", __func__);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_core_init(struct msm_vidc_core *core)
|
||||
{
|
||||
int rc = 0;
|
||||
@@ -3786,12 +3842,14 @@ int msm_vidc_core_init(struct msm_vidc_core *core)
|
||||
}
|
||||
|
||||
core_lock(core, __func__);
|
||||
if (core->state == MSM_VIDC_CORE_INIT) {
|
||||
rc = 0;
|
||||
rc = msm_vidc_core_init_wait(core);
|
||||
if (rc)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
msm_vidc_change_core_state(core, MSM_VIDC_CORE_INIT, __func__);
|
||||
if (core->state == MSM_VIDC_CORE_INIT)
|
||||
goto unlock;
|
||||
|
||||
msm_vidc_change_core_state(core, MSM_VIDC_CORE_INIT_WAIT, __func__);
|
||||
init_completion(&core->init_done);
|
||||
core->smmu_fault_handled = false;
|
||||
core->ssr.trigger = false;
|
||||
@@ -3812,6 +3870,7 @@ int msm_vidc_core_init(struct msm_vidc_core *core)
|
||||
d_vpr_e("%s: core init timed out\n", __func__);
|
||||
rc = -ETIMEDOUT;
|
||||
} else {
|
||||
msm_vidc_change_core_state(core, MSM_VIDC_CORE_INIT, __func__);
|
||||
d_vpr_h("%s: system init wait completed\n", __func__);
|
||||
rc = 0;
|
||||
}
|
||||
@@ -4015,7 +4074,7 @@ void msm_vidc_ssr_handler(struct work_struct *work)
|
||||
ssr = &core->ssr;
|
||||
|
||||
core_lock(core, __func__);
|
||||
if (core->state == MSM_VIDC_CORE_INIT) {
|
||||
if (core->state != MSM_VIDC_CORE_DEINIT) {
|
||||
/*
|
||||
* In current implementation, user-initiated SSR triggers
|
||||
* a fatal error from hardware. However, there is no way
|
||||
|
@@ -189,7 +189,7 @@ static void __strict_check(struct msm_vidc_core *core)
|
||||
|
||||
bool __core_in_valid_state(struct msm_vidc_core *core)
|
||||
{
|
||||
return core->state == MSM_VIDC_CORE_INIT;
|
||||
return core->state != MSM_VIDC_CORE_DEINIT;
|
||||
}
|
||||
|
||||
bool is_sys_cache_present(struct msm_vidc_core *core)
|
||||
|
Référencer dans un nouveau ticket
Bloquer un utilisateur