video: driver: add core sub_state support

Introduce core->sub_state similar to inst->sub_state.

[1] pm_suspended - moved to this substate in case of PM suspend
[2] handoff - moved to this state after successful
    handoff_regulator call.
[3] fw_power_control - moved to this state in case of IFPC.
[4] power_enable - will track core power_on/power_off status.
[5] page_fault - used to rate_limit fault logs.
[6] cpu_wd - indicates hw fired wd interrupt.
[7] video_unresponsive - moved to this state if sync cmd fails.

Change-Id: Iceb65cf404fd93aff7846860b0276307e4eab570
Signed-off-by: Govindaraj Rajagopal <quic_grajagop@quicinc.com>
This commit is contained in:
Govindaraj Rajagopal
2022-11-14 20:22:08 +05:30
parent 1addb15e58
commit 9b0140cf03
14 changed files with 293 additions and 129 deletions

View File

@@ -8,6 +8,7 @@
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include "msm_vidc_core.h" #include "msm_vidc_core.h"
#include "msm_vidc_driver.h"
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
#include "msm_vidc_variant.h" #include "msm_vidc_variant.h"
#include "msm_vidc_platform.h" #include "msm_vidc_platform.h"
@@ -44,7 +45,7 @@ int __write_register(struct msm_vidc_core *core, u32 reg, u32 value)
if (rc) if (rc)
return rc; return rc;
if (!core->power_enabled) { if (!is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE)) {
d_vpr_e("HFI Write register failed : Power is OFF\n"); d_vpr_e("HFI Write register failed : Power is OFF\n");
return -EINVAL; return -EINVAL;
} }
@@ -83,7 +84,7 @@ int __write_register_masked(struct msm_vidc_core *core, u32 reg, u32 value,
if (rc) if (rc)
return rc; return rc;
if (!core->power_enabled) { if (!is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE)) {
d_vpr_e("%s: register write failed, power is off\n", d_vpr_e("%s: register write failed, power is off\n",
__func__); __func__);
return -EINVAL; return -EINVAL;
@@ -121,7 +122,7 @@ int __read_register(struct msm_vidc_core *core, u32 reg, u32 *value)
return -EINVAL; return -EINVAL;
} }
if (!core->power_enabled) { if (!is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE)) {
d_vpr_e("HFI Read register failed : Power is OFF\n"); d_vpr_e("HFI Read register failed : Power is OFF\n");
return -EINVAL; return -EINVAL;
} }
@@ -152,7 +153,7 @@ int __read_register_with_poll_timeout(struct msm_vidc_core *core, u32 reg,
return -EINVAL; return -EINVAL;
} }
if (!core->power_enabled) { if (!is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE)) {
d_vpr_e("%s failed: Power is OFF\n", __func__); d_vpr_e("%s failed: Power is OFF\n", __func__);
return -EINVAL; return -EINVAL;
} }

View File

@@ -252,7 +252,7 @@ static int __power_off_iris2_hardware(struct msm_vidc_core *core)
int rc = 0, i; int rc = 0, i;
u32 value = 0; u32 value = 0;
if (core->hw_power_control) { if (is_core_sub_state(core, CORE_SUBSTATE_FW_PWR_CTRL)) {
d_vpr_h("%s: hardware power control enabled\n", __func__); d_vpr_h("%s: hardware power control enabled\n", __func__);
goto disable_power; goto disable_power;
} }
@@ -417,7 +417,7 @@ static int __power_off_iris2(struct msm_vidc_core *core)
return -EINVAL; return -EINVAL;
} }
if (!core->power_enabled) if (!is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE))
return 0; return 0;
/** /**
@@ -442,7 +442,7 @@ static int __power_off_iris2(struct msm_vidc_core *core)
disable_irq_nosync(core->resource->irq); disable_irq_nosync(core->resource->irq);
core->intr_status = 0; core->intr_status = 0;
core->power_enabled = false; msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE, 0, __func__);
return rc; return rc;
} }
@@ -504,9 +504,15 @@ static int __power_on_iris2(struct msm_vidc_core *core)
u32 freq = 0; u32 freq = 0;
int rc = 0; int rc = 0;
if (core->power_enabled) if (is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE))
return 0; return 0;
if (!core_in_valid_state(core)) {
d_vpr_e("%s: invalid core state %s\n",
__func__, core_state_name(core->state));
return -EINVAL;
}
/* Vote for all hardware resources */ /* Vote for all hardware resources */
rc = call_res_op(core, set_bw, core, INT_MAX, INT_MAX); rc = call_res_op(core, set_bw, core, INT_MAX, INT_MAX);
if (rc) { if (rc) {
@@ -526,7 +532,9 @@ static int __power_on_iris2(struct msm_vidc_core *core)
goto fail_power_on_hardware; goto fail_power_on_hardware;
} }
/* video controller and hardware powered on successfully */ /* video controller and hardware powered on successfully */
core->power_enabled = true; rc = msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_POWER_ENABLE, __func__);
if (rc)
goto fail_power_on_substate;
freq_tbl = core->resource->freq_set.freq_tbl; freq_tbl = core->resource->freq_set.freq_tbl;
freq = core->power.clk_freq ? core->power.clk_freq : freq = core->power.clk_freq ? core->power.clk_freq :
@@ -552,12 +560,14 @@ static int __power_on_iris2(struct msm_vidc_core *core)
return rc; return rc;
fail_power_on_substate:
__power_off_iris2_hardware(core);
fail_power_on_hardware: fail_power_on_hardware:
__power_off_iris2_controller(core); __power_off_iris2_controller(core);
fail_power_on_controller: fail_power_on_controller:
call_res_op(core, set_bw, core, 0, 0); call_res_op(core, set_bw, core, 0, 0);
fail_vote_buses: fail_vote_buses:
core->power_enabled = false; msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE, 0, __func__);
return rc; return rc;
} }

View File

