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 à :
Govindaraj Rajagopal
2021-05-10 14:19:37 +05:30
Parent 2e2fbdb7e5
révision 9a7e929dfe
3 fichiers modifiés avec 67 ajouts et 7 suppressions

Voir le fichier

@@ -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 {

Voir le fichier

@@ -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

Voir le fichier

@@ -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)