diff options
author | Andrey Moiseev <o2g.org.ru@gmail.com> | 2013-09-16 18:17:31 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-09-18 15:22:06 -0400 |
commit | 2f0d2604134880f739642fd7c3ae55db33c838e7 (patch) | |
tree | 8bde47595130fca3526efb343e2f3a2ed9b6901c /drivers/input/serio/i8042.c | |
parent | 049d75f72d9b1cce0f5ca66ea324f0b5318046eb (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.c | 23 |
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 | ||
850 | static int i8042_controller_check(void) | 855 | static 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 | } |