aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/port.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/port.c')
-rw-r--r--drivers/usb/core/port.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index 5ecdbf31dfcb..9b7496b52f2a 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -187,15 +187,18 @@ static void unlink_peers(struct usb_port *left, struct usb_port *right)
187 left->peer = NULL; 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 */
191static void find_and_link_peer(struct usb_hub *hub, int port1) 194static void find_and_link_peer(struct usb_hub *hub, int port1)
192{ 195{
193 struct usb_port *port_dev = hub->ports[port1 - 1], *peer; 196 struct usb_port *port_dev = hub->ports[port1 - 1], *peer;
194 struct usb_device *hdev = hub->hdev; 197 struct usb_device *hdev = hub->hdev;
198 struct usb_device *peer_hdev;
199 struct usb_hub *peer_hub;
195 200
196 if (!hdev->parent) { 201 if (!hdev->parent) {
197 struct usb_hub *peer_hub;
198 struct usb_device *peer_hdev;
199 struct usb_hcd *hcd = bus_to_hcd(hdev->bus); 202 struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
200 struct usb_hcd *peer_hcd = hcd->shared_hcd; 203 struct usb_hcd *peer_hcd = hcd->shared_hcd;
201 204
@@ -203,15 +206,28 @@ static void find_and_link_peer(struct usb_hub *hub, int port1)
203 return; 206 return;
204 207
205 peer_hdev = peer_hcd->self.root_hub; 208 peer_hdev = peer_hcd->self.root_hub;
206 peer_hub = usb_hub_to_struct_hub(peer_hdev); 209 } else {
207 if (!peer_hub || port1 > peer_hdev->maxchild) 210 struct usb_port *upstream;
211 struct usb_device *parent = hdev->parent;
212 struct usb_hub *parent_hub = usb_hub_to_struct_hub(parent);
213
214 if (!parent_hub)
208 return; 215 return;
209 216
210 peer = peer_hub->ports[port1 - 1]; 217 upstream = parent_hub->ports[hdev->portnum - 1];
218 if (!upstream || !upstream->peer)
219 return;
211 220
212 if (peer) 221 peer_hdev = upstream->peer->child;
213 link_peers(port_dev, peer);
214 } 222 }
223
224 peer_hub = usb_hub_to_struct_hub(peer_hdev);
225 if (!peer_hub || port1 > peer_hdev->maxchild)
226 return;
227
228 peer = peer_hub->ports[port1 - 1];
229 if (peer)
230 link_peers(port_dev, peer);
215} 231}
216 232
217int usb_hub_create_port_device(struct usb_hub *hub, int port1) 233int usb_hub_create_port_device(struct usb_hub *hub, int port1)