diff options
author | Evan Green <evgreen@chromium.org> | 2019-03-01 13:09:08 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-03-28 19:04:16 -0700 |
commit | 49b8070623ee1cecac387488ce668a4a11403653 (patch) | |
tree | bf4cc3078a496e7a9c8aa14c902be79cd3897c69 /power/common.c | |
parent | a029c7a27f3bd1a1066db9c167c6166688fe4ef3 (diff) | |
download | chrome-ec-49b8070623ee1cecac387488ce668a4a11403653.tar.gz |
power/intel_x86: Introduce s0ix failure detection
This change introduces logic in the EC that can detect if the host
attempted to go into S0ix, but never made it. The host already sends
commands indicating its intent to enter S0ix, and the EC has a SLP_S0
line that gets asserted by the AP when it actually enters S0ix.
All that's needed to monitor failures is to arm a timer when receiving
the S0ix suspend message. If the SLP_S0 pin goes low, then the suspend
occurred and the timer is canceled. If the timer expires before SLP_S0
goes low, then the EC wakes the AP up, since it has entered a shallower
idle state than intended, and should be alerted to avoid short battery
life.
The timer is also started when SLP_S0 is deasserted on resume. The
SoC comes out of S0ix to perform housekeeping activities unbeknownst
to Linux. In cases where housekeeping fails to suspend all the way back
down, this timer will wake the AP. Additionally, the number of S0ix
transitions is reported on resume. This enabled the AP to analyze the
amount of "sleepwalking" that is done, and can complain if it seems to
be waking up too often.
Design doc at:
https://docs.google.com/document/d/1mY-v02KAuOyET3td9s5GnxeUgMiAcD058oLEo57DZpY/edit
BUG=b:123716513
BRANCH=None
TEST=Test S0ix on hatch with modified code that forces a timeout,
use ectool to send messages manually before and after timeout,
Hack Linux to fail suspend very late to verify no regressions.
Signed-off-by: Evan Green <evgreen@chromium.org>
Change-Id: Ia64b496675a13dbed4ef74637f51e39eee68aa1a
Reviewed-on: https://chromium-review.googlesource.com/1501512
Commit-Ready: Evan Green <evgreen@chromium.org>
Tested-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-by: Karthikeyan Ramasubramanian <kramasub@chromium.org>
Diffstat (limited to 'power/common.c')
-rw-r--r-- | power/common.c | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/power/common.c b/power/common.c index cccb34911a..09501a16ec 100644 --- a/power/common.c +++ b/power/common.c @@ -873,37 +873,69 @@ DECLARE_CONSOLE_COMMAND(pause_in_s5, command_pause_in_s5, static enum host_sleep_event host_sleep_state; void __attribute__((weak)) -power_chipset_handle_host_sleep_event(enum host_sleep_event state) +power_chipset_handle_host_sleep_event(enum host_sleep_event state, + struct host_sleep_event_context *ctx) { /* Default weak implementation -- no action required. */ } static int host_command_host_sleep_event(struct host_cmd_handler_args *args) { - const struct ec_params_host_sleep_event *p = args->params; + const struct ec_params_host_sleep_event_v1 *p = args->params; + struct ec_response_host_sleep_event_v1 *r = args->response; + struct host_sleep_event_context ctx; + enum host_sleep_event state = p->sleep_event; - host_sleep_state = p->sleep_event; + host_sleep_state = state; + switch (state) { + case HOST_SLEEP_EVENT_S3_SUSPEND: + case HOST_SLEEP_EVENT_S0IX_SUSPEND: + case HOST_SLEEP_EVENT_S3_WAKEABLE_SUSPEND: + ctx.sleep_timeout_ms = EC_HOST_SLEEP_TIMEOUT_DEFAULT; + + /* The original version contained only state. */ + if (args->version >= 1) + ctx.sleep_timeout_ms = + p->suspend_params.sleep_timeout_ms; + + break; + + default: + break; + } - power_chipset_handle_host_sleep_event(host_sleep_state); + power_chipset_handle_host_sleep_event(host_sleep_state, &ctx); + switch (state) { + case HOST_SLEEP_EVENT_S3_RESUME: + case HOST_SLEEP_EVENT_S0IX_RESUME: + if (args->version >= 1) { + r->resume_response.sleep_transitions = + ctx.sleep_transitions; + + args->response_size = sizeof(*r); + } + + break; + + default: + break; + } return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_HOST_SLEEP_EVENT, host_command_host_sleep_event, - EC_VER_MASK(0)); + EC_VER_MASK(0) | EC_VER_MASK(1)); enum host_sleep_event power_get_host_sleep_state(void) { return host_sleep_state; } -#ifdef CONFIG_POWER_S0IX -void power_reset_host_sleep_state(void) +void power_set_host_sleep_state(enum host_sleep_event state) { - host_sleep_state = HOST_SLEEP_EVENT_DEFAULT_RESET; - power_chipset_handle_host_sleep_event(host_sleep_state); + host_sleep_state = state; } -#endif /* CONFIG_POWER_S0IX */ #endif /* CONFIG_POWER_TRACK_HOST_SLEEP_STATE */ |