summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-10-04 16:22:53 -0700
committerGerrit <chrome-bot@google.com>2012-10-05 04:26:19 -0700
commita752e1f5d18ac5bd129dbc60ca74abfdcb47ea09 (patch)
tree57ba8c7d58727e59ec96b29375a9239850604c99
parent6d6cfad2a00e8448c731ab5581080a90f3bbeb25 (diff)
downloadchrome-ec-a752e1f5d18ac5bd129dbc60ca74abfdcb47ea09.tar.gz
link: fix race condition enabling keyboard interrupt
Previously, an edge on a keyboard row could be missed if it occurred after the last scan, but before interrupts are enabled. Now we explicitly check if any keys are down before waiting for an interrupt, and if any are, we simply don't wait to scan. BUG=chrome-os-partner:7484 BRANCH=link TEST=the race condition's really tricky to hit The best we can do for testing is to ensure that we ARE sleeping in the normal case where no keys are held down. For that, don't press any keys, and run 'taskinfo' from the EC console twice about 10 sec apart. Both printouts should have virtually identical times for the KEYSCAN task. Change-Id: I4e0ef18a2d71d0a5d3655742bd49fc15afc4aaed Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/34709 Reviewed-by: Simon Glass <sjg@chromium.org> Reviewed-by: Yung-Chieh Lo <yjlou@chromium.org>
-rw-r--r--chip/lm4/keyboard_scan.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/chip/lm4/keyboard_scan.c b/chip/lm4/keyboard_scan.c
index ea4b5b82cd..33c894e8c1 100644
--- a/chip/lm4/keyboard_scan.c
+++ b/chip/lm4/keyboard_scan.c
@@ -83,7 +83,7 @@ static const uint8_t actual_key_masks[4][KB_COLS] = {
#define MASK_INDEX_KEY_H 6
#define MASK_VALUE_KEY_H 0x02
-static void wait_for_interrupt(void)
+static void enable_interrupt(void)
{
CPRINTF("[%T KB wait]\n");
@@ -442,11 +442,19 @@ void keyboard_scan_task(void)
while (1) {
/* Enable all outputs */
- wait_for_interrupt();
+ enable_interrupt();
/* Wait for scanning enabled and key pressed. */
do {
- task_wait_event(-1);
+ /*
+ * Don't wait if scanning is enabled and a key is
+ * already pressed. This prevents a race between the
+ * user pressing a key and enable_interrupt()
+ * starting to pay attention to edges.
+ */
+ if ((lm4_read_raw_row_state() == 0xff) ||
+ !lm4_get_scanning_enabled())
+ task_wait_event(-1);
} while (!lm4_get_scanning_enabled());
enter_polling_mode();
@@ -487,8 +495,8 @@ void keyboard_enable_scanning(int enable)
if (enable) {
/*
* A power button press had tri-stated all columns (see the
- * 'else' statement below), we need a wake-up to unlock the
- * task_wait_event() loop after wait_for_interrupt().
+ * 'else' statement below); we need a wake-up to unlock the
+ * task_wait_event() loop after enable_interrupt().
*/
task_wake(TASK_ID_KEYSCAN);
} else {