diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2023-05-11 11:52:45 -0700 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2023-05-18 11:40:32 -0700 |
commit | 7d674f9150c361e5b992551b46516d41eede3722 (patch) | |
tree | dbdf506fbd48d139cd86fa687481196d878f4b8c /drivers/input | |
parent | 1db0fd245b6016c21097b5ae01aeb447484de951 (diff) |
Input: libps2 - fix aborting PS/2 commands
When aborting PS/2 command the kernel should [re]set all flags before
waking up waiters, otherwise waiting thread may read obsolete values
of flags.
Reported-by: Raul Rangel <rrangel@chromium.org>
Reviewed-by: Raul E Rangel <rrangel@chromium.org>
Link: https://lore.kernel.org/r/20230511185252.386941-6-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/serio/libps2.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 14b70a78875d..09eb605364bb 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -478,15 +478,22 @@ bool ps2_handle_response(struct ps2dev *ps2dev, u8 data) } EXPORT_SYMBOL(ps2_handle_response); +/* + * Clears state of PS/2 device after communication error by resetting majority + * of flags and waking up waiters, if any. + */ void ps2_cmd_aborted(struct ps2dev *ps2dev) { - if (ps2dev->flags & PS2_FLAG_ACK) + unsigned long old_flags = ps2dev->flags; + + /* reset all flags except last nak */ + ps2dev->flags &= PS2_FLAG_NAK; + + if (old_flags & PS2_FLAG_ACK) ps2dev->nak = 1; - if (ps2dev->flags & (PS2_FLAG_ACK | PS2_FLAG_CMD)) + if (old_flags & (PS2_FLAG_ACK | PS2_FLAG_CMD)) wake_up(&ps2dev->wait); - /* reset all flags except last nack */ - ps2dev->flags &= PS2_FLAG_NAK; } EXPORT_SYMBOL(ps2_cmd_aborted); |