diff options
author | Furquan Shaikh <furquan@google.com> | 2018-10-26 14:13:37 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-10-30 01:04:55 -0700 |
commit | c334a73787bb869ddae19c5787a191062b5918ca (patch) | |
tree | 2e10b42db55953cd98c92b77a55cd42df1fd4059 /power | |
parent | 8a0ba88f26d5b806a503fc931c3fca5794a1d5c3 (diff) | |
download | chrome-ec-c334a73787bb869ddae19c5787a191062b5918ca.tar.gz |
power/common: Wait some time before updating wake masks
On platforms like KBL, the device keeps waking up periodically
for very short intervals to allow some SoC components to do
book-keeping activities. If the user happens to trigger EC-related
wake event during this short window, then the wakeup event could be
missed because it looks like the host is in S0 to the EC.
In order to avoid the race condition, update wake mask using a
deferred call to allow the system state to stabilize.
BUG=b:118490626
BRANCH=nocturne
TEST=No more lid open failures observed on nocturne.
Change-Id: I13f9f5760aaf7e54c676f43c48f9fc8de572fd01
Signed-off-by: Furquan Shaikh <furquan@google.com>
Reviewed-on: https://chromium-review.googlesource.com/1303133
Commit-Ready: Furquan Shaikh <furquan@chromium.org>
Tested-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'power')
-rw-r--r-- | power/common.c | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/power/common.c b/power/common.c index ddbfaebded..8a2770e03b 100644 --- a/power/common.c +++ b/power/common.c @@ -220,7 +220,8 @@ enum power_state power_get_state(void) #define DEFAULT_WAKE_MASK_S0IX (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) | \ EC_HOST_EVENT_MASK(EC_HOST_EVENT_MODE_CHANGE)) /* - * Set wake mask on edge of sleep state entry + * Set wake mask after power state has stabilized (5ms after power state + * change): * 1. On transition to S0, wake mask is reset. * 2. In non-S0 states, active mask set by host gets a higher preference. * 3. If host has not set any active mask, then check if a lazy mask exists @@ -228,11 +229,21 @@ enum power_state power_get_state(void) * 4. If state is S0ix and no lazy or active wake mask is set, then use default * S0ix mask to be compatible with older BIOS versions. * - * @param state New sleep state + * Reason for making this a deferred call is to avoid race conditions occurring + * from S0ix periodic wakes on the SoC. */ -static void power_set_active_wake_mask(enum power_state state) + +static void power_update_wake_mask_deferred(void); +DECLARE_DEFERRED(power_update_wake_mask_deferred); + +static void power_update_wake_mask_deferred(void) { host_event_t wake_mask; + enum power_state state; + + hook_call_deferred(&power_update_wake_mask_deferred_data, -1); + + state = power_get_state(); if (state == POWER_S0) wake_mask = 0; @@ -247,8 +258,27 @@ static void power_set_active_wake_mask(enum power_state state) lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, wake_mask); } + +static void power_set_active_wake_mask(void) +{ + /* + * Allow state machine to stabilize and update wake mask after 5msec. It + * was observed that on platforms where host wakes up periodically from + * S0ix for hardware book-keeping activities, there is a small window + * where host is not really up and running software, but still SLP_S0# + * is de-asserted and hence setting wake mask right away can cause user + * wake events to be missed. + * + * Time for deferred callback was chosen to be 5msec based on the fact + * that it takes ~2msec for the periodic wake cycle to complete on the + * host for KBL. + */ + hook_call_deferred(&power_update_wake_mask_deferred_data, + 5 * MSEC); +} + #else -static void power_set_active_wake_mask(enum power_state state) { } +static void power_set_active_wake_mask(void) { } #endif /** @@ -502,7 +532,7 @@ void chipset_task(void *u) /* Handle state changes */ if (new_state != state) { power_set_state(new_state); - power_set_active_wake_mask(new_state); + power_set_active_wake_mask(); } } } |