Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: i8042 - i8042_flush fix for a full 8042 buffer

When 8042 internal data buffer is full, the driver
erroneously decides that the controller is not present.

i8042_flush returns the number of flushed bytes, which is
in 0 - I8042_BUFFER_SIZE range inclusive. Therefore, i8042_flush
has no way to indicate an error. Moreover i8042_controller_check
takes initially full buffer (i8042_flush returned
I8042_BUFFER_SIZE) as a sign of absence of the controller.

Let's change i8042 to return success/error instead and make sure
we do not return error prematurely.

Signed-off-by: Andrey Moiseev <o2g.org.ru@gmail.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Andrey Moiseev and committed by
Dmitry Torokhov
2f0d2604 049d75f7

+14 -9
+14 -9
drivers/input/serio/i8042.c
··· 223 223 { 224 224 unsigned long flags; 225 225 unsigned char data, str; 226 - int i = 0; 226 + int count = 0; 227 + int retval = 0; 227 228 228 229 spin_lock_irqsave(&i8042_lock, flags); 229 230 230 - while (((str = i8042_read_status()) & I8042_STR_OBF) && (i < I8042_BUFFER_SIZE)) { 231 - udelay(50); 232 - data = i8042_read_data(); 233 - i++; 234 - dbg("%02x <- i8042 (flush, %s)\n", 235 - data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); 231 + while ((str = i8042_read_status()) & I8042_STR_OBF) { 232 + if (count++ < I8042_BUFFER_SIZE) { 233 + udelay(50); 234 + data = i8042_read_data(); 235 + dbg("%02x <- i8042 (flush, %s)\n", 236 + data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); 237 + } else { 238 + retval = -EIO; 239 + break; 240 + } 236 241 } 237 242 238 243 spin_unlock_irqrestore(&i8042_lock, flags); 239 244 240 - return i; 245 + return retval; 241 246 } 242 247 243 248 /* ··· 854 849 855 850 static int i8042_controller_check(void) 856 851 { 857 - if (i8042_flush() == I8042_BUFFER_SIZE) { 852 + if (i8042_flush()) { 858 853 pr_err("No controller found\n"); 859 854 return -ENODEV; 860 855 }