From: "Derek J. Clark" <derekjohn.clark@gmail.com>
To: Jiri Kosina <jikos@kernel.org>, Benjamin Tissoires <bentiss@kernel.org>
Cc: "Pierre-Loup A . Griffais" <pgriffais@valvesoftware.com>,
"Derek J . Clark" <derekjohn.clark@gmail.com>,
linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@lists.opengamingcollective.org, stable@vger.kernel.org
Subject: [PATCH v2 02/11] HID: hid-lenovo-go-s: Bound stale reply window before reusing send_cmd_complete
Date: Fri, 16 Oct 2026 18:39:47 -0700 [thread overview]
Message-ID: <20261017013956.2440130-3-derekjohn.clark@gmail.com> (raw)
In-Reply-To: <20261017013956.2440130-1-derekjohn.clark@gmail.com>
mcu_property_out() reinits send_cmd_complete immediately after a
timeout is detected, before the next command that reuses it is sent.
If the MCU's reply to the timed-out command arrives after this reinit
but before the next command's wait begins, it silently satisfies the
next, unrelated command's wait instead of the one it actually answers,
handing that caller stale data with no way to detect the mismatch.
Track when no reply was consumed, i.e. the wait timed out or was
interrupted, via orphan_ack_pending. Before the next command reuses
the completion, wait a bounded 25ms for a stale reply to arrive and be
consumed, then unconditionally clear the flag and reinit the
completion. This does not fully eliminate the window in which an
unrelated reply could still be received, but bounds it to a short
interval right before a new command is sent. Behavior matches the
solution to the same problem in hid-msi.
Fixes: a23f3497bf208c59ad ("HID: hid-lenovo-go-s: Add Lenovo Legion Go S Series HID Driver")
Cc: stable@vger.kernel.org
Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
---
drivers/hid/hid-lenovo-go-s.c | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c
index 68301d4c762a..e979527ece8e 100644
--- a/drivers/hid/hid-lenovo-go-s.c
+++ b/drivers/hid/hid-lenovo-go-s.c
@@ -37,6 +37,7 @@ static struct hid_gos_cfg {
struct completion send_cmd_complete;
struct led_classdev *led_cdev;
struct hid_device *hdev;
+ bool orphan_ack_pending;
struct mutex cfg_mutex; /*ensure single synchronous output report*/
int cmd_status;
u8 gp_auto_sleep_time;
@@ -448,12 +449,26 @@ static int mcu_property_out(struct hid_device *hdev, u8 command, u8 index,
unsigned char *dmabuf __free(kfree) = NULL;
u8 header[] = { command, index };
size_t header_size = ARRAY_SIZE(header);
+ long t_remaining;
int timeout, ret;
if (header_size + len > GO_S_PACKET_SIZE)
return -EINVAL;
guard(mutex)(&drvdata.cfg_mutex);
+
+ /*
+ * A reply to the previous command may still be in flight. Give it a
+ * short window to arrive and be consumed before this call reinits the
+ * completion, so a late reply can't be mistaken for this command's.
+ */
+ if (drvdata.orphan_ack_pending) {
+ wait_for_completion_timeout(&drvdata.send_cmd_complete, msecs_to_jiffies(25));
+ drvdata.orphan_ack_pending = false;
+ drvdata.cmd_status = -ETIMEDOUT;
+ }
+ reinit_completion(&drvdata.send_cmd_complete);
+
/* We can't use a devm_alloc reusable buffer without side effects during suspend */
dmabuf = kzalloc(GO_S_PACKET_SIZE, GFP_KERNEL);
if (!dmabuf)
@@ -475,11 +490,15 @@ static int mcu_property_out(struct hid_device *hdev, u8 command, u8 index,
/* PL_TEST commands can take longer because they go out to another device */
timeout = (command == GET_PL_TEST) ? 200 : 5;
- ret = wait_for_completion_interruptible_timeout(&drvdata.send_cmd_complete,
- msecs_to_jiffies(timeout));
- ret = ret > 0 ? drvdata.cmd_status : ret ?: -EBUSY;
+ t_remaining = wait_for_completion_interruptible_timeout(&drvdata.send_cmd_complete,
+ msecs_to_jiffies(timeout));
+ if (t_remaining <= 0) {
+ /* A reply to this command may still be in flight. */
+ drvdata.orphan_ack_pending = true;
+ }
+
+ ret = t_remaining > 0 ? drvdata.cmd_status : t_remaining ?: -EBUSY;
- reinit_completion(&drvdata.send_cmd_complete);
return ret;
}
--
2.55.0
next prev parent reply other threads:[~2026-10-17 1:40 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-17 1:39 [PATCH v2 00/11] HID: hid-lenovo-go-s: Fix various bugs Derek J. Clark
2026-10-17 1:39 ` [PATCH v2 01/11] HID: hid-lenovo-go-s: Return ret instead of 0 in mcu_property_out() Derek J. Clark
2026-10-17 1:39 ` Derek J. Clark [this message]
2026-10-17 1:39 ` [PATCH v2 03/11] HID: hid-lenovo-go-s: Prevent deadlock if device removed during setup Derek J. Clark
2026-10-17 1:39 ` [PATCH v2 04/11] HID: hid-lenovo-go-s: Use pm_ptr for reset_resume callback Derek J. Clark
2026-10-17 1:39 ` [PATCH v2 05/11] HID: hid-lenovo-go-s: Add kobject_uevent notify during reset-resume Derek J. Clark
2026-10-17 1:39 ` [PATCH v2 06/11] HID: hid-lenovo-go-s: Add suspend function and gate access under bool Derek J. Clark
2026-10-17 2:03 ` sashiko-bot
2026-10-17 1:39 ` [PATCH v2 07/11] HID: hid-lenovo-go-s: Move attribute init to after device query Derek J. Clark
2026-10-17 2:07 ` sashiko-bot
2026-10-17 1:39 ` [PATCH v2 08/11] HID: hid-lenovo-go-s: Reorganize and rename hid_gos_cfg Derek J. Clark
2026-10-17 1:39 ` [PATCH v2 09/11] HID: hid-lenovo-go-s: Move static led_classdev_mc to drvdata struct Derek J. Clark
2026-10-17 2:14 ` sashiko-bot
2026-10-17 1:39 ` [PATCH v2 10/11] HID: hid-lenovo-go-s: Use devm_kzalloc for drvdata Derek J. Clark
2026-10-17 2:23 ` sashiko-bot
2026-10-17 1:39 ` [PATCH v2 11/11] HID: hid-lenovo-go-s: Stop and close device on probe failure Derek J. Clark
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261017013956.2440130-3-derekjohn.clark@gmail.com \
--to=derekjohn.clark@gmail.com \
--cc=bentiss@kernel.org \
--cc=jikos@kernel.org \
--cc=kernel@lists.opengamingcollective.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pgriffais@valvesoftware.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox