power/intel_x86: Generalize the sleep failure detection, not bound to S0ix

This change prepares to separate the sleep failure detection out of
intel_x86, such that other chipset power sequence can reuse the code.

It only touches the naming. No logic changes.
 * Rename to CONFIG_POWER_SLEEP_FAILURE_DETECTION
 * Modify the function and variable names, to avoid S0ix
 * Modify the comment to more neutral

BRANCH=None
BUG=b:162083524
TEST=make buildall -j

Change-Id: I6a61c3b0a63af60913ee89e0ca343085fbd22308
Signed-off-by: Wai-Hong Tam <waihong@google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2321872
Reviewed-by: Eric Yilun Lin <yllin@chromium.org>
This commit is contained in:
Wai-Hong Tam 2020-07-23 13:35:48 -07:00 committed by Commit Bot
parent 3e8d31a1e1
commit 119a7701d5
6 changed files with 81 additions and 75 deletions

View File

@ -149,7 +149,7 @@
#define CONFIG_POWER_COMMON
#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE
#define CONFIG_POWER_S0IX
#define CONFIG_POWER_S0IX_FAILURE_DETECTION
#define CONFIG_POWER_SLEEP_FAILURE_DETECTION
#define CONFIG_CPU_PROCHOT_ACTIVE_LOW
/* USB Type-C */

View File

@ -55,7 +55,7 @@
#define CONFIG_POWER_COMMON
#define CONFIG_POWER_PP5000_CONTROL
#define CONFIG_POWER_S0IX
#define CONFIG_POWER_S0IX_FAILURE_DETECTION
#define CONFIG_POWER_SLEEP_FAILURE_DETECTION
#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE
/* Common Keyboard Defines */

View File

@ -53,7 +53,7 @@
#define CONFIG_POWER_BUTTON_X86
#define CONFIG_POWER_COMMON
#define CONFIG_POWER_S0IX
#define CONFIG_POWER_S0IX_FAILURE_DETECTION
#define CONFIG_POWER_SLEEP_FAILURE_DETECTION
#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE
#define CONFIG_BOARD_HAS_RTC_RESET

View File

@ -98,7 +98,7 @@
#define CONFIG_DELAY_DSW_PWROK_TO_PWRBTN
#define CONFIG_POWER_PP5000_CONTROL
#define CONFIG_POWER_S0IX
#define CONFIG_POWER_S0IX_FAILURE_DETECTION
#define CONFIG_POWER_SLEEP_FAILURE_DETECTION
#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE
#define CONFIG_INA3221

View File

