summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Barnes <robbarnes@google.com>2022-03-16 06:20:15 -0600
committerCommit Bot <commit-bot@chromium.org>2022-03-17 20:28:54 +0000
commit4412c9404d6e28e168ed2a4856d6d678707c8967 (patch)
tree730e26a7d6c0b37ce2f9494a47eb21986c069493
parentc24772c046ec72364e61e694694dca7865de0570 (diff)
downloadchrome-ec-4412c9404d6e28e168ed2a4856d6d678707c8967.tar.gz
power: Add chipset and board callbacks for sleep hangs
Instead of passing a callback to host_sleep, define overridable board and chipset callbacks for sleep hang detection. Introduce a sleep_hang_type enum that identifies the type of sleep hang (suspend or resume). These changes make it eaier for boards to implement custom logic to handle sleep hangs. BUG=b:218892808 BRANCH=guybrush TEST=Observe suspend hang detection on Nipperkin with KI Change-Id: Ifacf90f808b1447633f7cfc2d570209d1e233950 Signed-off-by: Rob Barnes <robbarnes@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3529606 Reviewed-by: Diana Z <dzigterman@chromium.org>
-rw-r--r--include/power.h40
-rw-r--r--power/amd_x86.c5
-rw-r--r--power/host_sleep.c35
-rw-r--r--power/intel_x86.c5
-rw-r--r--power/mt8183.c5
-rw-r--r--power/mt8186.c5
-rw-r--r--power/mt8192.c5
-rw-r--r--power/qcom.c5
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) {