Re: [PATCH v2] HID: logitech-hidpp: rework one more time the retries attempts

From: Benjamin Tissoires
Date: Fri Aug 25 2023 - 05:47:07 EST


Hi Thorsten,

On Fri, Aug 4, 2023 at 11:14 AM Linux regression tracking (Thorsten
Leemhuis) <regressions@xxxxxxxxxxxxx> wrote:
>
> Hi Benjamin, /me again! :-D
>
> On 12.07.23 17:02, bentiss@xxxxxxxxxx wrote:
> > From: Benjamin Tissoires <benjamin.tissoires@xxxxxxxxxx>
> >
> > Extract the internal code inside a helper function, fix the
> > initialization of the parameters used in the helper function
> > (`hidpp->answer_available` was not reset and `*response` wasn't either),
> > and use a `do {...} while();` loop.
> >
> > Fixes: 586e8fede795 ("HID: logitech-hidpp: Retry commands when device is busy")
> > Cc: stable@xxxxxxxxxxxxxxx
>
> From what I understood there was hope that this would cure the last
> remains (occasional init problems iirc) of the recent regressions with
> this driver and their fixes. But things look stalled. Is there a reason?
> Lack of reviews? Is there nevertheless hope that this will make it at
> least into 6.6?

Well, mostly lack of testing. But given that nothing happened, I just
sneaked it in the 6.6 work. I guess bots are happy enough by now.

Cheers,
Benjamin

>
> Ciao, Thorsten
>
> > Reviewed-by: Bastien Nocera <hadess@xxxxxxxxxx>
> > Signed-off-by: Benjamin Tissoires <benjamin.tissoires@xxxxxxxxxx>
> > ---
> > as requested by https://lore.kernel.org/all/CAHk-=wiMbF38KCNhPFiargenpSBoecSXTLQACKS2UMyo_Vu2ww@xxxxxxxxxxxxxx/
> > This is a rewrite of that particular piece of code.
> > ---
> > Changes in v2:
> > - added __must_hold() for KASAN
> > - Reworked the comment describing the functions and their return values
> > - Link to v1: https://lore.kernel.org/r/20230621-logitech-fixes-v1-1-32e70933c0b0@xxxxxxxxxx
> > ---
> > drivers/hid/hid-logitech-hidpp.c | 115 +++++++++++++++++++++++++--------------
> > 1 file changed, 75 insertions(+), 40 deletions(-)
> >
> > diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
> > index 129b01be488d..09ba2086c95c 100644
> > --- a/drivers/hid/hid-logitech-hidpp.c
> > +++ b/drivers/hid/hid-logitech-hidpp.c
> > @@ -275,21 +275,22 @@ static int __hidpp_send_report(struct hid_device *hdev,
> > }
> >
> > /*
> > - * hidpp_send_message_sync() returns 0 in case of success, and something else
> > - * in case of a failure.
> > - * - If ' something else' is positive, that means that an error has been raised
> > - * by the protocol itself.
> > - * - If ' something else' is negative, that means that we had a classic error
> > - * (-ENOMEM, -EPIPE, etc...)
> > + * Effectively send the message to the device, waiting for its answer.
> > + *
> > + * Must be called with hidpp->send_mutex locked
> > + *
> > + * Same return protocol than hidpp_send_message_sync():
> > + * - success on 0
> > + * - negative error means transport error
> > + * - positive value means protocol error
> > */
> > -static int hidpp_send_message_sync(struct hidpp_device *hidpp,
> > +static int __do_hidpp_send_message_sync(struct hidpp_device *hidpp,
> > struct hidpp_report *message,
> > struct hidpp_report *response)
> > {
> > - int ret = -1;
> > - int max_retries = 3;
> > + int ret;
> >
> > - mutex_lock(&hidpp->send_mutex);
> > + __must_hold(&hidpp->send_mutex);
> >
> > hidpp->send_receive_buf = response;
> > hidpp->answer_available = false;
> > @@ -300,47 +301,74 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp,
> > */
> > *response = *message;
> >
> > - for (; max_retries != 0 && ret; max_retries--) {
> > - ret = __hidpp_send_report(hidpp->hid_dev, message);
> > + ret = __hidpp_send_report(hidpp->hid_dev, message);
> > + if (ret) {
> > + dbg_hid("__hidpp_send_report returned err: %d\n", ret);
> > + memset(response, 0, sizeof(struct hidpp_report));
> > + return ret;
> > + }
> >
> > - if (ret) {
> > - dbg_hid("__hidpp_send_report returned err: %d\n", ret);
> > - memset(response, 0, sizeof(struct hidpp_report));
> > - break;
> > - }
> > + if (!wait_event_timeout(hidpp->wait, hidpp->answer_available,
> > + 5*HZ)) {
> > + dbg_hid("%s:timeout waiting for response\n", __func__);
> > + memset(response, 0, sizeof(struct hidpp_report));
> > + return -ETIMEDOUT;
> > + }
> >
> > - if (!wait_event_timeout(hidpp->wait, hidpp->answer_available,
> > - 5*HZ)) {
> > - dbg_hid("%s:timeout waiting for response\n", __func__);
> > - memset(response, 0, sizeof(struct hidpp_report));
> > - ret = -ETIMEDOUT;
> > - break;
> > - }
> > + if (response->report_id == REPORT_ID_HIDPP_SHORT &&
> > + response->rap.sub_id == HIDPP_ERROR) {
> > + ret = response->rap.params[1];
> > + dbg_hid("%s:got hidpp error %02X\n", __func__, ret);
> > + return ret;
> > + }
> >
> > - if (response->report_id == REPORT_ID_HIDPP_SHORT &&
> > - response->rap.sub_id == HIDPP_ERROR) {
> > - ret = response->rap.params[1];
> > - dbg_hid("%s:got hidpp error %02X\n", __func__, ret);
> > + if ((response->report_id == REPORT_ID_HIDPP_LONG ||
> > + response->report_id == REPORT_ID_HIDPP_VERY_LONG) &&
> > + response->fap.feature_index == HIDPP20_ERROR) {
> > + ret = response->fap.params[1];
> > + dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret);
> > + return ret;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +/*
> > + * hidpp_send_message_sync() returns 0 in case of success, and something else
> > + * in case of a failure.
> > + *
> > + * See __do_hidpp_send_message_sync() for a detailed explanation of the returned
> > + * value.
> > + */
> > +static int hidpp_send_message_sync(struct hidpp_device *hidpp,
> > + struct hidpp_report *message,
> > + struct hidpp_report *response)
> > +{
> > + int ret;
> > + int max_retries = 3;
> > +
> > + mutex_lock(&hidpp->send_mutex);
> > +
> > + do {
> > + ret = __do_hidpp_send_message_sync(hidpp, message, response);
> > + if (ret != HIDPP20_ERROR_BUSY)
> > break;
> > - }
> >
> > - if ((response->report_id == REPORT_ID_HIDPP_LONG ||
> > - response->report_id == REPORT_ID_HIDPP_VERY_LONG) &&
> > - response->fap.feature_index == HIDPP20_ERROR) {
> > - ret = response->fap.params[1];
> > - if (ret != HIDPP20_ERROR_BUSY) {
> > - dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret);
> > - break;
> > - }
> > - dbg_hid("%s:got busy hidpp 2.0 error %02X, retrying\n", __func__, ret);
> > - }
> > - }
> > + dbg_hid("%s:got busy hidpp 2.0 error %02X, retrying\n", __func__, ret);
> > + } while (--max_retries);
> >
> > mutex_unlock(&hidpp->send_mutex);
> > return ret;
> >
> > }
> >
> > +/*
> > + * hidpp_send_fap_command_sync() returns 0 in case of success, and something else
> > + * in case of a failure.
> > + *
> > + * See __do_hidpp_send_message_sync() for a detailed explanation of the returned
> > + * value.
> > + */
> > static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp,
> > u8 feat_index, u8 funcindex_clientid, u8 *params, int param_count,
> > struct hidpp_report *response)
> > @@ -373,6 +401,13 @@ static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp,
> > return ret;
> > }
> >
> > +/*
> > + * hidpp_send_rap_command_sync() returns 0 in case of success, and something else
> > + * in case of a failure.
> > + *
> > + * See __do_hidpp_send_message_sync() for a detailed explanation of the returned
> > + * value.
> > + */
> > static int hidpp_send_rap_command_sync(struct hidpp_device *hidpp_dev,
> > u8 report_id, u8 sub_id, u8 reg_address, u8 *params, int param_count,
> > struct hidpp_report *response)
> >
> > ---
> > base-commit: 87854366176403438d01f368b09de3ec2234e0f5
> > change-id: 20230621-logitech-fixes-a4c0e66ea2ad
> >
> > Best regards,
>