diff options
-rw-r--r-- | include/power.h | 40 | ||||
-rw-r--r-- | power/amd_x86.c | 5 | ||||
-rw-r--r-- | power/host_sleep.c | 35 | ||||
-rw-r--r-- | power/intel_x86.c | 5 | ||||
-rw-r--r-- | power/mt8183.c | 5 | ||||
-rw-r--r-- | power/mt8186.c | 5 | ||||
-rw-r--r-- | power/mt8192.c | 5 | ||||
-rw-r--r-- | power/qcom.c | 5 |
8 files changed, 79 insertions, 26 deletions
diff --git a/include/power.h b/include/power.h index c3d90253d5..547a4d93ab 100644 --- a/include/power.h +++ b/include/power.h @@ -319,16 +319,50 @@ void sleep_suspend_transition(void); void sleep_resume_transition(void); /** + * Type of sleep hang detected + */ +enum sleep_hang_type { + SLEEP_HANG_NONE, + SLEEP_HANG_S0IX_SUSPEND, + SLEEP_HANG_S0IX_RESUME +}; + +/** + * Provide callback to allow chipset to take action on host sleep hang + * detection. + * + * power_chipset_handle_sleep_hang will be called first. + * power_board_handle_sleep_hang will be called second. + * + * @param hang_type Host sleep hang type detected. + */ +__override_proto void power_chipset_handle_sleep_hang( + enum sleep_hang_type hang_type); + +/** + * Provide callback to allow board to take action on host sleep hang + * detection. + * + * power_chipset_handle_sleep_hang will be called first. + * power_board_handle_sleep_hang will be called second. + * + * @param hang_type Host sleep hang type detected. + */ +__override_proto void power_board_handle_sleep_hang( + enum sleep_hang_type hang_type); + +/** * Start the suspend process. * * It is called in power_chipset_handle_host_sleep_event(), after it receives * a host sleep event to hint that the suspend process starts. * + * power_chipset_handle_sleep_hang() and power_board_handle_sleep_hang() will + * be called when a sleep hang is detected. + * * @param ctx Possible sleep parameters and return values, depending on state. - * @param callback Will be called if timed out, i.e. suspend hang. */ -void sleep_start_suspend(struct host_sleep_event_context *ctx, - void (*callback)(void)); +void sleep_start_suspend(struct host_sleep_event_context *ctx); /** * Complete the resume process. diff --git a/power/amd_x86.c b/power/amd_x86.c index c62663e9e9..c3698bde5d 100644 --- a/power/amd_x86.c +++ b/power/amd_x86.c @@ -231,7 +231,8 @@ static void lpc_s0ix_resume_restore_masks(void) backup_sci_mask = backup_smi_mask = 0; } -static void lpc_s0ix_hang_detected(void) +__override void power_chipset_handle_sleep_hang( + enum sleep_hang_type hang_type) { /* * Wake up the AP so they don't just chill in a non-suspended state and @@ -301,7 +302,7 @@ __override void power_chipset_handle_host_sleep_event( */ sleep_set_notify(SLEEP_NOTIFY_SUSPEND); - sleep_start_suspend(ctx, lpc_s0ix_hang_detected); + sleep_start_suspend(ctx); power_signal_enable_interrupt(GPIO_PCH_SLP_S0_L); } else if (state == HOST_SLEEP_EVENT_S0IX_RESUME) { /* diff --git a/power/host_sleep.c b/power/host_sleep.c index bfa5cbd90a..e352e677f2 100644 --- a/power/host_sleep.c +++ b/power/host_sleep.c @@ -111,11 +111,23 @@ void sleep_notify_transition(int check_state, int hook_id) static uint16_t sleep_signal_timeout; static uint16_t host_sleep_timeout_default = CONFIG_SLEEP_TIMEOUT_MS; static uint32_t sleep_signal_transitions; -static void (*sleep_timeout_callback)(void); +static enum sleep_hang_type timeout_hang_type; static void sleep_transition_timeout(void); DECLARE_DEFERRED(sleep_transition_timeout); +__overridable void power_board_handle_sleep_hang( + enum sleep_hang_type hang_type) +{ + /* Default empty implementation */ +} + +__overridable void power_chipset_handle_sleep_hang( + enum sleep_hang_type hang_type) +{ + /* Default empty implementation */ +} + static void sleep_increment_transition(void) { if ((sleep_signal_transitions & EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK) < @@ -140,9 +152,11 @@ void sleep_resume_transition(void) * internal periodic housekeeping code might result in a situation * like this. */ - if (sleep_signal_timeout) + if (sleep_signal_timeout) { + timeout_hang_type = SLEEP_HANG_S0IX_RESUME; hook_call_deferred(&sleep_transition_timeout_data, (uint32_t)sleep_signal_timeout * 1000); + } } static void sleep_transition_timeout(void) @@ -151,17 +165,16 @@ static void sleep_transition_timeout(void) sleep_signal_transitions |= EC_HOST_RESUME_SLEEP_TIMEOUT; hook_call_deferred(&sleep_transition_timeout_data, -1); - /* Call the custom callback */ - if (sleep_timeout_callback) - sleep_timeout_callback(); + if (timeout_hang_type != SLEEP_HANG_NONE) { + power_chipset_handle_sleep_hang(timeout_hang_type); + power_board_handle_sleep_hang(timeout_hang_type); + } } -void sleep_start_suspend(struct host_sleep_event_context *ctx, - void (*callback)(void)) +void sleep_start_suspend(struct host_sleep_event_context *ctx) { uint16_t timeout = ctx->sleep_timeout_ms; - sleep_timeout_callback = callback; sleep_signal_transitions = 0; /* Use zero internally to indicate no timeout. */ @@ -176,6 +189,7 @@ void sleep_start_suspend(struct host_sleep_event_context *ctx, } sleep_signal_timeout = timeout; + timeout_hang_type = SLEEP_HANG_S0IX_SUSPEND; hook_call_deferred(&sleep_transition_timeout_data, (uint32_t)timeout * 1000); } @@ -196,7 +210,7 @@ void sleep_reset_tracking(void) { sleep_signal_transitions = 0; sleep_signal_timeout = 0; - sleep_timeout_callback = NULL; + timeout_hang_type = SLEEP_HANG_NONE; } static int command_sleep_fail_timeout(int argc, char **argv) @@ -253,8 +267,7 @@ void sleep_resume_transition(void) { } -void sleep_start_suspend(struct host_sleep_event_context *ctx, - void (*callback)(void)) +void sleep_start_suspend(struct host_sleep_event_context *ctx) { } diff --git a/power/intel_x86.c b/power/intel_x86.c index 9f26943dae..25778b3f78 100644 --- a/power/intel_x86.c +++ b/power/intel_x86.c @@ -179,7 +179,8 @@ static void lpc_s0ix_resume_restore_masks(void) backup_sci_mask = backup_smi_mask = 0; } -static void lpc_s0ix_hang_detected(void) +__override void power_chipset_handle_sleep_hang( + enum sleep_hang_type hang_type) { /* * Wake up the AP so they don't just chill in a non-suspended state and @@ -613,7 +614,7 @@ __override void power_chipset_handle_host_sleep_event( */ sleep_set_notify(SLEEP_NOTIFY_SUSPEND); - sleep_start_suspend(ctx, lpc_s0ix_hang_detected); + sleep_start_suspend(ctx); power_signal_enable_interrupt(sleep_sig[SYS_SLEEP_S0IX]); } else if (state == HOST_SLEEP_EVENT_S0IX_RESUME) { /* diff --git a/power/mt8183.c b/power/mt8183.c index 7c747541a6..f62ddafb51 100644 --- a/power/mt8183.c +++ b/power/mt8183.c @@ -581,7 +581,8 @@ enum power_state power_handle_state(enum power_state state) } #ifdef CONFIG_POWER_TRACK_HOST_SLEEP_STATE -static void suspend_hang_detected(void) +__override void power_chipset_handle_sleep_hang( + enum sleep_hang_type hang_type) { CPRINTS("Warning: Detected sleep hang! Waking host up!"); host_set_single_event(EC_HOST_EVENT_HANG_DETECT); @@ -600,7 +601,7 @@ __override void power_chipset_handle_host_sleep_event( * notification needs to be sent to listeners. */ sleep_set_notify(SLEEP_NOTIFY_SUSPEND); - sleep_start_suspend(ctx, suspend_hang_detected); + sleep_start_suspend(ctx); } else if (state == HOST_SLEEP_EVENT_S3_RESUME) { /* diff --git a/power/mt8186.c b/power/mt8186.c index 17beb48256..b83a46856b 100644 --- a/power/mt8186.c +++ b/power/mt8186.c @@ -438,7 +438,8 @@ static void power_button_changed(void) DECLARE_HOOK(HOOK_POWER_BUTTON_CHANGE, power_button_changed, HOOK_PRIO_DEFAULT); #ifdef CONFIG_POWER_TRACK_HOST_SLEEP_STATE -static void suspend_hang_detected(void) +__override void power_chipset_handle_sleep_hang( + enum sleep_hang_type hang_type) { CPRINTS("Warning: Detected sleep hang! Waking host up!"); host_set_single_event(EC_HOST_EVENT_HANG_DETECT); @@ -457,7 +458,7 @@ __override void power_chipset_handle_host_sleep_event( * notification needs to be sent to listeners. */ sleep_set_notify(SLEEP_NOTIFY_SUSPEND); - sleep_start_suspend(ctx, suspend_hang_detected); + sleep_start_suspend(ctx); } else if (state == HOST_SLEEP_EVENT_S3_RESUME) { /* diff --git a/power/mt8192.c b/power/mt8192.c index 3cb6e164d8..fc99bce5e0 100644 --- a/power/mt8192.c +++ b/power/mt8192.c @@ -505,7 +505,8 @@ static void power_button_changed(void) DECLARE_HOOK(HOOK_POWER_BUTTON_CHANGE, power_button_changed, HOOK_PRIO_DEFAULT); #ifdef CONFIG_POWER_TRACK_HOST_SLEEP_STATE -static void suspend_hang_detected(void) +__overridable void power_chipset_handle_sleep_hang( + enum sleep_hang_type hang_type) { CPRINTS("Warning: Detected sleep hang! Waking host up!"); host_set_single_event(EC_HOST_EVENT_HANG_DETECT); @@ -524,7 +525,7 @@ __override void power_chipset_handle_host_sleep_event( * notification needs to be sent to listeners. */ sleep_set_notify(SLEEP_NOTIFY_SUSPEND); - sleep_start_suspend(ctx, suspend_hang_detected); + sleep_start_suspend(ctx); } else if (state == HOST_SLEEP_EVENT_S3_RESUME) { /* diff --git a/power/qcom.c b/power/qcom.c index 127dbbf6cc..d931e6bb29 100644 --- a/power/qcom.c +++ b/power/qcom.c @@ -931,7 +931,8 @@ static inline int chipset_get_sleep_signal(void) return fake_suspend; } -static void suspend_hang_detected(void) +__override void power_chipset_handle_sleep_hang( + enum sleep_hang_type hang_type) { CPRINTS("Warning: Detected sleep hang! Waking host up!"); host_set_single_event(EC_HOST_EVENT_HANG_DETECT); @@ -968,7 +969,7 @@ __override void power_chipset_handle_host_sleep_event( * notification needs to be sent to listeners. */ sleep_set_notify(SLEEP_NOTIFY_SUSPEND); - sleep_start_suspend(ctx, suspend_hang_detected); + sleep_start_suspend(ctx); power_signal_enable_interrupt(GPIO_AP_SUSPEND); } else if (state == HOST_SLEEP_EVENT_S3_RESUME) { |