summaryrefslogtreecommitdiff
path: root/common/keyboard_mkbp.c
diff options
context:
space:
mode:
authorTing Shen <phoenixshen@google.com>2020-03-11 18:05:45 +0800
committerCommit Bot <commit-bot@chromium.org>2020-03-13 08:59:50 +0000
commit9a5de6a2ae81c534356e0fbd2bf8cfee54856674 (patch)
tree48372cfeaa50c4f8d43331e908fc77e6231ca00e /common/keyboard_mkbp.c
parentaf32d7eb68444fa5fe7b863e65063d75a3aa5007 (diff)
downloadchrome-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.c31
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)