diff --git a/driver/vidc/inc/msm_vidc_core.h b/driver/vidc/inc/msm_vidc_core.h index 5b4f0bae36..55adc570d5 100644 --- a/driver/vidc/inc/msm_vidc_core.h +++ b/driver/vidc/inc/msm_vidc_core.h @@ -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 { diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index 3ab57ed49c..55606b7019 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -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 diff --git a/driver/vidc/src/venus_hfi.c b/driver/vidc/src/venus_hfi.c index 2b52fb3f39..6958d42cd1 100644 --- a/driver/vidc/src/venus_hfi.c +++ b/driver/vidc/src/venus_hfi.c @@ -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)