summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-09-17 12:40:01 -0700
committerGerrit <chrome-bot@google.com>2012-09-17 18:06:33 -0700
commit72948eaf4e7829ee5af59f2d7e3edd0b983723ef (patch)
tree283ca00e54c949688d46fc0d81fe6ebb89f90b80
parentc0a2d9befb9863f4569c302b5137e6a666722436 (diff)
downloadchrome-ec-72948eaf4e7829ee5af59f2d7e3edd0b983723ef.tar.gz
Improve handling of bursts of port 80 writes
Loop on FRMH bit set in the interrupt handler. This has 2 benefits: 1) FRMH is checked every LPC interrupt. So if port 80 gets stuck, any LPC activity like keyboard or host commands will unstick it. 2) Bursts of rapid writes to port 80 are captured more accurately. This also seems to prevent the port 80 channel from getting stuck. There's a small drawback that if the host spams port 80 non-stop for several seconds it can watchdog the EC, but if the host has access to write to I/O ports it could already accomplish a similar result simply by writing the 0xd1 reboot command to the host interface. BUG=chrome-os-partner:12349 BRANCH=link TEST=manual 1. From a root shell, 'ectool port80flood' repeatedly (20x or so). 2. Reboot. Port 80 codes should still be captured. Change-Id: I7a51dfe6a384a0d08cfeb91a539217fc59488637 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/33444 Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
-rw-r--r--chip/lm4/lpc.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c
index 34929285a2..21314267b2 100644
--- a/chip/lm4/lpc.c
+++ b/chip/lm4/lpc.c
@@ -539,8 +539,14 @@ static void lpc_interrupt(void)
}
#endif
- /* Handle port 80 writes (CH0MIS1) */
- if (mis & LM4_LPC_INT_MASK(LPC_CH_PORT80, 2))
+ /*
+ * Handle port 80 writes (CH0MIS1). Due to crosbug.com/p/12349 the
+ * interrupt status (mis & LM4_LPC_INT_MASK(LPC_CH_PORT80, 2))
+ * apparently gets lost on back-to-back writes to port 80, so check the
+ * FRMH bit in the channel status register to see if a write is
+ * pending. Loop to handle bursts of back-to-back writes.
+ */
+ while (LM4_LPC_ST(LPC_CH_PORT80) & LM4_LPC_ST_FRMH)
port_80_write(LPC_POOL_PORT80[0]);
#ifdef CONFIG_TASK_I8042CMD