| From ce84ebf68593dad865b359752712f4d4ed275e52 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 2 Oct 2025 19:30:58 +0000 |
| Subject: HID: logitech-hidpp: Do not assume FAP in hidpp_send_message_sync() |
| |
| From: Mavroudis Chatzilazaridis <mavchatz@protonmail.com> |
| |
| [ Upstream commit aba7963544d47d82cdf36602a6678a093af0299d ] |
| |
| Currently, hidpp_send_message_sync() retries sending the message when the |
| device returns a busy error code, specifically HIDPP20_ERROR_BUSY, which |
| has a different meaning under RAP. This ends up being a problem because |
| this function is used for both FAP and RAP messages. |
| |
| This issue is not noticeable on older receivers with unreachable devices |
| since they return HIDPP_ERROR_RESOURCE_ERROR (0x09), which is not equal to |
| HIDPP20_ERROR_BUSY (0x08). |
| |
| However, newer receivers return HIDPP_ERROR_UNKNOWN_DEVICE (0x08) which |
| happens to equal to HIDPP20_ERROR_BUSY, causing unnecessary retries when |
| the device is not actually busy. |
| |
| This is resolved by checking if the error response is FAP or RAP and |
| picking the respective ERROR_BUSY code. |
| |
| Fixes: 60165ab774cb ("HID: logitech-hidpp: rework one more time the retries attempts") |
| Signed-off-by: Mavroudis Chatzilazaridis <mavchatz@protonmail.com> |
| Tested-by: Stuart Hayhurst <stuart.a.hayhurst@gmail.com> |
| Signed-off-by: Jiri Kosina <jkosina@suse.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/hid/hid-logitech-hidpp.c | 9 +++++++-- |
| 1 file changed, 7 insertions(+), 2 deletions(-) |
| |
| diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c |
| index 3a2c1e48aba20..5a2fe703cf57b 100644 |
| --- a/drivers/hid/hid-logitech-hidpp.c |
| +++ b/drivers/hid/hid-logitech-hidpp.c |
| @@ -351,10 +351,15 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp, |
| |
| do { |
| ret = __do_hidpp_send_message_sync(hidpp, message, response); |
| - if (ret != HIDPP20_ERROR_BUSY) |
| + if (response->report_id == REPORT_ID_HIDPP_SHORT && |
| + ret != HIDPP_ERROR_BUSY) |
| + break; |
| + if ((response->report_id == REPORT_ID_HIDPP_LONG || |
| + response->report_id == REPORT_ID_HIDPP_VERY_LONG) && |
| + ret != HIDPP20_ERROR_BUSY) |
| break; |
| |
| - dbg_hid("%s:got busy hidpp 2.0 error %02X, retrying\n", __func__, ret); |
| + dbg_hid("%s:got busy hidpp error %02X, retrying\n", __func__, ret); |
| } while (--max_retries); |
| |
| mutex_unlock(&hidpp->send_mutex); |
| -- |
| 2.51.0 |
| |