Skip to content

Commit

Permalink
usb: assign usb3 external hub port peers
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Dan Williams <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
djbw authored and gregkh committed May 27, 2014
1 parent d8521af commit 8b1ba80
Showing 1 changed file with 24 additions and 8 deletions.
32 changes: 24 additions & 8 deletions drivers/usb/core/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,31 +187,47 @@ static void unlink_peers(struct usb_port *left, struct usb_port *right)
left->peer = NULL;
}

/* set the default peer port for root hubs */
/*
* Set the default peer port for root hubs, or via the upstream peer
* relationship for all other hubs
*/
static void find_and_link_peer(struct usb_hub *hub, int port1)
{
struct usb_port *port_dev = hub->ports[port1 - 1], *peer;
struct usb_device *hdev = hub->hdev;
struct usb_device *peer_hdev;
struct usb_hub *peer_hub;

if (!hdev->parent) {
struct usb_hub *peer_hub;
struct usb_device *peer_hdev;
struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
struct usb_hcd *peer_hcd = hcd->shared_hcd;

if (!peer_hcd)
return;

peer_hdev = peer_hcd->self.root_hub;
peer_hub = usb_hub_to_struct_hub(peer_hdev);
if (!peer_hub || port1 > peer_hdev->maxchild)
} else {
struct usb_port *upstream;
struct usb_device *parent = hdev->parent;
struct usb_hub *parent_hub = usb_hub_to_struct_hub(parent);

if (!parent_hub)
return;

peer = peer_hub->ports[port1 - 1];
upstream = parent_hub->ports[hdev->portnum - 1];
if (!upstream || !upstream->peer)
return;

if (peer)
link_peers(port_dev, peer);
peer_hdev = upstream->peer->child;
}

peer_hub = usb_hub_to_struct_hub(peer_hdev);
if (!peer_hub || port1 > peer_hdev->maxchild)
return;

peer = peer_hub->ports[port1 - 1];
if (peer)
link_peers(port_dev, peer);
}

int usb_hub_create_port_device(struct usb_hub *hub, int port1)
Expand Down

0 comments on commit 8b1ba80

Please sign in to comment.