diff options
-rw-r--r-- | drivers/usb/core/port.c | 32 |
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 | */ | ||
191 | static void find_and_link_peer(struct usb_hub *hub, int port1) | 194 | static 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 | ||
217 | int usb_hub_create_port_device(struct usb_hub *hub, int port1) | 233 | int usb_hub_create_port_device(struct usb_hub *hub, int port1) |