@@ -277,24 +277,26 @@ static int __power_off_iris3_hardware(struct msm_vidc_core *core)
* Incase hw power control is enabled, for both CPU WD, video * Incase hw power control is enabled, for both CPU WD, video
* hw unresponsive cases, check for power status to decide on * hw unresponsive cases, check for power status to decide on
* executing NOC reset sequence before disabling power. If there * executing NOC reset sequence before disabling power. If there
* is no CPU WD and hw_power_control is enabled, fw is expected * is no CPU WD and hw power control is enabled, fw is expected
* to power collapse video hw always. * to power collapse video hw always.
*/ */
if (core->hw_power_control) { if (is_core_sub_state(core, CORE_SUBSTATE_FW_PWR_CTRL)) {
pwr_collapsed = is_iris3_hw_power_collapsed(core); pwr_collapsed = is_iris3_hw_power_collapsed(core);
if (core->cpu_watchdog || core->video_unresponsive) { if (is_core_sub_state(core, CORE_SUBSTATE_CPU_WATCHDOG) ||
is_core_sub_state(core, CORE_SUBSTATE_VIDEO_UNRESPONSIVE)) {
if (pwr_collapsed) { if (pwr_collapsed) {
d_vpr_e("%s: video hw power collapsed %d, %d\n", d_vpr_e("%s: video hw power collapsed %s\n",
__func__, core->cpu_watchdog, core->video_unresponsive); __func__, core->sub_state_name);
goto disable_power; goto disable_power;
} else { } else {
d_vpr_e("%s: video hw is power ON %d, %d\n", d_vpr_e("%s: video hw is power ON %s\n",
__func__, core->cpu_watchdog, core->video_unresponsive); __func__, core->sub_state_name);
} }
} else { } else {
if (!pwr_collapsed) if (!pwr_collapsed)
d_vpr_e("%s: video hw is not power collapsed\n", __func__); d_vpr_e("%s: video hw is not power collapsed\n", __func__);
d_vpr_h("%s: disabling hw power\n", __func__);
goto disable_power; goto disable_power;
} }
} }
@@ -465,7 +467,7 @@ static int __power_off_iris3(struct msm_vidc_core *core)
return -EINVAL; return -EINVAL;
} }
if (!core->power_enabled) if (!is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE))
return 0; return 0;
/** /**
@@ -490,7 +492,7 @@ static int __power_off_iris3(struct msm_vidc_core *core)
disable_irq_nosync(core->resource->irq); disable_irq_nosync(core->resource->irq);
core->intr_status = 0; core->intr_status = 0;
core->power_enabled = false; msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE, 0, __func__);
return rc; return rc;
} }
@@ -552,9 +554,15 @@ static int __power_on_iris3(struct msm_vidc_core *core)
u32 freq = 0; u32 freq = 0;
int rc = 0; int rc = 0;
if (core->power_enabled) if (is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE))
return 0; return 0;
if (!core_in_valid_state(core)) {
d_vpr_e("%s: invalid core state %s\n",
__func__, core_state_name(core->state));
return -EINVAL;
}
/* Vote for all hardware resources */ /* Vote for all hardware resources */
rc = call_res_op(core, set_bw, core, INT_MAX, INT_MAX); rc = call_res_op(core, set_bw, core, INT_MAX, INT_MAX);
if (rc) { if (rc) {
@@ -574,7 +582,9 @@ static int __power_on_iris3(struct msm_vidc_core *core)
goto fail_power_on_hardware; goto fail_power_on_hardware;
} }
/* video controller and hardware powered on successfully */ /* video controller and hardware powered on successfully */
core->power_enabled = true; rc = msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_POWER_ENABLE, __func__);
if (rc)
goto fail_power_on_substate;
freq_tbl = core->resource->freq_set.freq_tbl; freq_tbl = core->resource->freq_set.freq_tbl;
freq = core->power.clk_freq ? core->power.clk_freq : freq = core->power.clk_freq ? core->power.clk_freq :
@@ -597,12 +607,14 @@ static int __power_on_iris3(struct msm_vidc_core *core)
return rc; return rc;
fail_power_on_substate:
__power_off_iris3_hardware(core);
fail_power_on_hardware: fail_power_on_hardware:
__power_off_iris3_controller(core); __power_off_iris3_controller(core);
fail_power_on_controller: fail_power_on_controller:
call_res_op(core, set_bw, core, 0, 0); call_res_op(core, set_bw, core, 0, 0);
fail_vote_buses: fail_vote_buses:
core->power_enabled = false; msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE, 0, __func__);
return rc; return rc;
} }

View File

