aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/serio/i8042.c
diff options
context:
space:
mode:
authorAndrey Moiseev <o2g.org.ru@gmail.com>2013-09-16 18:17:31 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-09-18 15:22:06 -0400
commit2f0d2604134880f739642fd7c3ae55db33c838e7 (patch)
tree8bde47595130fca3526efb343e2f3a2ed9b6901c /drivers/input/serio/i8042.c
parent049d75f72d9b1cce0f5ca66ea324f0b5318046eb (diff)
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>
Diffstat (limited to 'drivers/input/serio/i8042.c')
-rw-r--r--drivers/input/serio/i8042.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 78e4de42efaa..52c9ebf94729 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -223,21 +223,26 @@ static int i8042_flush(void)
223{ 223{
224 unsigned long flags; 224 unsigned long flags;
225 unsigned char data, str; 225 unsigned char data, str;
226 int i = 0; 226 int count = 0;
227 int retval = 0;
227 228
228 spin_lock_irqsave(&i8042_lock, flags); 229 spin_lock_irqsave(&i8042_lock, flags);
229 230
230 while (((str = i8042_read_status()) & I8042_STR_OBF) && (i < I8042_BUFFER_SIZE)) { 231 while ((str = i8042_read_status()) & I8042_STR_OBF) {
231 udelay(50); 232 if (count++ < I8042_BUFFER_SIZE) {
232 data = i8042_read_data(); 233 udelay(50);
233 i++; 234 data = i8042_read_data();
234 dbg("%02x <- i8042 (flush, %s)\n", 235 dbg("%02x <- i8042 (flush, %s)\n",
235 data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); 236 data, str & I8042_STR_AUXDATA ? "aux" : "kbd");
237 } else {
238 retval = -EIO;
239 break;
240 }
236 } 241 }
237 242
238 spin_unlock_irqrestore(&i8042_lock, flags); 243 spin_unlock_irqrestore(&i8042_lock, flags);
239 244
240 return i; 245 return retval;
241} 246}
242 247
243/* 248/*
@@ -849,7 +854,7 @@ static int __init i8042_check_aux(void)
849 854
850static int i8042_controller_check(void) 855static int i8042_controller_check(void)
851{ 856{
852 if (i8042_flush() == I8042_BUFFER_SIZE) { 857 if (i8042_flush()) {
853 pr_err("No controller found\n"); 858 pr_err("No controller found\n");
854 return -ENODEV; 859 return -ENODEV;
855 } 860 }