diff --git a/driver/vidc/inc/msm_vidc_core.h b/driver/vidc/inc/msm_vidc_core.h index e4c3e826ac..d4b9547a13 100644 --- a/driver/vidc/inc/msm_vidc_core.h +++ b/driver/vidc/inc/msm_vidc_core.h @@ -21,6 +21,7 @@ struct msm_vidc_core; CORE_STATE(CORE_DEINIT) \ CORE_STATE(CORE_INIT_WAIT) \ CORE_STATE(CORE_INIT) \ + CORE_STATE(CORE_ERROR) \ } #define call_venus_op(d, op, ...) \ @@ -133,7 +134,8 @@ struct msm_vidc_core { static inline bool core_in_valid_state(struct msm_vidc_core *core) { - return core->state != MSM_VIDC_CORE_DEINIT; + return (core->state == MSM_VIDC_CORE_INIT || + core->state == MSM_VIDC_CORE_INIT_WAIT); } #endif // _MSM_VIDC_CORE_H_ diff --git a/driver/vidc/inc/msm_vidc_driver.h b/driver/vidc/inc/msm_vidc_driver.h index 83c2bcdc1b..6861703771 100644 --- a/driver/vidc/inc/msm_vidc_driver.h +++ b/driver/vidc/inc/msm_vidc_driver.h @@ -451,6 +451,7 @@ int msm_vidc_change_core_sub_state(struct msm_vidc_core *core, int msm_vidc_core_init(struct msm_vidc_core *core); int msm_vidc_core_init_wait(struct msm_vidc_core *core); int msm_vidc_core_deinit(struct msm_vidc_core *core, bool force); +int msm_vidc_core_deinit_locked(struct msm_vidc_core *core, bool force); int msm_vidc_inst_timeout(struct msm_vidc_inst *inst); int msm_vidc_print_buffer_info(struct msm_vidc_inst *inst); int msm_vidc_print_inst_info(struct msm_vidc_inst *inst); diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index def57702a8..7843422f28 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -1032,11 +1032,20 @@ int signal_session_msg_receipt(struct msm_vidc_inst *inst, int msm_vidc_change_core_state(struct msm_vidc_core *core, enum msm_vidc_core_state request_state, const char *func) { + int rc = 0; + if (!core) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } + /* core must be locked */ + rc = __strict_check(core, func); + if (rc) { + d_vpr_e("%s(): core was not locked\n", func); + return rc; + } + d_vpr_h("%s: core state changed to %s from %s\n", func, core_state_name(request_state), core_state_name(core->state)); @@ -4781,7 +4790,10 @@ int msm_vidc_core_init_wait(struct msm_vidc_core *core) if (is_core_state(core, MSM_VIDC_CORE_INIT)) { rc = 0; goto unlock; - } else if (is_core_state(core, MSM_VIDC_CORE_DEINIT)) { + } else if (is_core_state(core, MSM_VIDC_CORE_DEINIT) || + is_core_state(core, MSM_VIDC_CORE_ERROR)) { + d_vpr_e("%s: invalid core state %s\n", + __func__, core_state_name(core->state)); rc = -EINVAL; goto unlock; } @@ -4804,18 +4816,24 @@ int msm_vidc_core_init_wait(struct msm_vidc_core *core) d_vpr_h("%s: sys init successful\n", __func__); rc = 0; goto unlock; - } else { + } else if (is_core_state(core, MSM_VIDC_CORE_INIT_WAIT)) { d_vpr_h("%s: sys init wait timedout. state %s\n", __func__, core_state_name(core->state)); + msm_vidc_change_core_state(core, MSM_VIDC_CORE_ERROR, __func__); /* mark video hw unresponsive */ msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_VIDEO_UNRESPONSIVE, __func__); + /* core deinit to handle error */ + msm_vidc_core_deinit_locked(core, true); + rc = -EINVAL; + goto unlock; + } else { + d_vpr_e("%s: invalid core state %s\n", + __func__, core_state_name(core->state)); rc = -EINVAL; goto unlock; } unlock: - if (rc) - msm_vidc_core_deinit_locked(core, true); core_unlock(core, __func__); return rc; } @@ -4830,9 +4848,14 @@ int msm_vidc_core_init(struct msm_vidc_core *core) } core_lock(core, __func__); - if (is_core_state(core, MSM_VIDC_CORE_INIT) || - is_core_state(core, MSM_VIDC_CORE_INIT_WAIT)) + if (core_in_valid_state(core)) { goto unlock; + } else if (is_core_state(core, MSM_VIDC_CORE_ERROR)) { + d_vpr_e("%s: invalid core state %s\n", + __func__, core_state_name(core->state)); + rc = -EINVAL; + goto unlock; + } msm_vidc_change_core_state(core, MSM_VIDC_CORE_INIT_WAIT, __func__); /* clear PM suspend from core sub_state */ @@ -4841,13 +4864,14 @@ int msm_vidc_core_init(struct msm_vidc_core *core) rc = venus_hfi_core_init(core); if (rc) { + msm_vidc_change_core_state(core, MSM_VIDC_CORE_ERROR, __func__); d_vpr_e("%s: core init failed\n", __func__); + /* do core deinit to handle error */ + msm_vidc_core_deinit_locked(core, true); goto unlock; } unlock: - if (rc) - msm_vidc_core_deinit_locked(core, true); core_unlock(core, __func__); return rc; } @@ -4885,6 +4909,7 @@ int msm_vidc_inst_timeout(struct msm_vidc_inst *inst) goto unlock; } /* mark video hw unresponsive */ + msm_vidc_change_core_state(core, MSM_VIDC_CORE_ERROR, __func__); msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_VIDEO_UNRESPONSIVE, __func__); @@ -5038,7 +5063,9 @@ int msm_vidc_smmu_fault_handler(struct iommu_domain *domain, d_vpr_e(FMT_STRING_FAULT_HANDLER, __func__, iova); /* mark smmu fault as handled */ + core_lock(core, __func__); msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_PAGE_FAULT, __func__); + core_unlock(core, __func__); /* print noc error log registers */ venus_hfi_noc_error_info(core); diff --git a/driver/vidc/src/venus_hfi.c b/driver/vidc/src/venus_hfi.c index c151eadefb..6c4e53423f 100644 --- a/driver/vidc/src/venus_hfi.c +++ b/driver/vidc/src/venus_hfi.c @@ -750,10 +750,13 @@ static int __response_handler(struct msm_vidc_core *core) if (call_venus_op(core, watchdog, core, core->intr_status)) { struct hfi_packet pkt = {.type = HFI_SYS_ERROR_WD_TIMEOUT}; + core_lock(core, __func__); + msm_vidc_change_core_state(core, MSM_VIDC_CORE_ERROR, __func__); /* mark cpu watchdog error */ msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_CPU_WATCHDOG, __func__); d_vpr_e("%s: CPU WD error received\n", __func__); + core_unlock(core, __func__); return handle_system_error(core, &pkt); } @@ -822,6 +825,7 @@ void venus_hfi_pm_work_handler(struct work_struct *work) return; } + core_lock(core, __func__); d_vpr_h("%s: try power collapse\n", __func__); /* * It is ok to check this variable outside the lock since @@ -831,14 +835,15 @@ void venus_hfi_pm_work_handler(struct work_struct *work) d_vpr_e("Failed to PC for %d times\n", core->skip_pc_count); core->skip_pc_count = 0; + msm_vidc_change_core_state(core, MSM_VIDC_CORE_ERROR, __func__); /* mark video hw unresponsive */ msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_VIDEO_UNRESPONSIVE, __func__); - msm_vidc_core_deinit(core, true); - return; + /* do core deinit to handle error */ + msm_vidc_core_deinit_locked(core, true); + goto unlock; } - core_lock(core, __func__); /* core already deinited - skip power collapse */ if (is_core_state(core, MSM_VIDC_CORE_DEINIT)) { d_vpr_e("%s: invalid core state %s\n",