From: Marco Tormento <mtormento80@gmail.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>,
Alan Stern <stern@rowland.harvard.edu>,
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
Marco Tormento <mtormento80@gmail.com>
Subject: [PATCH] usb: core: deattach child device from typec connector on port unbind
Date: Tue, 21 Jul 2026 22:22:01 +0200 [thread overview]
Message-ID: <20260721202201.27442-1-mtormento80@gmail.com> (raw)
connector_bind() tells the Type-C connector about a port's already
attached child via typec_attach(), but connector_unbind() has no
mirror image: it drops port_dev->connector without deattaching a
still-present child first. When that happens, port->usb2_dev (or
usb3_dev) in the Type-C port is left pointing at a device that is
about to be torn down, and typec_partner_deattach() never runs for
it.
This shows up on hardware where a single Type-C connector's component
aggregate spans ports on more than one USB root hub sharing an xHCI
controller (e.g. a Thunderbolt-attached hub exposing both a USB-2 and
a USB-3 root-hub port through the same connector). Unbinding the
connector from one root hub's ports also unbinds it for the other's,
even though the other root hub's child device is still attached and
gets disconnected later, by which point the connector is already
gone. The result is a "kernfs: can not remove 'typec', no directory"
warning the first time, "sysfs: cannot create duplicate filename"
the next time the device is reattached, and eventually a general
protection fault in typec_unregister_partner() when it dereferences
port->usb2_dev/usb3_dev after the device it points to has been freed.
Fix connector_unbind() to mirror connector_bind(): deattach the
child from the connector before dropping the reference to it. This
closes the race regardless of which order the parent USB controllers
happen to be torn down in.
Reported on a Lenovo Thinkpad T480s (BenQ EX3501R monitor with an
integrated USB hub, connected via the Thunderbolt-capable Type-C
port, alongside a USB-C power delivery brick on the other Type-C
port). Ran the reported plug/unplug sequence multiple times on that
hardware with this patch applied and could not reproduce the failure;
the same kernel build without the patch reproduced it on the first
attempt. Supersedes an earlier attempt that reordered
typec_deattach() in usb_disconnect() instead; that approach worked
around the same race but only for one ordering of controller teardown,
and inverted the normal teardown-mirrors-setup convention.
The original investigation, including the v1 patch and the hardware
reproduction that led to identifying this bug, is my own work. The
connector_unbind() fix approach below was proposed by Claude (Anthropic,
Sonnet 5) during code review of the v1 patch. Hardware reproduction and
validation of this fix were carried out by me, on the same hardware, per
the note above.
Link: https://lore.kernel.org/r/20250720210847.30998-1-mtormento80@gmail.com
Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Marco Tormento <mtormento80@gmail.com>
---
drivers/usb/core/port.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index b1364f0c384c..3b258246bb3f 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -738,6 +738,14 @@ static void connector_unbind(struct device *dev, struct device *connector, void
{
struct usb_port *port_dev = to_usb_port(dev);
+ /*
+ * If a USB device is still connected to the port, let the
+ * Type-C connector know it's going away before we drop our
+ * reference to it.
+ */
+ if (port_dev->child)
+ typec_deattach(data, &port_dev->child->dev);
+
sysfs_remove_link(&connector->kobj, dev_name(dev));
sysfs_remove_link(&dev->kobj, "connector");
port_dev->connector = NULL;
--
2.55.0
next reply other threads:[~2026-07-21 20:23 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-21 20:22 Marco Tormento [this message]
2026-07-22 16:02 ` [PATCH] usb: core: deattach child device from typec connector on port unbind Heikki Krogerus
2026-07-22 16:25 ` Marco Tormento
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=20260721202201.27442-1-mtormento80@gmail.com \
--to=mtormento80@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=heikki.krogerus@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=stern@rowland.harvard.edu \
/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