video: driver: add error state support for core
Introduced MSM_VIDC_CORE_ERROR state in core. It supports CPU_WATCHDOG and VIDEO_UNRESPONSIVE core substates. Change-Id: I6aa700c37782d64d64cd132ea13009dda22cc8d1 Signed-off-by: Govindaraj Rajagopal <quic_grajagop@quicinc.com>
This commit is contained in:
@@ -21,6 +21,7 @@ struct msm_vidc_core;
|
|||||||
CORE_STATE(CORE_DEINIT) \
|
CORE_STATE(CORE_DEINIT) \
|
||||||
CORE_STATE(CORE_INIT_WAIT) \
|
CORE_STATE(CORE_INIT_WAIT) \
|
||||||
CORE_STATE(CORE_INIT) \
|
CORE_STATE(CORE_INIT) \
|
||||||
|
CORE_STATE(CORE_ERROR) \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define call_venus_op(d, op, ...) \
|
#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)
|
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_
|
#endif // _MSM_VIDC_CORE_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(struct msm_vidc_core *core);
|
||||||
int msm_vidc_core_init_wait(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(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_inst_timeout(struct msm_vidc_inst *inst);
|
||||||
int msm_vidc_print_buffer_info(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);
|
int msm_vidc_print_inst_info(struct msm_vidc_inst *inst);
|
||||||
|
@@ -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,
|
int msm_vidc_change_core_state(struct msm_vidc_core *core,
|
||||||
enum msm_vidc_core_state request_state, const char *func)
|
enum msm_vidc_core_state request_state, const char *func)
|
||||||
{
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
if (!core) {
|
if (!core) {
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
d_vpr_e("%s: invalid params\n", __func__);
|
||||||
return -EINVAL;
|
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",
|
d_vpr_h("%s: core state changed to %s from %s\n",
|
||||||
func, core_state_name(request_state),
|
func, core_state_name(request_state),
|
||||||
core_state_name(core->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)) {
|
if (is_core_state(core, MSM_VIDC_CORE_INIT)) {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
goto unlock;
|
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;
|
rc = -EINVAL;
|
||||||
goto unlock;
|
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__);
|
d_vpr_h("%s: sys init successful\n", __func__);
|
||||||
rc = 0;
|
rc = 0;
|
||||||
goto unlock;
|
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",
|
d_vpr_h("%s: sys init wait timedout. state %s\n",
|
||||||
__func__, core_state_name(core->state));
|
__func__, core_state_name(core->state));
|
||||||
|
msm_vidc_change_core_state(core, MSM_VIDC_CORE_ERROR, __func__);
|
||||||
/* mark video hw unresponsive */
|
/* mark video hw unresponsive */
|
||||||
msm_vidc_change_core_sub_state(core,
|
msm_vidc_change_core_sub_state(core,
|
||||||
0, CORE_SUBSTATE_VIDEO_UNRESPONSIVE, __func__);
|
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;
|
rc = -EINVAL;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
unlock:
|
unlock:
|
||||||
if (rc)
|
|
||||||
msm_vidc_core_deinit_locked(core, true);
|
|
||||||
core_unlock(core, __func__);
|
core_unlock(core, __func__);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -4830,9 +4848,14 @@ int msm_vidc_core_init(struct msm_vidc_core *core)
|
|||||||
}
|
}
|
||||||
|
|
||||||
core_lock(core, __func__);
|
core_lock(core, __func__);
|
||||||
if (is_core_state(core, MSM_VIDC_CORE_INIT) ||
|
if (core_in_valid_state(core)) {
|
||||||
is_core_state(core, MSM_VIDC_CORE_INIT_WAIT))
|
|
||||||
goto unlock;
|
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__);
|
msm_vidc_change_core_state(core, MSM_VIDC_CORE_INIT_WAIT, __func__);
|
||||||
/* clear PM suspend from core sub_state */
|
/* 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);
|
rc = venus_hfi_core_init(core);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
msm_vidc_change_core_state(core, MSM_VIDC_CORE_ERROR, __func__);
|
||||||
d_vpr_e("%s: core init failed\n", __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;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
if (rc)
|
|
||||||
msm_vidc_core_deinit_locked(core, true);
|
|
||||||
core_unlock(core, __func__);
|
core_unlock(core, __func__);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -4885,6 +4909,7 @@ int msm_vidc_inst_timeout(struct msm_vidc_inst *inst)
|
|||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
/* mark video hw unresponsive */
|
/* mark video hw unresponsive */
|
||||||
|
msm_vidc_change_core_state(core, MSM_VIDC_CORE_ERROR, __func__);
|
||||||
msm_vidc_change_core_sub_state(core,
|
msm_vidc_change_core_sub_state(core,
|
||||||
0, CORE_SUBSTATE_VIDEO_UNRESPONSIVE, __func__);
|
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);
|
d_vpr_e(FMT_STRING_FAULT_HANDLER, __func__, iova);
|
||||||
|
|
||||||
/* mark smmu fault as handled */
|
/* mark smmu fault as handled */
|
||||||
|
core_lock(core, __func__);
|
||||||
msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_PAGE_FAULT, __func__);
|
msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_PAGE_FAULT, __func__);
|
||||||
|
core_unlock(core, __func__);
|
||||||
|
|
||||||
/* print noc error log registers */
|
/* print noc error log registers */
|
||||||
venus_hfi_noc_error_info(core);
|
venus_hfi_noc_error_info(core);
|
||||||
|
@@ -750,10 +750,13 @@ static int __response_handler(struct msm_vidc_core *core)
|
|||||||
if (call_venus_op(core, watchdog, core, core->intr_status)) {
|
if (call_venus_op(core, watchdog, core, core->intr_status)) {
|
||||||
struct hfi_packet pkt = {.type = HFI_SYS_ERROR_WD_TIMEOUT};
|
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 */
|
/* mark cpu watchdog error */
|
||||||
msm_vidc_change_core_sub_state(core,
|
msm_vidc_change_core_sub_state(core,
|
||||||
0, CORE_SUBSTATE_CPU_WATCHDOG, __func__);
|
0, CORE_SUBSTATE_CPU_WATCHDOG, __func__);
|
||||||
d_vpr_e("%s: CPU WD error received\n", __func__);
|
d_vpr_e("%s: CPU WD error received\n", __func__);
|
||||||
|
core_unlock(core, __func__);
|
||||||
|
|
||||||
return handle_system_error(core, &pkt);
|
return handle_system_error(core, &pkt);
|
||||||
}
|
}
|
||||||
@@ -822,6 +825,7 @@ void venus_hfi_pm_work_handler(struct work_struct *work)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core_lock(core, __func__);
|
||||||
d_vpr_h("%s: try power collapse\n", __func__);
|
d_vpr_h("%s: try power collapse\n", __func__);
|
||||||
/*
|
/*
|
||||||
* It is ok to check this variable outside the lock since
|
* 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",
|
d_vpr_e("Failed to PC for %d times\n",
|
||||||
core->skip_pc_count);
|
core->skip_pc_count);
|
||||||
core->skip_pc_count = 0;
|
core->skip_pc_count = 0;
|
||||||
|
msm_vidc_change_core_state(core, MSM_VIDC_CORE_ERROR, __func__);
|
||||||
/* mark video hw unresponsive */
|
/* mark video hw unresponsive */
|
||||||
msm_vidc_change_core_sub_state(core,
|
msm_vidc_change_core_sub_state(core,
|
||||||
0, CORE_SUBSTATE_VIDEO_UNRESPONSIVE, __func__);
|
0, CORE_SUBSTATE_VIDEO_UNRESPONSIVE, __func__);
|
||||||
msm_vidc_core_deinit(core, true);
|
/* do core deinit to handle error */
|
||||||
return;
|
msm_vidc_core_deinit_locked(core, true);
|
||||||
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
core_lock(core, __func__);
|
|
||||||
/* core already deinited - skip power collapse */
|
/* core already deinited - skip power collapse */
|
||||||
if (is_core_state(core, MSM_VIDC_CORE_DEINIT)) {
|
if (is_core_state(core, MSM_VIDC_CORE_DEINIT)) {
|
||||||
d_vpr_e("%s: invalid core state %s\n",
|
d_vpr_e("%s: invalid core state %s\n",
|
||||||
|
Reference in New Issue
Block a user