Re: [PATCH v6 part1 5/8] usb: assign usb3 external hub port peers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 2014-02-28 at 15:18 -0800, Dan Williams wrote:
> 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].
> 
> The usb_port_peer_mutex is held when marking hubs as disconnected
> (meaning all child ports are invalid for peering) and when the ->child
> pointer on a port_dev is marked NULL.  Strictly speaking it seems the
> latter should be sufficient for protecting collisions with port peering.
> However, this still includes the lock around setting hub->disconnected
> for extra protection and documentation of the window for when a peer
> relationship can be established.
> 
> [1]: usb3 3.1 section 10.3.3
> 
> Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>

Deleted the usb_port_peer_mutex usages added by this patch.  They're
moot now given the locking done at the hub level.

8<---------
Subject: usb: assign usb3 external hub port peers

From: Dan Williams <dan.j.williams@xxxxxxxxx>

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

Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>
---
 drivers/usb/core/port.c |   28 ++++++++++++++++++++--------
 1 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index cb42352b97e6..6fd827e6a9f8 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -152,17 +152,17 @@ static struct device_driver usb_port_driver = {
 };
 
 /*
- * Set the default peer port for root hubs.  Assumes the primary_hcd is
+ * Set the default peer port via the peer hcd for root hubs and the
+ * upstream peer relationship for other hubs.  Assumes the primary_hcd is
  * registered first
  */
 static struct usb_port *find_default_peer(struct usb_hub *hub, int port1)
 {
 	struct usb_device *hdev = hub->hdev;
-	struct usb_port *peer = NULL;
+	struct usb_device *peer_hdev = NULL;
+	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->primary_hcd;
 
@@ -170,14 +170,26 @@ static struct usb_port *find_default_peer(struct usb_hub *hub, int port1)
 			return NULL;
 
 		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 NULL;
+
+		upstream = parent_hub->ports[hdev->portnum - 1];
+		if (!upstream || !upstream->peer)
 			return NULL;
 
-		peer = peer_hub->ports[port1 - 1];
+		peer_hdev = upstream->peer->child;
 	}
 
-	return peer;
+	peer_hub = usb_hub_to_struct_hub(peer_hdev);
+	if (!peer_hub || port1 > peer_hdev->maxchild)
+		return NULL;
+
+	return peer_hub->ports[port1 - 1];
 }
 
 static void link_peers(struct usb_port *left, struct usb_port *right)


--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux