From: sashiko-bot@kernel.org
To: "Arun Iyengar" <aiyengar1990@gmail.com>
Cc: linux-usb@vger.kernel.org
Subject: Re: [PATCH v4 1/2] usb: core: Pair ports of different hubs through their connector
Date: Sun, 15 Nov 2026 09:50:30 +0000 [thread overview]
Message-ID: <sashiko-outbox-215380@kernel.org> (raw)
In-Reply-To: <20261115-usb-port-pairing-v4-1-25d3c9adcc21@gmail.com>
Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [High] usb: core: OF graph port numbering mismatch in
usb_port_graph_id()
- [Medium] usb: core: raw port number not passed to
usb_of_get_connect_type()
- [Medium] usb: core: update connect_type and connector_peer after
device_register()
--
commit a8c7879971bee16d5ebf91273578d78c7dde5445
Author: Arun Iyengar <aiyengar1990@gmail.com>
usb: core: Pair ports of different hubs through their connector
This commit pairs USB 2.0 and SuperSpeed ports across different hubs or
host controllers when they are linked to the same usb-connector node in
the OF graph.
> diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
> index b4452b665f591..5b2041d891eca 100644
> --- a/drivers/usb/core/port.c
> +++ b/drivers/usb/core/port.c
> @@ -649,10 +649,49 @@ static int match_location(struct usb_device *peer_hdev, void *p)
> return 0;
> }
>
> +static u32 usb_port_graph_id(struct usb_device *hdev, int port1)
> +{
> + if (hdev->parent)
> + return port1;
> + return usb_hcd_find_raw_port_number(bus_to_hcd(hdev->bus), port1);
> +}
> +
> +struct usb_connector_peer {
> + struct usb_port *port_dev;
> + struct device_node *np;
> + u32 port;
> +};
> +
> +static int match_connector_peer(struct usb_device *peer_hdev, void *p)
> +{
> + struct usb_connector_peer *cp = p;
> + struct usb_hub *peer_hub = usb_hub_to_struct_hub(peer_hdev);
> + struct usb_port *peer;
> + int port1;
> +
> + if (!peer_hub || peer_hdev->dev.of_node != cp->np ||
> + hub_is_superspeed(peer_hdev) == cp->port_dev->is_superspeed)
> + return 0;
> +
> + for (port1 = 1; port1 <= peer_hdev->maxchild; port1++) {
> + if (usb_port_graph_id(peer_hdev, port1) == cp->port)
> + break;
> + }
[Severity: High]
Does usb_port_graph_id() match the OF graph port numbering used by USB
controller bindings, and does usb_of_get_connector_peer() leave USB 2.0
ports unpeered when the peer controller uses dwc3 graph numbering?
On dwc3 xHCI controllers, xhci_find_raw_port_number() returns 1 for the
High-Speed root hub port and 2 for the SuperSpeed root hub port, whereas
USB controller DT bindings (such as snps,dwc3-common.yaml and
rockchip,dwc3.yaml) define port@0 as High-Speed and port@1 as SuperSpeed.
When find_and_link_peer() runs for a USB 2.0 hub port whose connector
port@1 points to a dwc3 controller's port@1 (as on
rk3576-lckfb-tspi-3m.dts), usb_of_get_connector_peer() checks !*peer_port,
which rejects port@0 when starting from a SuperSpeed port but accepts
*peer_port == 1 when starting from a USB 2.0 port. find_and_link_peer()
then sets port_dev->connector_peer = 1 and returns early, while
match_connector_peer() compares usb_port_graph_id() (2) against cp->port
(1) and fails to link the ports. Meanwhile, when the dwc3 SuperSpeed root
hub port runs find_and_link_peer(), usb_port_graph_id() returns 2, which
misses port@1 on the controller node and falls through to default peering
with the wrong port (or is blocked by !peer->connector_peer when the
default peer was already marked).
> @@ -671,7 +711,21 @@ static void find_and_link_peer(struct usb_hub *hub, int port1)
> /* we link the peer in match_location() if found */
> usb_for_each_dev(port_dev, match_location);
> return;
> - } else if (!hdev->parent) {
> + }
> +
> + cp.np = usb_of_get_connector_peer(hdev, usb_port_graph_id(hdev, port1),
> + port_dev->is_superspeed, &cp.port);
> + if (cp.np) {
> + cp.port_dev = port_dev;
> + port_dev->connector_peer = 1;
[Severity: Medium]
Does setting port_dev->connector_peer and port_dev->connect_type in
find_and_link_peer() happen too late, after device_register() has already
exposed the port to sysfs?
In usb_hub_create_port_device(), device_register(&port_dev->dev) publishes
the sysfs attributes and emits KOBJ_ADD before find_and_link_peer() runs.
Userspace handlers reacting to KOBJ_ADD can read the stale connect_type,
and the unlocked bitfield write to connector_peer can race with sysfs
writes to sibling bitfields in struct usb_port (early_stop_store() and
usb3_lpm_permit_store()):
CPU0 CPU1
usb_hub_create_port_device()
device_register(&port_dev->dev)
early_stop_store()
port_dev->early_stop = ...
find_and_link_peer()
port_dev->connector_peer = 1;
<-- bitfield RMW clobbers early_stop
> + /* usb_of_get_connect_type() misses graph ports */
> + port_dev->connect_type = USB_PORT_CONNECT_TYPE_HOT_PLUG;
[Severity: Medium]
Why does find_and_link_peer() override port_dev->connect_type here instead
of usb_hub_create_port_device() passing usb_port_graph_id(hdev, port1) to
usb_of_get_connect_type()?
usb_of_get_connect_type() already checks OF graph endpoints via
of_graph_get_endpoint_by_regs(), but usb_hub_create_port_device() passes
the HCD-relative port1 index instead of the controller's raw port number:
drivers/usb/core/port.c:usb_hub_create_port_device() {
...
port_dev->connect_type = usb_of_get_connect_type(hdev, port1);
...
}
On a split-roothub controller where usb_port_graph_id(hdev, port1) !=
port1, usb_of_get_connect_type() inspects the wrong port number on the
controller DT node. Whenever usb_of_get_connector_peer() returns NULL
(for example, when both ports of the connector belong to the same
controller node, or for a hardwired child device node), connect_type is
never fixed up and remains wrong (such as USB_PORT_NOT_USED), causing
set_usb_port_removable() to misclassify hotplugged devices as fixed.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261115-usb-port-pairing-v4-0-25d3c9adcc21@gmail.com?part=1
next prev parent reply other threads:[~2026-11-15 9:50 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-15 8:57 [PATCH v4 0/2] usb: core: Pair ports of different host controllers through their connector Arun Iyengar via B4 Relay
2026-11-15 8:57 ` Arun Iyengar
2026-11-15 8:57 ` [PATCH v4 1/2] usb: core: Pair ports of different hubs " Arun Iyengar via B4 Relay
2026-11-15 8:57 ` Arun Iyengar
2026-11-15 9:50 ` sashiko-bot [this message]
2026-11-15 8:57 ` [PATCH v4 2/2] usb: hub: Retry SuperSpeed for a device stuck on its USB 2.0 peer Arun Iyengar via B4 Relay
2026-11-15 8:57 ` Arun Iyengar
2026-11-15 9:27 ` sashiko-bot
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=sashiko-outbox-215380@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=aiyengar1990@gmail.com \
--cc=linux-usb@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.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.