Linux USB
 help / color / mirror / Atom feed
* [PATCH] usb: core: deattach child device from typec connector on port unbind
@ 2026-07-21 20:22 Marco Tormento
  2026-07-22 16:02 ` Heikki Krogerus
  0 siblings, 1 reply; 3+ messages in thread
From: Marco Tormento @ 2026-07-21 20:22 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Heikki Krogerus, Alan Stern, linux-usb, linux-kernel,
	Marco Tormento

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


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-07-22 16:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-21 20:22 [PATCH] usb: core: deattach child device from typec connector on port unbind Marco Tormento
2026-07-22 16:02 ` Heikki Krogerus
2026-07-22 16:25   ` Marco Tormento

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox