Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: assign usb3 external hub port peers

Given that root hub port peers are already established, external hub peer
ports can be determined by traversing the device topology:

1/ ascend to the parent hub and find the upstream port_dev

2/ walk ->peer to find the peer port

3/ descend to the peer hub via ->child

4/ find the port with the matching port id

Note that this assumes the port labeling scheme required by the
specification [1].

[1]: usb3 3.1 section 10.3.3

Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Dan Williams and committed by
Greg Kroah-Hartman
8b1ba80c d8521afe

+24 -8
+24 -8
drivers/usb/core/port.c
··· 187 187 left->peer = NULL; 188 188 } 189 189 190 - /* set the default peer port for root hubs */ 190 + /* 191 + * Set the default peer port for root hubs, or via the upstream peer 192 + * relationship for all other hubs 193 + */ 191 194 static void find_and_link_peer(struct usb_hub *hub, int port1) 192 195 { 193 196 struct usb_port *port_dev = hub->ports[port1 - 1], *peer; 194 197 struct usb_device *hdev = hub->hdev; 198 + struct usb_device *peer_hdev; 199 + struct usb_hub *peer_hub; 195 200 196 201 if (!hdev->parent) { 197 - struct usb_hub *peer_hub; 198 - struct usb_device *peer_hdev; 199 202 struct usb_hcd *hcd = bus_to_hcd(hdev->bus); 200 203 struct usb_hcd *peer_hcd = hcd->shared_hcd; 201 204 ··· 206 203 return; 207 204 208 205 peer_hdev = peer_hcd->self.root_hub; 209 - peer_hub = usb_hub_to_struct_hub(peer_hdev); 210 - if (!peer_hub || port1 > peer_hdev->maxchild) 206 + } else { 207 + struct usb_port *upstream; 208 + struct usb_device *parent = hdev->parent; 209 + struct usb_hub *parent_hub = usb_hub_to_struct_hub(parent); 210 + 211 + if (!parent_hub) 211 212 return; 212 213 213 - peer = peer_hub->ports[port1 - 1]; 214 + upstream = parent_hub->ports[hdev->portnum - 1]; 215 + if (!upstream || !upstream->peer) 216 + return; 214 217 215 - if (peer) 216 - link_peers(port_dev, peer); 218 + peer_hdev = upstream->peer->child; 217 219 } 220 + 221 + peer_hub = usb_hub_to_struct_hub(peer_hdev); 222 + if (!peer_hub || port1 > peer_hdev->maxchild) 223 + return; 224 + 225 + peer = peer_hub->ports[port1 - 1]; 226 + if (peer) 227 + link_peers(port_dev, peer); 218 228 } 219 229 220 230 int usb_hub_create_port_device(struct usb_hub *hub, int port1)