Skip to content

Commit c472d33

Browse files
committed
Input: cypress_ps2 - fix waiting for command response
Commit 8bccf66 ("Input: cypress_ps2 - report timeouts when reading command status") uncovered an existing problem with cypress_ps2 driver: it tries waiting on a PS/2 device waitqueue without using the rest of libps2. Unfortunately without it nobody signals wakeup for the waiting process, and each "extended" command was timing out. But the rest of the code simply did not notice it. Fix this by switching from homegrown way of sending request to get command response and reading it to standard ps2_command() which does the right thing. Reported-by: Woody Suwalski <[email protected]> Tested-by: Woody Suwalski <[email protected]> Fixes: 8bccf66 ("Input: cypress_ps2 - report timeouts when reading command status") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 4e870e6 commit c472d33

File tree

1 file changed

+13
-45
lines changed

1 file changed

+13
-45
lines changed

drivers/input/mouse/cypress_ps2.c

Lines changed: 13 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -91,48 +91,6 @@ static int cypress_ps2_ext_cmd(struct psmouse *psmouse, u8 prefix, u8 nibble)
9191
return rc;
9292
}
9393

94-
static int cypress_ps2_read_cmd_status(struct psmouse *psmouse,
95-
u8 cmd, u8 *param)
96-
{
97-
struct ps2dev *ps2dev = &psmouse->ps2dev;
98-
enum psmouse_state old_state;
99-
int pktsize;
100-
int rc;
101-
102-
ps2_begin_command(ps2dev);
103-
104-
old_state = psmouse->state;
105-
psmouse->state = PSMOUSE_CMD_MODE;
106-
psmouse->pktcnt = 0;
107-
108-
pktsize = (cmd == CYTP_CMD_READ_TP_METRICS) ? 8 : 3;
109-
memset(param, 0, pktsize);
110-
111-
rc = cypress_ps2_sendbyte(psmouse, PSMOUSE_CMD_GETINFO & 0xff);
112-
if (rc)
113-
goto out;
114-
115-
if (!wait_event_timeout(ps2dev->wait,
116-
psmouse->pktcnt >= pktsize,
117-
msecs_to_jiffies(CYTP_CMD_TIMEOUT))) {
118-
rc = -ETIMEDOUT;
119-
goto out;
120-
}
121-
122-
memcpy(param, psmouse->packet, pktsize);
123-
124-
psmouse_dbg(psmouse, "Command 0x%02x response data (0x): %*ph\n",
125-
cmd, pktsize, param);
126-
127-
out:
128-
psmouse->state = old_state;
129-
psmouse->pktcnt = 0;
130-
131-
ps2_end_command(ps2dev);
132-
133-
return rc;
134-
}
135-
13694
static bool cypress_verify_cmd_state(struct psmouse *psmouse, u8 cmd, u8* param)
13795
{
13896
bool rate_match = false;
@@ -166,6 +124,8 @@ static bool cypress_verify_cmd_state(struct psmouse *psmouse, u8 cmd, u8* param)
166124
static int cypress_send_ext_cmd(struct psmouse *psmouse, u8 cmd, u8 *param)
167125
{
168126
u8 cmd_prefix = PSMOUSE_CMD_SETRES & 0xff;
127+
unsigned int resp_size = cmd == CYTP_CMD_READ_TP_METRICS ? 8 : 3;
128+
unsigned int ps2_cmd = (PSMOUSE_CMD_GETINFO & 0xff) | (resp_size << 8);
169129
int tries = CYTP_PS2_CMD_TRIES;
170130
int error;
171131

@@ -179,10 +139,18 @@ static int cypress_send_ext_cmd(struct psmouse *psmouse, u8 cmd, u8 *param)
179139
cypress_ps2_ext_cmd(psmouse, cmd_prefix, DECODE_CMD_BB(cmd));
180140
cypress_ps2_ext_cmd(psmouse, cmd_prefix, DECODE_CMD_AA(cmd));
181141

182-
error = cypress_ps2_read_cmd_status(psmouse, cmd, param);
183-
if (!error && cypress_verify_cmd_state(psmouse, cmd, param))
184-
return 0;
142+
error = ps2_command(&psmouse->ps2dev, param, ps2_cmd);
143+
if (error) {
144+
psmouse_dbg(psmouse, "Command 0x%02x failed: %d\n",
145+
cmd, error);
146+
} else {
147+
psmouse_dbg(psmouse,
148+
"Command 0x%02x response data (0x): %*ph\n",
149+
cmd, resp_size, param);
185150

151+
if (cypress_verify_cmd_state(psmouse, cmd, param))
152+
return 0;
153+
}
186154
} while (--tries > 0);
187155

188156
return -EIO;

0 commit comments

Comments
 (0)