diff options
author | Ting Shen <phoenixshen@google.com> | 2020-03-11 18:05:45 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-03-13 08:59:50 +0000 |
commit | 9a5de6a2ae81c534356e0fbd2bf8cfee54856674 (patch) | |
tree | 48372cfeaa50c4f8d43331e908fc77e6231ca00e /common/keyboard_mkbp.c | |
parent | af32d7eb68444fa5fe7b863e65063d75a3aa5007 (diff) | |
download | chrome-ec-9a5de6a2ae81c534356e0fbd2bf8cfee54856674.tar.gz |
mkbp: keyboard_clear_buffer should only drop keyboard events
Two hooks in HOOK_LID_CHANGE has race condition:
1) keyboard_lid_change() wakes up KEYSCAN task and calls
keyboard_clear_buffer() to clear the MKBP fifo
2) mkbp_lid_change() pushes EC_MKBP_LID_OPEN event into the same fifo.
mkbp_lid_change has lowest priority, so usually the flow looks like
keyboard_lid_change()
keyboard_clear_buffer()
mkbp_lid_change()
EC_MKBP_LID_OPEN event inserted after buffer clear, everything good.
But in Juniper, we found that sometimes the flow becomes
keyboard_lid_change()
mkbp_lid_change()
keyboard_clear_buffer()
And cause the EC_MKBP_LID_OPEN dropped before sending to host.
To fix this, change the behavior of keyboard_clear_buffer() to keep all
non-keyboard events inside the queue. So EC_MKBP_LID_OPEN will never be
removed regardless of how task is scheduled.
BUG=b:149880594
TEST=1) On Jacuzzi, host able to receive lid switch event
2) Set the priority mkbp_lid_change to 1(highest) and verify 1)
still works
BRANCH=kukui
Signed-off-by: Ting Shen <phoenixshen@google.com>
Change-Id: I55d7c6c45ecb6505134e430689887ce98ea0c29b
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2098018
Reviewed-by: Eric Yilun Lin <yllin@chromium.org>
Reviewed-by: Jett Rink <jettrink@chromium.org>
Tested-by: Ting Shen <phoenixshen@chromium.org>
Commit-Queue: Ting Shen <phoenixshen@chromium.org>
Diffstat (limited to 'common/keyboard_mkbp.c')
-rw-r--r-- | common/keyboard_mkbp.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/common/keyboard_mkbp.c b/common/keyboard_mkbp.c index ff7ddc4d5c..0902a434d7 100644 --- a/common/keyboard_mkbp.c +++ b/common/keyboard_mkbp.c @@ -164,7 +164,36 @@ static int fifo_remove(uint8_t *buffp) void keyboard_clear_buffer(void) { - mkbp_clear_fifo(); + int i, new_fifo_entries = 0; + + CPRINTS("clear keyboard MKBP fifo"); + + /* + * Order of these locks is important to prevent deadlock since + * mkbp_fifo_add() may call fifo_remove(). + */ + mutex_lock(&fifo_add_mutex); + mutex_lock(&fifo_remove_mutex); + + /* Reset the end position */ + fifo_end = fifo_start; + + for (i = 0; i < fifo_entries; i++) { + int cur = (fifo_start + i) % FIFO_DEPTH; + + /* Drop keyboard events */ + if (fifo[cur].event_type == EC_MKBP_EVENT_KEY_MATRIX) + continue; + + /* And move other events to the front */ + memmove(&fifo[fifo_end], &fifo[cur], sizeof(fifo[cur])); + fifo_end = (fifo_end + 1) % FIFO_DEPTH; + ++new_fifo_entries; + } + fifo_entries = new_fifo_entries; + + mutex_unlock(&fifo_remove_mutex); + mutex_unlock(&fifo_add_mutex); } void mkbp_clear_fifo(void) |