@@ -280,24 +280,26 @@ static int __power_off_iris33_hardware(struct msm_vidc_core *core)
* Incase hw power control is enabled, for both CPU WD, video * Incase hw power control is enabled, for both CPU WD, video
* hw unresponsive cases, check for power status to decide on * hw unresponsive cases, check for power status to decide on
* executing NOC reset sequence before disabling power. If there * executing NOC reset sequence before disabling power. If there
* is no CPU WD and hw_power_control is enabled, fw is expected * is no CPU WD and hw power control is enabled, fw is expected
* to power collapse video hw always. * to power collapse video hw always.
*/ */
if (core->hw_power_control) { if (is_core_sub_state(core, CORE_SUBSTATE_FW_PWR_CTRL)) {
pwr_collapsed = is_iris33_hw_power_collapsed(core); pwr_collapsed = is_iris33_hw_power_collapsed(core);
if (core->cpu_watchdog || core->video_unresponsive) { if (is_core_sub_state(core, CORE_SUBSTATE_CPU_WATCHDOG) ||
is_core_sub_state(core, CORE_SUBSTATE_VIDEO_UNRESPONSIVE)) {
if (pwr_collapsed) { if (pwr_collapsed) {
d_vpr_e("%s: video hw power collapsed %d, %d\n", d_vpr_e("%s: video hw power collapsed %s\n",
__func__, core->cpu_watchdog, core->video_unresponsive); __func__, core->sub_state_name);
goto disable_power; goto disable_power;
} else { } else {
d_vpr_e("%s: video hw is power ON %d, %d\n", d_vpr_e("%s: video hw is power ON %s\n",
__func__, core->cpu_watchdog, core->video_unresponsive); __func__, core->sub_state_name);
} }
} else { } else {
if (!pwr_collapsed) if (!pwr_collapsed)
d_vpr_e("%s: video hw is not power collapsed\n", __func__); d_vpr_e("%s: video hw is not power collapsed\n", __func__);
d_vpr_h("%s: disabling hw power\n", __func__);
goto disable_power; goto disable_power;
} }
} }
@@ -530,7 +532,7 @@ static int __power_off_iris33(struct msm_vidc_core *core)
return -EINVAL; return -EINVAL;
} }
if (!core->power_enabled) if (!is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE))
return 0; return 0;
/** /**
@@ -555,7 +557,7 @@ static int __power_off_iris33(struct msm_vidc_core *core)
disable_irq_nosync(core->resource->irq); disable_irq_nosync(core->resource->irq);
core->intr_status = 0; core->intr_status = 0;
core->power_enabled = false; msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE, 0, __func__);
return rc; return rc;
} }
@@ -633,9 +635,15 @@ static int __power_on_iris33(struct msm_vidc_core *core)
u32 freq = 0; u32 freq = 0;
int rc = 0; int rc = 0;
if (core->power_enabled) if (is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE))
return 0; return 0;
if (!core_in_valid_state(core)) {
d_vpr_e("%s: invalid core state %s\n",
__func__, core_state_name(core->state));
return -EINVAL;
}
/* Vote for all hardware resources */ /* Vote for all hardware resources */
rc = call_res_op(core, set_bw, core, INT_MAX, INT_MAX); rc = call_res_op(core, set_bw, core, INT_MAX, INT_MAX);
if (rc) { if (rc) {
@@ -655,7 +663,9 @@ static int __power_on_iris33(struct msm_vidc_core *core)
goto fail_power_on_hardware; goto fail_power_on_hardware;
} }
/* video controller and hardware powered on successfully */ /* video controller and hardware powered on successfully */
core->power_enabled = true; rc = msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_POWER_ENABLE, __func__);
if (rc)
goto fail_power_on_substate;
freq_tbl = core->resource->freq_set.freq_tbl; freq_tbl = core->resource->freq_set.freq_tbl;
freq = core->power.clk_freq ? core->power.clk_freq : freq = core->power.clk_freq ? core->power.clk_freq :
@@ -678,12 +688,14 @@ static int __power_on_iris33(struct msm_vidc_core *core)
return rc; return rc;
fail_power_on_substate:
__power_off_iris33_hardware(core);
fail_power_on_hardware: fail_power_on_hardware:
__power_off_iris33_controller(core); __power_off_iris33_controller(core);
fail_power_on_controller: fail_power_on_controller:
call_res_op(core, set_bw, core, 0, 0); call_res_op(core, set_bw, core, 0, 0);
fail_vote_buses: fail_vote_buses:
core->power_enabled = false; msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE, 0, __func__);
return rc; return rc;
} }

View File

