Skip to content

Commit 586e8fe

Browse files
hadessbentiss
authored andcommitted
HID: logitech-hidpp: Retry commands when device is busy
Handle the busy error coming from the device or receiver. The documentation says a busy error can be returned when: " Device (or receiver) cannot answer immediately to this request for any reason i.e: - already processing a request from the same or another SW - pipe full " Signed-off-by: Bastien Nocera <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Benjamin Tissoires <[email protected]>
1 parent a47a3b7 commit 586e8fe

File tree

1 file changed

+30
-24
lines changed

1 file changed

+30
-24
lines changed

drivers/hid/hid-logitech-hidpp.c

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp,
283283
struct hidpp_report *response)
284284
{
285285
int ret;
286+
int max_retries = 3;
286287

287288
mutex_lock(&hidpp->send_mutex);
288289

@@ -295,34 +296,39 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp,
295296
*/
296297
*response = *message;
297298

298-
ret = __hidpp_send_report(hidpp->hid_dev, message);
299+
for (; max_retries != 0; max_retries--) {
300+
ret = __hidpp_send_report(hidpp->hid_dev, message);
299301

300-
if (ret) {
301-
dbg_hid("__hidpp_send_report returned err: %d\n", ret);
302-
memset(response, 0, sizeof(struct hidpp_report));
303-
goto exit;
304-
}
302+
if (ret) {
303+
dbg_hid("__hidpp_send_report returned err: %d\n", ret);
304+
memset(response, 0, sizeof(struct hidpp_report));
305+
goto exit;
306+
}
305307

306-
if (!wait_event_timeout(hidpp->wait, hidpp->answer_available,
307-
5*HZ)) {
308-
dbg_hid("%s:timeout waiting for response\n", __func__);
309-
memset(response, 0, sizeof(struct hidpp_report));
310-
ret = -ETIMEDOUT;
311-
}
308+
if (!wait_event_timeout(hidpp->wait, hidpp->answer_available,
309+
5*HZ)) {
310+
dbg_hid("%s:timeout waiting for response\n", __func__);
311+
memset(response, 0, sizeof(struct hidpp_report));
312+
ret = -ETIMEDOUT;
313+
}
312314

313-
if (response->report_id == REPORT_ID_HIDPP_SHORT &&
314-
response->rap.sub_id == HIDPP_ERROR) {
315-
ret = response->rap.params[1];
316-
dbg_hid("%s:got hidpp error %02X\n", __func__, ret);
317-
goto exit;
318-
}
315+
if (response->report_id == REPORT_ID_HIDPP_SHORT &&
316+
response->rap.sub_id == HIDPP_ERROR) {
317+
ret = response->rap.params[1];
318+
dbg_hid("%s:got hidpp error %02X\n", __func__, ret);
319+
goto exit;
320+
}
319321

320-
if ((response->report_id == REPORT_ID_HIDPP_LONG ||
321-
response->report_id == REPORT_ID_HIDPP_VERY_LONG) &&
322-
response->fap.feature_index == HIDPP20_ERROR) {
323-
ret = response->fap.params[1];
324-
dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret);
325-
goto exit;
322+
if ((response->report_id == REPORT_ID_HIDPP_LONG ||
323+
response->report_id == REPORT_ID_HIDPP_VERY_LONG) &&
324+
response->fap.feature_index == HIDPP20_ERROR) {
325+
ret = response->fap.params[1];
326+
if (ret != HIDPP20_ERROR_BUSY) {
327+
dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret);
328+
goto exit;
329+
}
330+
dbg_hid("%s:got busy hidpp 2.0 error %02X, retrying\n", __func__, ret);
331+
}
326332
}
327333

328334
exit:

0 commit comments

Comments
 (0)