@ -3014,8 +3014,8 @@
/* Support S0ix */
#undef CONFIG_POWER_S0IX
/* Support detecting failure to enter S0ix */
#undef CONFIG_POWER_S0IX_FAILURE_DETECTION
/* Support detecting failure to enter a sleep state (S0ix/S3) */
#undef CONFIG_POWER_SLEEP_FAILURE_DETECTION
/*
* Allow the host to self-report its sleep state, in case there is some delay

View File

@ -176,26 +176,30 @@ static void lpc_s0ix_resume_restore_masks(void)
backup_sci_mask = backup_smi_mask = 0;
}
enum s0ix_notify_type {
S0IX_NOTIFY_NONE,
S0IX_NOTIFY_SUSPEND,
S0IX_NOTIFY_RESUME,
enum sleep_notify_type {
SLEEP_NOTIFY_NONE,
SLEEP_NOTIFY_SUSPEND,
SLEEP_NOTIFY_RESUME,
};
/* Flag to notify listeners about S0ix suspend/resume events. */
enum s0ix_notify_type s0ix_notify = S0IX_NOTIFY_NONE;
/* Flag to notify listeners about suspend/resume events. */
enum sleep_notify_type sleep_notify = SLEEP_NOTIFY_NONE;
static void s0ix_transition(int check_state, int hook_id)
/*
* Note: the following sleep_ functions do not get called in the S3 path on
* Intel devices. On Intel devices, they are called in the S0ix path.
*/
static void sleep_notify_transition(int check_state, int hook_id)
{
if (s0ix_notify != check_state)
if (sleep_notify != check_state)
return;
/* Clear masks before any hooks are run for suspend. */
if (s0ix_notify == S0IX_NOTIFY_SUSPEND)
if (sleep_notify == SLEEP_NOTIFY_SUSPEND)
lpc_s0ix_suspend_clear_masks();
hook_notify(hook_id);
s0ix_notify = S0IX_NOTIFY_NONE;
sleep_notify = SLEEP_NOTIFY_NONE;
}
static void handle_chipset_reset(void)
@ -208,47 +212,48 @@ static void handle_chipset_reset(void)
}
DECLARE_HOOK(HOOK_CHIPSET_RESET, handle_chipset_reset, HOOK_PRIO_FIRST);
#ifdef CONFIG_POWER_S0IX_FAILURE_DETECTION
#ifdef CONFIG_POWER_SLEEP_FAILURE_DETECTION
static uint16_t slp_s0ix_timeout;
static uint32_t slp_s0ix_transitions;
static uint16_t sleep_signal_timeout;
static uint32_t sleep_signal_transitions;
static void s0ix_transition_timeout(void);
DECLARE_DEFERRED(s0ix_transition_timeout);
static void sleep_transition_timeout(void);
DECLARE_DEFERRED(sleep_transition_timeout);
static void s0ix_increment_transition(void)
static void sleep_increment_transition(void)
{
if ((slp_s0ix_transitions & EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK) <
if ((sleep_signal_transitions & EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK) <
EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK)
slp_s0ix_transitions += 1;
sleep_signal_transitions += 1;
}
static void s0ix_suspend_transition(void)
static void sleep_suspend_transition(void)
{
s0ix_increment_transition();
hook_call_deferred(&s0ix_transition_timeout_data, -1);
sleep_increment_transition();
hook_call_deferred(&sleep_transition_timeout_data, -1);
}
static void s0ix_resume_transition(void)
static void sleep_resume_transition(void)
{
s0ix_increment_transition();
sleep_increment_transition();
/*
* Start the timer again to ensure the AP doesn't get itself stuck in
* a state where it's no longer in S0ix, but from the Linux perspective
* is still suspended. Perhaps a bug in the SoC-internal periodic
* housekeeping code might result in a situation like this.
* a state where it's no longer in a sleep state (S0ix/S3), but from
* the Linux perspective is still suspended. Perhaps a bug in the SoC-
* internal periodic housekeeping code might result in a situation
* like this.
*/
if (slp_s0ix_timeout)
hook_call_deferred(&s0ix_transition_timeout_data,
(uint32_t)slp_s0ix_timeout * 1000);
if (sleep_signal_timeout)
hook_call_deferred(&sleep_transition_timeout_data,
(uint32_t)sleep_signal_timeout * 1000);
}
static void s0ix_transition_timeout(void)
static void sleep_transition_timeout(void)
{
/* Mark the timeout. */
slp_s0ix_transitions |= EC_HOST_RESUME_SLEEP_TIMEOUT;
hook_call_deferred(&s0ix_transition_timeout_data, -1);
sleep_signal_transitions |= EC_HOST_RESUME_SLEEP_TIMEOUT;
hook_call_deferred(&sleep_transition_timeout_data, -1);
/*
* Wake up the AP so they don't just chill in a non-suspended state and
@ -258,69 +263,70 @@ static void s0ix_transition_timeout(void)
* system.
*/
if (power_get_state() == POWER_S0) {
host_event_t s0ix_wake_mask;
host_event_t sleep_wake_mask;
get_lazy_wake_mask(POWER_S0ix, &s0ix_wake_mask);
lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, s0ix_wake_mask);
get_lazy_wake_mask(POWER_S0ix, &sleep_wake_mask);
lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, sleep_wake_mask);
}
CPRINTS("Warning: Detected S0ix hang! Waking host up!");
CPRINTS("Warning: Detected sleep hang! Waking host up!");
host_set_single_event(EC_HOST_EVENT_HANG_DETECT);
}
static void s0ix_start_suspend(struct host_sleep_event_context *ctx)
static void sleep_start_suspend(struct host_sleep_event_context *ctx)
{
uint16_t timeout = ctx->sleep_timeout_ms;
slp_s0ix_transitions = 0;
sleep_signal_transitions = 0;
/* Use zero internally to indicate no timeout. */
if (timeout == EC_HOST_SLEEP_TIMEOUT_DEFAULT) {
timeout = CONFIG_SLEEP_TIMEOUT_MS;
} else if (timeout == EC_HOST_SLEEP_TIMEOUT_INFINITE) {
slp_s0ix_timeout = 0;
sleep_signal_timeout = 0;
return;
}
slp_s0ix_timeout = timeout;
hook_call_deferred(&s0ix_transition_timeout_data,
sleep_signal_timeout = timeout;
hook_call_deferred(&sleep_transition_timeout_data,
(uint32_t)timeout * 1000);
}
static void s0ix_complete_resume(struct host_sleep_event_context *ctx)
static void sleep_complete_resume(struct host_sleep_event_context *ctx)
{
hook_call_deferred(&s0ix_transition_timeout_data, -1);
ctx->sleep_transitions = slp_s0ix_transitions;
hook_call_deferred(&sleep_transition_timeout_data, -1);
ctx->sleep_transitions = sleep_signal_transitions;
/*
* If s0ix timed out and never transitioned, then the wake mask was
* modified to its s0ix state, so that the event wakes the system.
* Explicitly restore the wake mask to its S0 state now.
* If the sleep signal timed out and never transitioned, then the
* wake mask was modified to its suspend state (S0ix), so that the
* event wakes the system. Explicitly restore the wake mask to its
* S0 state now.
*/
power_update_wake_mask();
}
static void s0ix_reset_tracking(void)
static void sleep_reset_tracking(void)
{
slp_s0ix_transitions = 0;
slp_s0ix_timeout = 0;
sleep_signal_transitions = 0;
sleep_signal_timeout = 0;
}
#else /* !CONFIG_POWER_S0IX_FAILURE_DETECTION */
#else /* !CONFIG_POWER_SLEEP_FAILURE_DETECTION */
#define s0ix_suspend_transition()
#define s0ix_resume_transition()
#define s0ix_start_suspend(_ctx)
#define s0ix_complete_resume(_ctx)
#define s0ix_reset_tracking()
#define sleep_suspend_transition()
#define sleep_resume_transition()
#define sleep_start_suspend(_ctx)
#define sleep_complete_resume(_ctx)
#define sleep_reset_tracking()
#endif /* CONFIG_POWER_S0IX_FAILURE_DETECTION */
#endif /* CONFIG_POWER_SLEEP_FAILURE_DETECTION */
void power_reset_host_sleep_state(void)
{
power_set_host_sleep_state(HOST_SLEEP_EVENT_DEFAULT_RESET);
s0ix_reset_tracking();
sleep_reset_tracking();
power_chipset_handle_host_sleep_event(HOST_SLEEP_EVENT_DEFAULT_RESET,
NULL);
}
@ -421,8 +427,8 @@ enum power_state common_intel_x86_power_handle_state(enum power_state state)
chipset_get_sleep_signal(SYS_SLEEP_S0IX) == 0) {
return POWER_S0S0ix;
} else {
s0ix_transition(S0IX_NOTIFY_RESUME,
HOOK_CHIPSET_RESUME);
sleep_notify_transition(SLEEP_NOTIFY_RESUME,
HOOK_CHIPSET_RESUME);
#endif
}
@ -536,13 +542,13 @@ enum power_state common_intel_x86_power_handle_state(enum power_state state)
#ifdef CONFIG_POWER_S0IX
case POWER_S0S0ix:
/*
* Call hooks only if we haven't notified listeners of S0ix
* suspend.
*/
s0ix_transition(S0IX_NOTIFY_SUSPEND, HOOK_CHIPSET_SUSPEND);
s0ix_suspend_transition();
sleep_notify_transition(SLEEP_NOTIFY_SUSPEND,
HOOK_CHIPSET_SUSPEND);
sleep_suspend_transition();
/*
* Enable idle task deep sleep. Allow the low power idle task
@ -558,7 +564,7 @@ enum power_state common_intel_x86_power_handle_state(enum power_state state)
*/
disable_sleep(SLEEP_MASK_AP_RUN);
s0ix_resume_transition();
sleep_resume_transition();
return POWER_S0;
#endif
@ -669,23 +675,23 @@ __override void power_chipset_handle_host_sleep_event(
if (state == HOST_SLEEP_EVENT_S0IX_SUSPEND) {
/*
* Indicate to power state machine that a new host event for
* s0ix suspend has been received and so chipset suspend
* s0ix/s3 suspend has been received and so chipset suspend
* notification needs to be sent to listeners.
*/
s0ix_notify = S0IX_NOTIFY_SUSPEND;
sleep_notify = SLEEP_NOTIFY_SUSPEND;
s0ix_start_suspend(ctx);
sleep_start_suspend(ctx);
power_signal_enable_interrupt(sleep_sig[SYS_SLEEP_S0IX]);
} else if (state == HOST_SLEEP_EVENT_S0IX_RESUME) {
/*
* Wake up chipset task and indicate to power state machine that
* listeners need to be notified of chipset resume.
*/
s0ix_notify = S0IX_NOTIFY_RESUME;
sleep_notify = SLEEP_NOTIFY_RESUME;
task_wake(TASK_ID_CHIPSET);
lpc_s0ix_resume_restore_masks();
power_signal_disable_interrupt(sleep_sig[SYS_SLEEP_S0IX]);
s0ix_complete_resume(ctx);
sleep_complete_resume(ctx);
} else if (state == HOST_SLEEP_EVENT_DEFAULT_RESET) {
power_signal_disable_interrupt(sleep_sig[SYS_SLEEP_S0IX]);