@@ -65,6 +65,18 @@ struct msm_vidc_core_power {
enum msm_vidc_core_state FOREACH_CORE_STATE(GENERATE_MSM_VIDC_ENUM); enum msm_vidc_core_state FOREACH_CORE_STATE(GENERATE_MSM_VIDC_ENUM);
enum msm_vidc_core_sub_state {
CORE_SUBSTATE_NONE = 0x0,
CORE_SUBSTATE_POWER_ENABLE = BIT(0),
CORE_SUBSTATE_GDSC_HANDOFF = BIT(1),
CORE_SUBSTATE_PM_SUSPEND = BIT(2),
CORE_SUBSTATE_FW_PWR_CTRL = BIT(3),
CORE_SUBSTATE_PAGE_FAULT = BIT(4),
CORE_SUBSTATE_CPU_WATCHDOG = BIT(5),
CORE_SUBSTATE_VIDEO_UNRESPONSIVE = BIT(6),
CORE_SUBSTATE_MAX = BIT(7),
};
struct msm_vidc_core { struct msm_vidc_core {
struct platform_device *pdev; struct platform_device *pdev;
struct msm_video_device vdev[2]; struct msm_video_device vdev[2];
@@ -76,13 +88,14 @@ struct msm_vidc_core {
struct dentry *debugfs_root; struct dentry *debugfs_root;
char fw_version[MAX_NAME_LENGTH]; char fw_version[MAX_NAME_LENGTH];
enum msm_vidc_core_state state; enum msm_vidc_core_state state;
enum msm_vidc_core_sub_state sub_state;
char sub_state_name[MAX_NAME_LENGTH];
struct mutex lock; struct mutex lock;
struct msm_vidc_resource *resource; struct msm_vidc_resource *resource;
struct msm_vidc_platform *platform; struct msm_vidc_platform *platform;
u32 intr_status; u32 intr_status;
u32 spur_count; u32 spur_count;
u32 reg_count; u32 reg_count;
bool power_enabled;
u32 codecs_count; u32 codecs_count;
struct msm_vidc_core_capability *capabilities; struct msm_vidc_core_capability *capabilities;
struct msm_vidc_inst_capability *inst_caps; struct msm_vidc_inst_capability *inst_caps;
@@ -96,7 +109,6 @@ struct msm_vidc_core {
struct work_struct ssr_work; struct work_struct ssr_work;
struct msm_vidc_core_power power; struct msm_vidc_core_power power;
struct msm_vidc_ssr ssr; struct msm_vidc_ssr ssr;
bool smmu_fault_handled;
u32 skip_pc_count; u32 skip_pc_count;
u32 last_packet_type; u32 last_packet_type;
u8 *packet; u8 *packet;
@@ -117,11 +129,11 @@ struct msm_vidc_core {
u32 header_id; u32 header_id;
u32 packet_id; u32 packet_id;
u32 sys_init_id; u32 sys_init_id;
bool handoff_done;
bool hw_power_control;
bool pm_suspended;
bool cpu_watchdog;
bool video_unresponsive;
}; };
static inline bool core_in_valid_state(struct msm_vidc_core *core)
{
return core->state != MSM_VIDC_CORE_DEINIT;
}
#endif // _MSM_VIDC_CORE_H_ #endif // _MSM_VIDC_CORE_H_

View File

@@ -370,6 +370,17 @@ static inline bool is_sub_state(struct msm_vidc_inst *inst,
return (inst->sub_state & sub_state); return (inst->sub_state & sub_state);
} }
static inline bool is_core_state(struct msm_vidc_core *core, enum msm_vidc_core_state state)
{
return core->state == state;
}
static inline bool is_core_sub_state(struct msm_vidc_core *core,
enum msm_vidc_core_sub_state sub_state)
{
return !!(core->sub_state & sub_state);
}
const char *cap_name(enum msm_vidc_inst_capability_type cap_id); const char *cap_name(enum msm_vidc_inst_capability_type cap_id);
const char *v4l2_pixelfmt_name(struct msm_vidc_inst *inst, u32 pixelfmt); const char *v4l2_pixelfmt_name(struct msm_vidc_inst *inst, u32 pixelfmt);
const char *v4l2_type_name(u32 port); const char *v4l2_type_name(u32 port);
@@ -434,6 +445,9 @@ int msm_vidc_kill_session(struct msm_vidc_inst* inst);
int msm_vidc_get_inst_capability(struct msm_vidc_inst *inst); int msm_vidc_get_inst_capability(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 msm_vidc_change_core_sub_state(struct msm_vidc_core *core,
enum msm_vidc_core_sub_state clear_sub_states,
enum msm_vidc_core_sub_state set_sub_states, const char *func);
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);
@@ -451,7 +465,7 @@ int msm_vidc_trigger_stability(struct msm_vidc_core *core,
void msm_vidc_stability_handler(struct work_struct *work); void msm_vidc_stability_handler(struct work_struct *work);
int cancel_stability_work_sync(struct msm_vidc_inst *inst); int cancel_stability_work_sync(struct msm_vidc_inst *inst);
void msm_vidc_fw_unload_handler(struct work_struct *work); void msm_vidc_fw_unload_handler(struct work_struct *work);
int msm_vidc_suspend(struct msm_vidc_core *core); int msm_vidc_suspend_locked(struct msm_vidc_core *core);
void msm_vidc_batch_handler(struct work_struct *work); void msm_vidc_batch_handler(struct work_struct *work);
int msm_vidc_event_queue_init(struct msm_vidc_inst *inst); int msm_vidc_event_queue_init(struct msm_vidc_inst *inst);
int msm_vidc_event_queue_deinit(struct msm_vidc_inst *inst); int msm_vidc_event_queue_deinit(struct msm_vidc_inst *inst);
@@ -516,6 +530,7 @@ enum msm_vidc_allow msm_vidc_allow_qbuf(struct msm_vidc_inst *inst, u32 type);
enum msm_vidc_allow msm_vidc_allow_input_psc(struct msm_vidc_inst *inst); enum msm_vidc_allow msm_vidc_allow_input_psc(struct msm_vidc_inst *inst);
bool msm_vidc_allow_drain_last_flag(struct msm_vidc_inst *inst); bool msm_vidc_allow_drain_last_flag(struct msm_vidc_inst *inst);
bool msm_vidc_allow_psc_last_flag(struct msm_vidc_inst *inst); bool msm_vidc_allow_psc_last_flag(struct msm_vidc_inst *inst);
bool msm_vidc_allow_pm_suspend(struct msm_vidc_core *core);
int msm_vidc_state_change_streamon(struct msm_vidc_inst *inst, u32 type); int msm_vidc_state_change_streamon(struct msm_vidc_inst *inst, u32 type);
int msm_vidc_state_change_streamoff(struct msm_vidc_inst *inst, u32 type); int msm_vidc_state_change_streamoff(struct msm_vidc_inst *inst, u32 type);
int msm_vidc_state_change_input_psc(struct msm_vidc_inst *inst); int msm_vidc_state_change_input_psc(struct msm_vidc_inst *inst);

View File

@@ -949,7 +949,6 @@ struct msm_vidc_input_timer {
enum msm_vidc_allow FOREACH_ALLOW(GENERATE_ENUM); enum msm_vidc_allow FOREACH_ALLOW(GENERATE_ENUM);
struct msm_vidc_ssr { struct msm_vidc_ssr {
bool trigger;
enum msm_vidc_ssr_trigger_type ssr_type; enum msm_vidc_ssr_trigger_type ssr_type;
u32 sub_client_id; u32 sub_client_id;
u32 test_addr; u32 test_addr;

View File

@@ -73,6 +73,5 @@ irqreturn_t venus_hfi_isr(int irq, void *data);
irqreturn_t venus_hfi_isr_handler(int irq, void *data); irqreturn_t venus_hfi_isr_handler(int irq, void *data);
int __prepare_pc(struct msm_vidc_core *core); int __prepare_pc(struct msm_vidc_core *core);
bool __core_in_valid_state(struct msm_vidc_core *core);
#endif // _VENUS_HFI_H_ #endif // _VENUS_HFI_H_

View File

@@ -146,6 +146,23 @@ exit:
return name; return name;
} }
const char *core_sub_state_name(enum msm_vidc_core_sub_state sub_state)
{
switch (sub_state) {
case CORE_SUBSTATE_NONE: return "NONE ";
case CORE_SUBSTATE_GDSC_HANDOFF: return "GDSC_HANDOFF ";
case CORE_SUBSTATE_PM_SUSPEND: return "PM_SUSPEND ";
case CORE_SUBSTATE_FW_PWR_CTRL: return "FW_PWR_CTRL ";
case CORE_SUBSTATE_POWER_ENABLE: return "POWER_ENABLE ";
case CORE_SUBSTATE_PAGE_FAULT: return "PAGE_FAULT ";
case CORE_SUBSTATE_CPU_WATCHDOG: return "CPU_WATCHDOG ";
case CORE_SUBSTATE_VIDEO_UNRESPONSIVE: return "VIDEO_UNRESPONSIVE ";
case CORE_SUBSTATE_MAX: return "MAX ";
}
return "UNKNOWN ";
}
const char *v4l2_type_name(u32 port) const char *v4l2_type_name(u32 port)
{ {
switch (port) { switch (port) {
@@ -304,7 +321,7 @@ static u32 msm_vidc_get_buffer_stats_flag(struct msm_vidc_inst *inst)
return flags; return flags;
} }
static int msm_vidc_suspend_locked(struct msm_vidc_core *core) int msm_vidc_suspend_locked(struct msm_vidc_core *core)
{ {
int rc = 0; int rc = 0;
@@ -1027,6 +1044,53 @@ int msm_vidc_change_core_state(struct msm_vidc_core *core,
return 0; return 0;
} }
int msm_vidc_change_core_sub_state(struct msm_vidc_core *core,
enum msm_vidc_core_sub_state clear_sub_state,
enum msm_vidc_core_sub_state set_sub_state, const char *func)
{
int i = 0;
enum msm_vidc_core_sub_state prev_sub_state;
if (!core) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
/* final value will not change */
if (clear_sub_state == set_sub_state)
return 0;
/* sanitize clear & set value */
if (set_sub_state > CORE_SUBSTATE_MAX ||
clear_sub_state > CORE_SUBSTATE_MAX) {
d_vpr_e("%s: invalid sub states. clear %#x or set %#x\n",
func, clear_sub_state, set_sub_state);
return -EINVAL;
}
prev_sub_state = core->sub_state;
core->sub_state |= set_sub_state;
core->sub_state &= ~clear_sub_state;
/* print substates only when there is a change */
if (core->sub_state != prev_sub_state) {
strscpy(core->sub_state_name, "\0", sizeof(core->sub_state_name));
for (i = 0; BIT(i) < CORE_SUBSTATE_MAX; i++) {
if (core->sub_state == CORE_SUBSTATE_NONE) {
strscpy(core->sub_state_name, "CORE_SUBSTATE_NONE",
sizeof(core->sub_state_name));
break;
}
if (core->sub_state & BIT(i))
strlcat(core->sub_state_name, core_sub_state_name(BIT(i)),
sizeof(core->sub_state_name));
}
d_vpr_h("%s: core sub state changed to %s\n", func, core->sub_state_name);
}
return 0;
}
int msm_vidc_change_state(struct msm_vidc_inst *inst, int msm_vidc_change_state(struct msm_vidc_inst *inst,
enum msm_vidc_state request_state, const char *func) enum msm_vidc_state request_state, const char *func)
{ {
@@ -1561,6 +1625,29 @@ bool msm_vidc_allow_psc_last_flag(struct msm_vidc_inst *inst)
return false; return false;
} }
bool msm_vidc_allow_pm_suspend(struct msm_vidc_core *core)
{
if (!core) {
d_vpr_e("%s: invalid param\n", __func__);
return false;
}
/* core must be in valid state to do pm_suspend */
if (!core_in_valid_state(core)) {
d_vpr_e("%s: invalid core state %s\n",
__func__, core_state_name(core->state));
return false;
}
/* check if power is enabled */
if (!is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE)) {
d_vpr_e("%s: Power already disabled\n", __func__);
return false;
}
return true;
}
bool is_hevc_10bit_decode_session(struct msm_vidc_inst *inst) bool is_hevc_10bit_decode_session(struct msm_vidc_inst *inst)
{ {
bool is10bit = false; bool is10bit = false;
@@ -4640,7 +4727,7 @@ int msm_vidc_core_deinit_locked(struct msm_vidc_core *core, bool force)
return rc; return rc;
} }
if (core->state == MSM_VIDC_CORE_DEINIT) if (is_core_state(core, MSM_VIDC_CORE_DEINIT))
return 0; return 0;
if (force) { if (force) {
@@ -4693,10 +4780,10 @@ int msm_vidc_core_init_wait(struct msm_vidc_core *core)
} }
core_lock(core, __func__); core_lock(core, __func__);
if (core->state == MSM_VIDC_CORE_INIT) { if (is_core_state(core, MSM_VIDC_CORE_INIT)) {
rc = 0; rc = 0;
goto unlock; goto unlock;
} else if (core->state == MSM_VIDC_CORE_DEINIT) { } else if (is_core_state(core, MSM_VIDC_CORE_DEINIT)) {
rc = -EINVAL; rc = -EINVAL;
goto unlock; goto unlock;
} }
@@ -4715,14 +4802,16 @@ int msm_vidc_core_init_wait(struct msm_vidc_core *core)
d_vpr_h("%s: state %s, interval %u, count %u, max_tries %u\n", __func__, d_vpr_h("%s: state %s, interval %u, count %u, max_tries %u\n", __func__,
core_state_name(core->state), interval, count, max_tries); core_state_name(core->state), interval, count, max_tries);
if (core->state == MSM_VIDC_CORE_INIT) { if (is_core_state(core, MSM_VIDC_CORE_INIT)) {
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 {
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));
core->video_unresponsive = true; /* mark video hw unresponsive */
msm_vidc_change_core_sub_state(core,
0, CORE_SUBSTATE_VIDEO_UNRESPONSIVE, __func__);
rc = -EINVAL; rc = -EINVAL;
goto unlock; goto unlock;
} }
@@ -4743,14 +4832,14 @@ int msm_vidc_core_init(struct msm_vidc_core *core)
} }
core_lock(core, __func__); core_lock(core, __func__);
if (core->state == MSM_VIDC_CORE_INIT || if (is_core_state(core, MSM_VIDC_CORE_INIT) ||
core->state == MSM_VIDC_CORE_INIT_WAIT) is_core_state(core, MSM_VIDC_CORE_INIT_WAIT))
goto unlock; 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__);
core->smmu_fault_handled = false; /* clear PM suspend from core sub_state */
core->ssr.trigger = false; msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_PM_SUSPEND, 0, __func__);
core->pm_suspended = false; msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_PAGE_FAULT, 0, __func__);
rc = venus_hfi_core_init(core); rc = venus_hfi_core_init(core);
if (rc) { if (rc) {
@@ -4798,7 +4887,8 @@ int msm_vidc_inst_timeout(struct msm_vidc_inst *inst)
goto unlock; goto unlock;
} }
/* mark video hw unresponsive */ /* mark video hw unresponsive */
core->video_unresponsive = true; msm_vidc_change_core_sub_state(core,
0, CORE_SUBSTATE_VIDEO_UNRESPONSIVE, __func__);
/* call core deinit for a valid instance timeout case */ /* call core deinit for a valid instance timeout case */
msm_vidc_core_deinit_locked(core, true); msm_vidc_core_deinit_locked(core, true);
@@ -4938,7 +5028,7 @@ int msm_vidc_smmu_fault_handler(struct iommu_domain *domain,
return -EINVAL; return -EINVAL;
} }
if (core->smmu_fault_handled) { if (is_core_sub_state(core, CORE_SUBSTATE_PAGE_FAULT)) {
if (core->capabilities[NON_FATAL_FAULTS].value) { if (core->capabilities[NON_FATAL_FAULTS].value) {
dprintk_ratelimit(VIDC_ERR, "err ", dprintk_ratelimit(VIDC_ERR, "err ",
"%s: non-fatal pagefault address: %lx\n", "%s: non-fatal pagefault address: %lx\n",
@@ -4949,7 +5039,8 @@ 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);
core->smmu_fault_handled = true; /* mark smmu fault as handled */
msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_PAGE_FAULT, __func__);
/* print noc error log registers */ /* print noc error log registers */
venus_hfi_noc_error_info(core); venus_hfi_noc_error_info(core);
@@ -5005,20 +5096,17 @@ void msm_vidc_ssr_handler(struct work_struct *work)
ssr = &core->ssr; ssr = &core->ssr;
core_lock(core, __func__); core_lock(core, __func__);
if (core->state == MSM_VIDC_CORE_INIT) { if (is_core_state(core, MSM_VIDC_CORE_INIT)) {
/* /*
* In current implementation, user-initiated SSR triggers * In current implementation, user-initiated SSR triggers
* a fatal error from hardware. However, there is no way * a fatal error from hardware. However, there is no way
* to know if fatal error is due to SSR or not. Handle * to know if fatal error is due to SSR or not. Handle
* user SSR as non-fatal. * user SSR as non-fatal.
*/ */
core->ssr.trigger = true;
rc = venus_hfi_trigger_ssr(core, ssr->ssr_type, rc = venus_hfi_trigger_ssr(core, ssr->ssr_type,
ssr->sub_client_id, ssr->test_addr); ssr->sub_client_id, ssr->test_addr);
if (rc) { if (rc)
d_vpr_e("%s: trigger_ssr failed\n", __func__); d_vpr_e("%s: trigger_ssr failed\n", __func__);
core->ssr.trigger = false;
}
} else { } else {
d_vpr_e("%s: video core not initialized\n", __func__); d_vpr_e("%s: video core not initialized\n", __func__);
} }
@@ -5114,26 +5202,6 @@ void msm_vidc_fw_unload_handler(struct work_struct *work)
} }
int msm_vidc_suspend(struct msm_vidc_core *core)
{
int rc = 0;
if (!core) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
core_lock(core, __func__);
d_vpr_h("%s: initiate PM suspend\n", __func__);
rc = msm_vidc_suspend_locked(core);
if (rc)
goto exit;
exit:
core_unlock(core, __func__);
return rc;
}
void msm_vidc_batch_handler(struct work_struct *work) void msm_vidc_batch_handler(struct work_struct *work)
{ {
struct msm_vidc_inst *inst; struct msm_vidc_inst *inst;
@@ -5155,7 +5223,7 @@ void msm_vidc_batch_handler(struct work_struct *work)
goto exit; goto exit;
} }
if (core->pm_suspended) { if (is_core_sub_state(core, CORE_SUBSTATE_PM_SUSPEND)) {
i_vpr_h(inst, "%s: device in pm suspend state\n", __func__); i_vpr_h(inst, "%s: device in pm suspend state\n", __func__);
goto exit; goto exit;
} }

View File

@@ -806,6 +806,7 @@ static int msm_vidc_pm_suspend(struct device *dev)
{ {
int rc = 0; int rc = 0;
struct msm_vidc_core *core; struct msm_vidc_core *core;
bool allow = false;
/* /*
* Bail out if * Bail out if
@@ -822,15 +823,25 @@ static int msm_vidc_pm_suspend(struct device *dev)
return -EINVAL; return -EINVAL;
} }
core_lock(core, __func__);
allow = msm_vidc_allow_pm_suspend(core);
if (!allow) {
d_vpr_e("%s: pm suspend not allowed\n", __func__);
rc = 0;
goto unlock;
}
d_vpr_h("%s\n", __func__); d_vpr_h("%s\n", __func__);
rc = msm_vidc_suspend(core); rc = msm_vidc_suspend_locked(core);
if (rc == -ENOTSUPP) if (rc == -ENOTSUPP)
rc = 0; rc = 0;
else if (rc) else if (rc)
d_vpr_e("Failed to suspend: %d\n", rc); d_vpr_e("Failed to suspend: %d\n", rc);
else else
core->pm_suspended = true; msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_PM_SUSPEND, __func__);
unlock:
core_unlock(core, __func__);
return rc; return rc;
} }
@@ -854,7 +865,12 @@ static int msm_vidc_pm_resume(struct device *dev)
} }
d_vpr_h("%s\n", __func__); d_vpr_h("%s\n", __func__);
core->pm_suspended = false;
/* remove PM suspend from core sub_state */
core_lock(core, __func__);
msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_PM_SUSPEND, 0, __func__);
core_unlock(core, __func__);
return 0; return 0;
} }

View File

@@ -16,6 +16,7 @@
#include "msm_vidc_core.h" #include "msm_vidc_core.h"
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
#include "msm_vidc_power.h" #include "msm_vidc_power.h"
#include "msm_vidc_driver.h"
#include "msm_vidc_platform.h" #include "msm_vidc_platform.h"
#include "venus_hfi.h" #include "venus_hfi.h"
@@ -666,7 +667,9 @@ static int __acquire_regulator(struct msm_vidc_core *core,
if (regulator_get_mode(rinfo->regulator) == if (regulator_get_mode(rinfo->regulator) ==
REGULATOR_MODE_NORMAL) { REGULATOR_MODE_NORMAL) {
core->handoff_done = false; /* clear handoff from core sub_state */
msm_vidc_change_core_sub_state(core,
CORE_SUBSTATE_GDSC_HANDOFF, 0, __func__);
d_vpr_h("Skip acquire regulator %s\n", rinfo->name); d_vpr_h("Skip acquire regulator %s\n", rinfo->name);
goto exit; goto exit;
} }
@@ -683,7 +686,9 @@ static int __acquire_regulator(struct msm_vidc_core *core,
rinfo->name); rinfo->name);
goto exit; goto exit;
} else { } else {
core->handoff_done = false; /* reset handoff from core sub_state */
msm_vidc_change_core_sub_state(core,
CORE_SUBSTATE_GDSC_HANDOFF, 0, __func__);
d_vpr_h("Acquired regulator control from HW: %s\n", d_vpr_h("Acquired regulator control from HW: %s\n",
rinfo->name); rinfo->name);
@@ -729,7 +734,9 @@ static int __hand_off_regulator(struct msm_vidc_core *core,
rinfo->name); rinfo->name);
return rc; return rc;
} else { } else {
core->handoff_done = true; /* set handoff done in core sub_state */
msm_vidc_change_core_sub_state(core,
0, CORE_SUBSTATE_GDSC_HANDOFF, __func__);
d_vpr_h("Hand off regulator control to HW: %s\n", d_vpr_h("Hand off regulator control to HW: %s\n",
rinfo->name); rinfo->name);
} }
@@ -798,7 +805,8 @@ static int __disable_regulator(struct msm_vidc_core *core, const char *reg_name)
WARN_ON(true); WARN_ON(true);
return rc; return rc;
} }
core->handoff_done = false; /* reset handoff done from core sub_state */
msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_GDSC_HANDOFF, 0, __func__);
rc = regulator_disable(rinfo->regulator); rc = regulator_disable(rinfo->regulator);
if (rc) { if (rc) {

View File

@@ -59,11 +59,6 @@ static int __strict_check(struct msm_vidc_core *core, const char *function)
return fatal ? -EINVAL : 0; return fatal ? -EINVAL : 0;
} }
bool __core_in_valid_state(struct msm_vidc_core *core)
{
return core->state != MSM_VIDC_CORE_DEINIT;
}
static bool __valdiate_session(struct msm_vidc_core *core, static bool __valdiate_session(struct msm_vidc_core *core,
struct msm_vidc_inst *inst, const char *func) struct msm_vidc_inst *inst, const char *func)
{ {
@@ -253,12 +248,18 @@ static int __sys_set_power_control(struct msm_vidc_core *core, bool enable)
{ {
int rc = 0; int rc = 0;
if (!core->handoff_done) { if (!is_core_sub_state(core, CORE_SUBSTATE_GDSC_HANDOFF)) {
d_vpr_e("%s: skipping as power control hanfoff was not done\n", d_vpr_e("%s: skipping as power control hanfoff was not done\n",
__func__); __func__);
return rc; return rc;
} }
if (!core_in_valid_state(core)) {
d_vpr_e("%s: invalid core state %s\n",
__func__, core_state_name(core->state));
return rc;
}
rc = hfi_packet_sys_intraframe_powercollapse(core, rc = hfi_packet_sys_intraframe_powercollapse(core,
core->packet, core->packet_size, enable); core->packet, core->packet_size, enable);
if (rc) if (rc)
@@ -268,7 +269,10 @@ static int __sys_set_power_control(struct msm_vidc_core *core, bool enable)
if (rc) if (rc)
return rc; return rc;
core->hw_power_control = true; rc = msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_FW_PWR_CTRL, __func__);
if (rc)
return rc;
d_vpr_h("%s: set hardware power control successful\n", __func__); d_vpr_h("%s: set hardware power control successful\n", __func__);
return rc; return rc;
@@ -300,12 +304,12 @@ static int __power_collapse(struct msm_vidc_core *core, bool force)
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
if (!core->power_enabled) { if (!is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE)) {
d_vpr_h("%s: Power already disabled\n", __func__); d_vpr_h("%s: Power already disabled\n", __func__);
goto exit; goto exit;
} }
if (!__core_in_valid_state(core)) { if (!core_in_valid_state(core)) {
d_vpr_e("%s: Core not in init state\n", __func__); d_vpr_e("%s: Core not in init state\n", __func__);
return -EINVAL; return -EINVAL;
} }
@@ -534,7 +538,7 @@ static int __venus_power_off(struct msm_vidc_core* core)
{ {
int rc = 0; int rc = 0;
if (!core->power_enabled) if (!is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE))
return 0; return 0;
rc = call_venus_op(core, power_off, core); rc = call_venus_op(core, power_off, core);
@@ -542,7 +546,7 @@ static int __venus_power_off(struct msm_vidc_core* core)
d_vpr_e("Failed to power off, err: %d\n", rc); d_vpr_e("Failed to power off, err: %d\n", rc);
return rc; return rc;
} }
core->power_enabled = false; msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE, 0, __func__);
return rc; return rc;
} }
@@ -551,7 +555,7 @@ static int __venus_power_on(struct msm_vidc_core *core)
{ {
int rc = 0; int rc = 0;
if (core->power_enabled) if (is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE))
return 0; return 0;
rc = call_venus_op(core, power_on, core); rc = call_venus_op(core, power_on, core);
@@ -559,7 +563,10 @@ static int __venus_power_on(struct msm_vidc_core *core)
d_vpr_e("Failed to power on, err: %d\n", rc); d_vpr_e("Failed to power on, err: %d\n", rc);
return rc; return rc;
} }
core->power_enabled = true;
rc = msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_POWER_ENABLE, __func__);
if (rc)
return rc;
return rc; return rc;
} }
@@ -571,7 +578,7 @@ static int __suspend(struct msm_vidc_core *core)
if (!core) { if (!core) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} else if (!core->power_enabled) { } else if (!is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE)) {
d_vpr_h("Power already disabled\n"); d_vpr_h("Power already disabled\n");
return 0; return 0;
} }
@@ -605,9 +612,9 @@ static int __resume(struct msm_vidc_core *core)
if (!core) { if (!core) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} else if (core->power_enabled) { } else if (is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE)) {
goto exit; goto exit;
} else if (!__core_in_valid_state(core)) { } else if (!core_in_valid_state(core)) {
d_vpr_e("%s: core not in valid state\n", __func__); d_vpr_e("%s: core not in valid state\n", __func__);
return -EINVAL; return -EINVAL;
} }
@@ -617,8 +624,14 @@ static int __resume(struct msm_vidc_core *core)
return rc; return rc;
d_vpr_h("Resuming from power collapse\n"); d_vpr_h("Resuming from power collapse\n");
core->handoff_done = false; /* reset handoff done from core sub_state */
core->hw_power_control = false; rc = msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_GDSC_HANDOFF, 0, __func__);
if (rc)
return rc;
/* reset hw pwr ctrl from core sub_state */
rc = msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_FW_PWR_CTRL, 0, __func__);
if (rc)
return rc;
rc = __venus_power_on(core); rc = __venus_power_on(core);
if (rc) { if (rc) {
@@ -684,10 +697,8 @@ int __load_fw(struct msm_vidc_core *core)
int rc = 0; int rc = 0;
d_vpr_h("%s\n", __func__); d_vpr_h("%s\n", __func__);
core->handoff_done = false; /* clear all substates */
core->hw_power_control = false; msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_MAX - 1, 0, __func__);
core->cpu_watchdog = false;
core->video_unresponsive = false;
trace_msm_v4l2_vidc_fw_load("START"); trace_msm_v4l2_vidc_fw_load("START");
rc = __venus_power_on(core); rc = __venus_power_on(core);
@@ -726,8 +737,8 @@ void __unload_fw(struct msm_vidc_core *core)
fw_unload(core); fw_unload(core);
__venus_power_off(core); __venus_power_off(core);
core->cpu_watchdog = false; /* clear all substates */
core->video_unresponsive = false; msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_MAX - 1, 0, __func__);
d_vpr_h("%s done\n", __func__); d_vpr_h("%s done\n", __func__);
} }
@@ -738,7 +749,10 @@ 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->cpu_watchdog = true;
/* 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__); d_vpr_e("%s: CPU WD error received\n", __func__);
return handle_system_error(core, &pkt); return handle_system_error(core, &pkt);
@@ -817,15 +831,18 @@ 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;
core->video_unresponsive = true; /* mark video hw unresponsive */
msm_vidc_change_core_sub_state(core,
0, CORE_SUBSTATE_VIDEO_UNRESPONSIVE, __func__);
msm_vidc_core_deinit(core, true); msm_vidc_core_deinit(core, true);
return; return;
} }
core_lock(core, __func__); core_lock(core, __func__);
/* core already deinited - skip power collapse */ /* core already deinited - skip power collapse */
if (core->state == MSM_VIDC_CORE_DEINIT) { if (is_core_state(core, MSM_VIDC_CORE_DEINIT)) {
d_vpr_e("%s: core is already de-inited\n", __func__); d_vpr_e("%s: invalid core state %s\n",
__func__, core_state_name(core->state));
goto unlock; goto unlock;
} }
@@ -962,7 +979,7 @@ int venus_hfi_core_deinit(struct msm_vidc_core *core, bool force)
if (rc) if (rc)
return rc; return rc;
if (core->state == MSM_VIDC_CORE_DEINIT) if (is_core_state(core, MSM_VIDC_CORE_DEINIT))
return 0; return 0;
__resume(core); __resume(core);
__flush_debug_queue(core, (!force ? core->packet : NULL), core->packet_size); __flush_debug_queue(core, (!force ? core->packet : NULL), core->packet_size);
@@ -993,7 +1010,7 @@ int venus_hfi_noc_error_info(struct msm_vidc_core *core)
return 0; return 0;
core_lock(core, __func__); core_lock(core, __func__);
if (core->state == MSM_VIDC_CORE_DEINIT) if (is_core_state(core, MSM_VIDC_CORE_DEINIT))
goto unlock; goto unlock;
/* resume venus before accessing noc registers */ /* resume venus before accessing noc registers */

