summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorWai-Hong Tam <waihong@google.com>2020-07-30 14:17:29 -0700
committerCommit Bot <commit-bot@chromium.org>2020-08-01 02:36:15 +0000
commitd334050b8b0755201f1909002b3b01392cba2c23 (patch)
tree5292dd5cc0355484e2ef18be04debb0232a87763 /common
parent744a611d80219aa430501e2a1923e2d06af7fe0a (diff)
downloadchrome-ec-d334050b8b0755201f1909002b3b01392cba2c23.tar.gz
power_button: Use polling instead of forever wait for release
The existing logic may cause infinite wait, if the power_button_wait_for_release() is called during debouncing, i.e. after the interrupt is triggered, but before the debouncing function power_button_change_deferred() is called. The interrupt sets power_button_is_stable to 0. It makes entering the loop to wait for a event. After debouncing, if found out it is a false alarm, it sets power_button_is_stable back to 1 and does nothing. The HOOK_POWER_BUTTON_CHANGE is not notified. So no way to escape the loop. The HOOK_POWER_BUTTON_CHANGE is supposed to wake the task. This CL simply changes the logic to polling, that prevents the above forever wait issue. We use task_wait_event() instead of usleep() to wait. It will be woken up immediately if the power button is debouned and changed. However, it is not guaranteed, like the cases that the power button is debounced but not changed, or the power button has not been debounced. BRANCH=None BUG=b:161652942 TEST=Tested a previously failed scenario: waked from hibernate, checked AP auto-booting into S0, not stuck at S5S3. TEST=Tested the normal case: hold Refresh + Power -> release Refresh, checked staying in S5S3. Release power, checked transit to S0. Change-Id: I10b67513c232b7ebe26af4d5b88e064cea9e6dc7 Signed-off-by: Wai-Hong Tam <waihong@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2330577 Reviewed-by: Jett Rink <jettrink@chromium.org>
Diffstat (limited to 'common')
-rw-r--r--common/power_button.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/common/power_button.c b/common/power_button.c
index 2b4668b733..1ac3893492 100644
--- a/common/power_button.c
+++ b/common/power_button.c
@@ -82,14 +82,19 @@ int power_button_wait_for_release(int timeout_us)
while (!power_button_is_stable || power_button_is_pressed()) {
now = get_time();
- if (timeout_us < 0) {
- task_wait_event(-1);
- } else if (timestamp_expired(deadline, &now) ||
- (task_wait_event(deadline.val - now.val) ==
- TASK_EVENT_TIMER)) {
+ if (timeout_us >= 0 && timestamp_expired(deadline, &now)) {
CPRINTS("%s not released in time", power_button.name);
return EC_ERROR_TIMEOUT;
}
+ /*
+ * We use task_wait_event() instead of usleep() here. It will
+ * be woken up immediately if the power button is debouned and
+ * changed. However, it is not guaranteed, like the cases that
+ * the power button is debounced but not changed, or the power
+ * button has not been debounced.
+ */
+ task_wait_event(MIN(power_button.debounce_us,
+ deadline.val - now.val));
}
CPRINTS("%s released in time", power_button.name);