From: Denis Benato <denis.benato@linux.dev>
To: linux-kernel@vger.kernel.org
Cc: linux-input@vger.kernel.org,
"Benjamin Tissoires" <bentiss@kernel.org>,
"Jiri Kosina" <jikos@kernel.org>,
"Luke D . Jones" <luke@ljones.dev>,
"Mateusz Schyboll" <dragonn@op.pl>,
"Denis Benato" <benato.denis96@gmail.com>,
Denis Benato <denis.benato@linux.dev>
Subject: [PATCH 1/3] HID: asus: document and harden the worker teardown
Date: Tue, 15 Sep 2026 18:11:58 +0000 [thread overview]
Message-ID: <20260915181200.18086-2-denis.benato@linux.dev> (raw)
In-Reply-To: <20260915181200.18086-1-denis.benato@linux.dev>
asus_work() executes actions against the device: they send feature
reports with hid_hw_raw_request() and, for the Fn+F5 fan key fallback,
re-inject the raw report into the HID core with hid_report_raw_event().
For this reason the worker must be quiesced before hid_hw_stop(): after
the low level driver has stopped, the transport is gone (usbhid_stop()
frees the URBs and the I/O buffers) and re-injected reports would race
against the input devices being unregistered by hid_disconnect().
Make so that the teardown cannot race to a use-after-free: every site
queueing an action holds worker->lock across the .removed check, the
list insertion and schedule_work(), and asus_worker_stop() sets .removed
and drains the queue under that same lock before calling
cancel_work_sync(). An action that passed the check is caught by the
latter while any later attempt is discarded by asus_worker_schedule().
Closes: https://lore.kernel.org/all/20260908180032.34C2D1F00A3A@smtp.kernel.org/
Fixes: 47669bec44fe ("HID: asus: refactor the two workqueues and init sequence")
Assisted-by: zcode:glm-5.3-flash
Signed-off-by: Denis Benato <denis.benato@linux.dev>
---
drivers/hid/hid-asus.c | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index bd46aba6622a..3a8b8b7e90f7 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -765,9 +765,14 @@ static void asus_work(struct work_struct *work)
struct asus_work_action *action = NULL;
unsigned long flags;
- /* Save the action to be performed and clear the flag */
+ /*
+ * Dequeue the next action, if any. Once teardown has begun .removed
+ * is set and asus_worker_stop() drains the queue: leave the queued
+ * actions alone, they are dropped instead of being executed against
+ * a device that is being removed.
+ */
spin_lock_irqsave(&worker->lock, flags);
- if (!list_empty(&worker->actions)) {
+ if (!worker->removed && !list_empty(&worker->actions)) {
action = list_first_entry(&worker->actions,
struct asus_work_action, node);
list_del(&action->node);
@@ -817,6 +822,25 @@ static int asus_worker_create(struct hid_device *hdev, struct asus_drvdata *drvd
return 0;
}
+/**
+ * asus_worker_stop - quiesce the worker
+ * @worker: the worker to quiesce
+ *
+ * Once this function returns no more actions can be queued and no instance
+ * of asus_work() is running or pending.
+ *
+ * Callers must do this before hid_hw_stop(): actions are executed while the
+ * device is fully operational, since they send raw requests to it and, in
+ * the fan-key fallback path, re-inject raw reports into the HID core. After
+ * hid_hw_stop() the transport is gone (usbhid_stop() frees the URBs and the
+ * I/O buffers) and the input devices have been unregistered.
+ *
+ * The quiescing is race free because every site that queues an action holds
+ * worker->lock across the .removed check, the list insertion and
+ * schedule_work(): anything scheduled before .removed is set here is caught
+ * by the cancel_work_sync() below, anything after it is discarded by
+ * asus_worker_schedule().
+ */
static void asus_worker_stop(struct asus_worker *worker)
{
struct asus_work_action *action, *tmp;
--
2.47.3
next prev parent reply other threads:[~2026-09-15 18:12 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-15 18:11 [PATCH 0/3] HID: asus: improve the driver support for laptops Denis Benato
2026-09-15 18:11 ` Denis Benato [this message]
2026-09-15 18:11 ` [PATCH 2/3] HID: asus: reinitialize the device after exiting a sleep state Denis Benato
2026-09-15 18:12 ` [PATCH 3/3] HID: asus: add support for xgm led Denis Benato
2026-09-15 18:19 ` sashiko-bot
2026-09-15 21:52 ` Antheas Kapenekakis
2026-09-16 0:54 ` Denis Benato
2026-09-16 6:46 ` Antheas Kapenekakis
2026-09-16 12:18 ` Denis Benato
2026-09-16 12:31 ` Antheas Kapenekakis
2026-09-16 13:05 ` Denis Benato
2026-09-17 22:06 ` Antheas Kapenekakis
2026-09-18 1:50 ` Denis Benato
2026-09-18 7:28 ` Antheas Kapenekakis
2026-09-18 7:29 ` Antheas Kapenekakis
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=20260915181200.18086-2-denis.benato@linux.dev \
--to=denis.benato@linux.dev \
--cc=benato.denis96@gmail.com \
--cc=bentiss@kernel.org \
--cc=dragonn@op.pl \
--cc=jikos@kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luke@ljones.dev \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.