The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Hongyan Xu <getshell@seu.edu.cn>
To: John Stultz <jstultz@google.com>, Arnd Bergmann <arnd@arndb.de>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-kernel@vger.kernel.org, jianhao.xu@seu.edu.cn, getshell@seu.edu.cn
Subject: [PATCH] misc: hisi_hikey_usb: cancel role switch work on remove
Date: Tue, 28 Jul 2026 14:55:58 +0800	[thread overview]
Message-ID: <20260728065558.1532-1-getshell@seu.edu.cn> (raw)

The hub role switch set callback schedules private work that dereferences
both driver data and the downstream role switch. Unregistering the hub
switch does not drain work already queued, and a callback that fetched
driver data before unregister can queue more work during removal.

Mark the instance as removing under its mutex and serialize removal
with role switch set callbacks by setting the role to USB_ROLE_NONE.
The callback clears the switch driver data when it observes removal and
no longer queues work. Unregister the switch, cancel the work, and only
then drop the downstream role switch reference.

This issue was found by a static analysis tool.

Signed-off-by: Hongyan Xu <getshell@seu.edu.cn>
---
 drivers/misc/hisi_hikey_usb.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/misc/hisi_hikey_usb.c b/drivers/misc/hisi_hikey_usb.c
index 2165ec3..9db6429 100644
--- a/drivers/misc/hisi_hikey_usb.c
+++ b/drivers/misc/hisi_hikey_usb.c
@@ -45,6 +45,7 @@ struct hisi_hikey_usb {
 
 	struct mutex lock;
 	struct work_struct work;
+	bool removing;
 
 	struct notifier_block nb;
 };
@@ -130,17 +131,23 @@ static void relay_set_role_switch(struct work_struct *work)
 static int hub_usb_role_switch_set(struct usb_role_switch *sw, enum usb_role role)
 {
 	struct hisi_hikey_usb *hisi_hikey_usb = usb_role_switch_get_drvdata(sw);
+	int ret = 0;
 
-	if (!hisi_hikey_usb || !hisi_hikey_usb->dev_role_sw)
-		return -EINVAL;
+	if (!hisi_hikey_usb)
+		return -ENODEV;
 
 	mutex_lock(&hisi_hikey_usb->lock);
-	hisi_hikey_usb->role = role;
+	if (hisi_hikey_usb->removing || !hisi_hikey_usb->dev_role_sw) {
+		if (hisi_hikey_usb->removing)
+			usb_role_switch_set_drvdata(sw, NULL);
+		ret = -ENODEV;
+	} else {
+		hisi_hikey_usb->role = role;
+		schedule_work(&hisi_hikey_usb->work);
+	}
 	mutex_unlock(&hisi_hikey_usb->lock);
 
-	schedule_work(&hisi_hikey_usb->work);
-
-	return 0;
+	return ret;
 }
 
 static int hisi_hikey_usb_of_role_switch(struct platform_device *pdev,
@@ -244,7 +251,15 @@ static int  hisi_hikey_usb_remove(struct platform_device *pdev)
 	struct hisi_hikey_usb *hisi_hikey_usb = platform_get_drvdata(pdev);
 
 	if (hisi_hikey_usb->hub_role_sw) {
+		mutex_lock(&hisi_hikey_usb->lock);
+		hisi_hikey_usb->removing = true;
+		mutex_unlock(&hisi_hikey_usb->lock);
+
+		/* Serialize with set callbacks and clear their private data. */
+		usb_role_switch_set_role(hisi_hikey_usb->hub_role_sw,
+					 USB_ROLE_NONE);
 		usb_role_switch_unregister(hisi_hikey_usb->hub_role_sw);
+		cancel_work_sync(&hisi_hikey_usb->work);
 
 		if (hisi_hikey_usb->dev_role_sw)
 			usb_role_switch_put(hisi_hikey_usb->dev_role_sw);
-- 
2.50.1.windows.1

             reply	other threads:[~2026-07-28  6:56 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-28  6:55 Hongyan Xu [this message]
2026-07-29  2:54 ` [PATCH] misc: hisi_hikey_usb: cancel role switch work on remove John Stultz
2026-07-29  8:03   ` Arnd Bergmann
2026-07-29 10:56 ` Hongyan Xu
2026-07-29 13:41   ` Greg Kroah-Hartman
2026-07-29 13:42   ` Greg Kroah-Hartman
2026-07-29 14:38     ` Arnd Bergmann
2026-07-29 15:45 ` [PATCH] misc: hisi_hikey_usb: remove untested role-switch driver Hongyan Xu
2026-07-29 15:45 ` [PATCH] misc: hisi_hikey_usb: cancel role switch work on remove Hongyan Xu

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=20260728065558.1532-1-getshell@seu.edu.cn \
    --to=getshell@seu.edu.cn \
    --cc=arnd@arndb.de \
    --cc=gregkh@linuxfoundation.org \
    --cc=jianhao.xu@seu.edu.cn \
    --cc=jstultz@google.com \
    --cc=linux-kernel@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