View File

@@ -22,11 +22,6 @@ static int __strict_check(struct msm_vidc_core *core, const char *function)
return fatal ? -EINVAL : 0; return fatal ? -EINVAL : 0;
} }
static bool __core_in_valid_state(struct msm_vidc_core *core)
{
return core->state != MSM_VIDC_CORE_DEINIT;
}
static void __set_queue_hdr_defaults(struct hfi_queue_header *q_hdr) static void __set_queue_hdr_defaults(struct hfi_queue_header *q_hdr)
{ {
q_hdr->qhdr_status = 0x1; q_hdr->qhdr_status = 0x1;
@@ -290,7 +285,7 @@ static int __iface_cmdq_write_relaxed(struct msm_vidc_core *core,
if (rc) if (rc)
return rc; return rc;
if (!__core_in_valid_state(core)) { if (!core_in_valid_state(core)) {
d_vpr_e("%s: fw not in init state\n", __func__); d_vpr_e("%s: fw not in init state\n", __func__);
rc = -EINVAL; rc = -EINVAL;
goto err_q_null; goto err_q_null;
@@ -355,7 +350,7 @@ int venus_hfi_queue_msg_read(struct msm_vidc_core *core, void *pkt)
return -EINVAL; return -EINVAL;
} }
if (!__core_in_valid_state(core)) { if (!core_in_valid_state(core)) {
d_vpr_e("%s: fw not in init state\n", __func__); d_vpr_e("%s: fw not in init state\n", __func__);
rc = -EINVAL; rc = -EINVAL;
goto read_error_null; goto read_error_null;

View File

@@ -495,7 +495,7 @@ static int handle_system_init(struct msm_vidc_core *core,
{ {
if (pkt->flags & HFI_FW_FLAGS_SUCCESS) { if (pkt->flags & HFI_FW_FLAGS_SUCCESS) {
core_lock(core, __func__); core_lock(core, __func__);
if (core->state == MSM_VIDC_CORE_INIT_WAIT && if (is_core_state(core, MSM_VIDC_CORE_INIT_WAIT) &&
pkt->packet_id == core->sys_init_id) { pkt->packet_id == core->sys_init_id) {
msm_vidc_change_core_state(core, MSM_VIDC_CORE_INIT, __func__); msm_vidc_change_core_state(core, MSM_VIDC_CORE_INIT, __func__);
d_vpr_h("%s: successful\n", __func__); d_vpr_h("%s: successful\n", __func__);