diff options
author | Wai-Hong Tam <waihong@google.com> | 2020-07-30 14:17:29 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-08-01 02:36:15 +0000 |
commit | d334050b8b0755201f1909002b3b01392cba2c23 (patch) | |
tree | 5292dd5cc0355484e2ef18be04debb0232a87763 /common/power_button.c | |
parent | 744a611d80219aa430501e2a1923e2d06af7fe0a (diff) | |
download | chrome-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/power_button.c')
-rw-r--r-- | common/power_button.c | 15 |
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); |