From a216a4b6e6f1fdfd3d1f20f03d9d45f05a63d643 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 17 Nov 2006 01:07:06 -0500 Subject: [PATCH] Input: i8042 - fix shutdown issue on some boxes with active MUXes MUX error handling has a workaround for KBCs that get confused which port data came from and signal MUXERR while data is actually good. Unfortunately this workaround hurts with KBCs that signal timeouts as 0xfc (spec says that only 0xfd, 0xfe and 0xff are alowed with MUXERR) since it causes endless attempts to rescan i8042 serio ports. The solution is to treat 0xfc as timeout (0xfe). Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index d365f227ac5..debe9445488 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -322,23 +322,27 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) dfl = 0; if (str & I8042_STR_MUXERR) { dbg("MUX error, status is %02x, data is %02x", str, data); - switch (data) { - default: /* * When MUXERR condition is signalled the data register can only contain * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately - * it is not always the case. Some KBC just get confused which port the - * data came from and signal error leaving the data intact. They _do not_ - * revert to legacy mode (actually I've never seen KBC reverting to legacy - * mode yet, when we see one we'll add proper handling). - * Anyway, we will assume that the data came from the same serio last byte + * it is not always the case. Some KBCs also report 0xfc when there is + * nothing connected to the port while others sometimes get confused which + * port the data came from and signal error leaving the data intact. They + * _do not_ revert to legacy mode (actually I've never seen KBC reverting + * to legacy mode yet, when we see one we'll add proper handling). + * Anyway, we process 0xfc, 0xfd, 0xfe and 0xff as timeouts, and for the + * rest assume that the data came from the same serio last byte * was transmitted (if transmission happened not too long ago). */ + + switch (data) { + default: if (time_before(jiffies, last_transmit + HZ/10)) { str = last_str; break; } /* fall through - report timeout */ + case 0xfc: case 0xfd: case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break; case 0xff: dfl = SERIO_PARITY; data = 0xfe; break; -- 2.41.1