aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/hub.c
diff options
context:
space:
mode:
authorLan Tianyu <tianyu.lan@intel.com>2012-05-11 04:08:30 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-11 20:08:41 -0400
commitbebc56d58dc780539777d2b1ca80df5566e2ad87 (patch)
treee24d45842809c559c98abb6fb6b2db1445264220 /drivers/usb/core/hub.c
parentf397d7c4c5e8a1eb93f2ed15808a509318ccf1dd (diff)
usb: move struct usb_device->children to struct usb_hub_port->child
Move child's pointer to the struct usb_hub_port since the child device is directly associated with the port. Provide usb_get_hub_child_device() to get child's pointer. Signed-off-by: Lan Tianyu <tianyu.lan@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r--drivers/usb/core/hub.c67
1 files changed, 40 insertions, 27 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 0c17d5a91d79..6bf7124fdf96 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -39,6 +39,7 @@
39 39
40struct usb_hub_port { 40struct usb_hub_port {
41 void *port_owner; 41 void *port_owner;
42 struct usb_device *child;
42}; 43};
43 44
44struct usb_hub { 45struct usb_hub {
@@ -93,7 +94,7 @@ static inline int hub_is_superspeed(struct usb_device *hdev)
93 return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS); 94 return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS);
94} 95}
95 96
96/* Protect struct usb_device->state and ->children members 97/* Protect struct usb_device->state and struct usb_hub_port->child members
97 * Note: Both are also protected by ->dev.sem, except that ->state can 98 * Note: Both are also protected by ->dev.sem, except that ->state can
98 * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */ 99 * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
99static DEFINE_SPINLOCK(device_state_lock); 100static DEFINE_SPINLOCK(device_state_lock);
@@ -176,7 +177,7 @@ static inline char *portspeed(struct usb_hub *hub, int portstatus)
176/* Note that hdev or one of its children must be locked! */ 177/* Note that hdev or one of its children must be locked! */
177static struct usb_hub *hdev_to_hub(struct usb_device *hdev) 178static struct usb_hub *hdev_to_hub(struct usb_device *hdev)
178{ 179{
179 if (!hdev || !hdev->actconfig) 180 if (!hdev || !hdev->actconfig || !hdev->maxchild)
180 return NULL; 181 return NULL;
181 return usb_get_intfdata(hdev->actconfig->interface[0]); 182 return usb_get_intfdata(hdev->actconfig->interface[0]);
182} 183}
@@ -649,8 +650,8 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
649 struct usb_device *hdev = hub->hdev; 650 struct usb_device *hdev = hub->hdev;
650 int ret = 0; 651 int ret = 0;
651 652
652 if (hdev->children[port1-1] && set_state) 653 if (hub->port_data[port1-1].child && set_state)
653 usb_set_device_state(hdev->children[port1-1], 654 usb_set_device_state(hub->port_data[port1-1].child,
654 USB_STATE_NOTATTACHED); 655 USB_STATE_NOTATTACHED);
655 if (!hub->error && !hub_is_superspeed(hub->hdev)) 656 if (!hub->error && !hub_is_superspeed(hub->hdev))
656 ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); 657 ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
@@ -806,7 +807,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
806 * which ports need attention. 807 * which ports need attention.
807 */ 808 */
808 for (port1 = 1; port1 <= hdev->maxchild; ++port1) { 809 for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
809 struct usb_device *udev = hdev->children[port1-1]; 810 struct usb_device *udev = hub->port_data[port1-1].child;
810 u16 portstatus, portchange; 811 u16 portstatus, portchange;
811 812
812 portstatus = portchange = 0; 813 portstatus = portchange = 0;
@@ -971,8 +972,8 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
971 if (type != HUB_SUSPEND) { 972 if (type != HUB_SUSPEND) {
972 /* Disconnect all the children */ 973 /* Disconnect all the children */
973 for (i = 0; i < hdev->maxchild; ++i) { 974 for (i = 0; i < hdev->maxchild; ++i) {
974 if (hdev->children[i]) 975 if (hub->port_data[i].child)
975 usb_disconnect(&hdev->children[i]); 976 usb_disconnect(&hub->port_data[i].child);
976 } 977 }
977 } 978 }
978 979
@@ -1051,11 +1052,9 @@ static int hub_configure(struct usb_hub *hub,
1051 dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild, 1052 dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild,
1052 (hdev->maxchild == 1) ? "" : "s"); 1053 (hdev->maxchild == 1) ? "" : "s");
1053 1054
1054 hdev->children = kzalloc(hdev->maxchild *
1055 sizeof(struct usb_device *), GFP_KERNEL);
1056 hub->port_data = kzalloc(hdev->maxchild * sizeof(struct usb_hub_port), 1055 hub->port_data = kzalloc(hdev->maxchild * sizeof(struct usb_hub_port),
1057 GFP_KERNEL); 1056 GFP_KERNEL);
1058 if (!hub->port_data || !hdev->children) { 1057 if (!hub->port_data) {
1059 ret = -ENOMEM; 1058 ret = -ENOMEM;
1060 goto fail; 1059 goto fail;
1061 } 1060 }
@@ -1287,7 +1286,6 @@ static unsigned highspeed_hubs;
1287static void hub_disconnect(struct usb_interface *intf) 1286static void hub_disconnect(struct usb_interface *intf)
1288{ 1287{
1289 struct usb_hub *hub = usb_get_intfdata(intf); 1288 struct usb_hub *hub = usb_get_intfdata(intf);
1290 struct usb_device *hdev = interface_to_usbdev(intf);
1291 1289
1292 /* Take the hub off the event list and don't let it be added again */ 1290 /* Take the hub off the event list and don't let it be added again */
1293 spin_lock_irq(&hub_event_lock); 1291 spin_lock_irq(&hub_event_lock);
@@ -1309,7 +1307,6 @@ static void hub_disconnect(struct usb_interface *intf)
1309 highspeed_hubs--; 1307 highspeed_hubs--;
1310 1308
1311 usb_free_urb(hub->urb); 1309 usb_free_urb(hub->urb);
1312 kfree(hdev->children);
1313 kfree(hub->port_data); 1310 kfree(hub->port_data);
1314 kfree(hub->descriptor); 1311 kfree(hub->descriptor);
1315 kfree(hub->status); 1312 kfree(hub->status);
@@ -1397,6 +1394,7 @@ static int
1397hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) 1394hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
1398{ 1395{
1399 struct usb_device *hdev = interface_to_usbdev (intf); 1396 struct usb_device *hdev = interface_to_usbdev (intf);
1397 struct usb_hub *hub = usb_get_intfdata(intf);
1400 1398
1401 /* assert ifno == 0 (part of hub spec) */ 1399 /* assert ifno == 0 (part of hub spec) */
1402 switch (code) { 1400 switch (code) {
@@ -1410,11 +1408,11 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
1410 else { 1408 else {
1411 info->nports = hdev->maxchild; 1409 info->nports = hdev->maxchild;
1412 for (i = 0; i < info->nports; i++) { 1410 for (i = 0; i < info->nports; i++) {
1413 if (hdev->children[i] == NULL) 1411 if (hub->port_data[i].child == NULL)
1414 info->port[i] = 0; 1412 info->port[i] = 0;
1415 else 1413 else
1416 info->port[i] = 1414 info->port[i] =
1417 hdev->children[i]->devnum; 1415 hub->port_data[i].child->devnum;
1418 } 1416 }
1419 } 1417 }
1420 spin_unlock_irq(&device_state_lock); 1418 spin_unlock_irq(&device_state_lock);
@@ -1501,11 +1499,13 @@ bool usb_device_is_owned(struct usb_device *udev)
1501 1499
1502static void recursively_mark_NOTATTACHED(struct usb_device *udev) 1500static void recursively_mark_NOTATTACHED(struct usb_device *udev)
1503{ 1501{
1502 struct usb_hub *hub = hdev_to_hub(udev);
1504 int i; 1503 int i;
1505 1504
1506 for (i = 0; i < udev->maxchild; ++i) { 1505 for (i = 0; i < udev->maxchild; ++i) {
1507 if (udev->children[i]) 1506 if (hub->port_data[i].child)
1508 recursively_mark_NOTATTACHED(udev->children[i]); 1507 recursively_mark_NOTATTACHED(
1508 hub->port_data[i].child);
1509 } 1509 }
1510 if (udev->state == USB_STATE_SUSPENDED) 1510 if (udev->state == USB_STATE_SUSPENDED)
1511 udev->active_duration -= jiffies; 1511 udev->active_duration -= jiffies;
@@ -1669,6 +1669,7 @@ static void hub_free_dev(struct usb_device *udev)
1669void usb_disconnect(struct usb_device **pdev) 1669void usb_disconnect(struct usb_device **pdev)
1670{ 1670{
1671 struct usb_device *udev = *pdev; 1671 struct usb_device *udev = *pdev;
1672 struct usb_hub *hub = hdev_to_hub(udev);
1672 int i; 1673 int i;
1673 1674
1674 /* mark the device as inactive, so any further urb submissions for 1675 /* mark the device as inactive, so any further urb submissions for
@@ -1683,8 +1684,8 @@ void usb_disconnect(struct usb_device **pdev)
1683 1684
1684 /* Free up all the children before we remove this device */ 1685 /* Free up all the children before we remove this device */
1685 for (i = 0; i < udev->maxchild; i++) { 1686 for (i = 0; i < udev->maxchild; i++) {
1686 if (udev->children[i]) 1687 if (hub->port_data[i].child)
1687 usb_disconnect(&udev->children[i]); 1688 usb_disconnect(&hub->port_data[i].child);
1688 } 1689 }
1689 1690
1690 /* deallocate hcd/hardware state ... nuking all pending urbs and 1691 /* deallocate hcd/hardware state ... nuking all pending urbs and
@@ -2765,7 +2766,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
2765 for (port1 = 1; port1 <= hdev->maxchild; port1++) { 2766 for (port1 = 1; port1 <= hdev->maxchild; port1++) {
2766 struct usb_device *udev; 2767 struct usb_device *udev;
2767 2768
2768 udev = hdev->children [port1-1]; 2769 udev = hub->port_data[port1-1].child;
2769 if (udev && udev->can_submit) { 2770 if (udev && udev->can_submit) {
2770 dev_warn(&intf->dev, "port %d nyet suspended\n", port1); 2771 dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
2771 if (PMSG_IS_AUTO(msg)) 2772 if (PMSG_IS_AUTO(msg))
@@ -3266,7 +3267,7 @@ hub_power_remaining (struct usb_hub *hub)
3266 3267
3267 remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent; 3268 remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent;
3268 for (port1 = 1; port1 <= hdev->maxchild; ++port1) { 3269 for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
3269 struct usb_device *udev = hdev->children[port1 - 1]; 3270 struct usb_device *udev = hub->port_data[port1 - 1].child;
3270 int delta; 3271 int delta;
3271 3272
3272 if (!udev) 3273 if (!udev)
@@ -3330,7 +3331,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
3330#endif 3331#endif
3331 3332
3332 /* Try to resuscitate an existing device */ 3333 /* Try to resuscitate an existing device */
3333 udev = hdev->children[port1-1]; 3334 udev = hub->port_data[port1-1].child;
3334 if ((portstatus & USB_PORT_STAT_CONNECTION) && udev && 3335 if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
3335 udev->state != USB_STATE_NOTATTACHED) { 3336 udev->state != USB_STATE_NOTATTACHED) {
3336 usb_lock_device(udev); 3337 usb_lock_device(udev);
@@ -3359,7 +3360,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
3359 3360
3360 /* Disconnect any existing devices under this port */ 3361 /* Disconnect any existing devices under this port */
3361 if (udev) 3362 if (udev)
3362 usb_disconnect(&hdev->children[port1-1]); 3363 usb_disconnect(&hub->port_data[port1-1].child);
3363 clear_bit(port1, hub->change_bits); 3364 clear_bit(port1, hub->change_bits);
3364 3365
3365 /* We can forget about a "removed" device when there's a physical 3366 /* We can forget about a "removed" device when there's a physical
@@ -3474,7 +3475,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
3474 && highspeed_hubs != 0) 3475 && highspeed_hubs != 0)
3475 check_highspeed (hub, udev, port1); 3476 check_highspeed (hub, udev, port1);
3476 3477
3477 /* Store the parent's children[] pointer. At this point 3478 /* Store the hub port's child pointer. At this point
3478 * udev becomes globally accessible, although presumably 3479 * udev becomes globally accessible, although presumably
3479 * no one will look at it until hdev is unlocked. 3480 * no one will look at it until hdev is unlocked.
3480 */ 3481 */
@@ -3488,7 +3489,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
3488 if (hdev->state == USB_STATE_NOTATTACHED) 3489 if (hdev->state == USB_STATE_NOTATTACHED)
3489 status = -ENOTCONN; 3490 status = -ENOTCONN;
3490 else 3491 else
3491 hdev->children[port1-1] = udev; 3492 hub->port_data[port1-1].child = udev;
3492 spin_unlock_irq(&device_state_lock); 3493 spin_unlock_irq(&device_state_lock);
3493 3494
3494 /* Run it through the hoops (find a driver, etc) */ 3495 /* Run it through the hoops (find a driver, etc) */
@@ -3496,7 +3497,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
3496 status = usb_new_device(udev); 3497 status = usb_new_device(udev);
3497 if (status) { 3498 if (status) {
3498 spin_lock_irq(&device_state_lock); 3499 spin_lock_irq(&device_state_lock);
3499 hdev->children[port1-1] = NULL; 3500 hub->port_data[port1-1].child = NULL;
3500 spin_unlock_irq(&device_state_lock); 3501 spin_unlock_irq(&device_state_lock);
3501 } 3502 }
3502 } 3503 }
@@ -3542,7 +3543,7 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port,
3542 int ret; 3543 int ret;
3543 3544
3544 hdev = hub->hdev; 3545 hdev = hub->hdev;
3545 udev = hdev->children[port-1]; 3546 udev = hub->port_data[port - 1].child;
3546 if (!hub_is_superspeed(hdev)) { 3547 if (!hub_is_superspeed(hdev)) {
3547 if (!(portchange & USB_PORT_STAT_C_SUSPEND)) 3548 if (!(portchange & USB_PORT_STAT_C_SUSPEND))
3548 return 0; 3549 return 0;
@@ -3696,7 +3697,7 @@ static void hub_events(void)
3696 */ 3697 */
3697 if (!(portstatus & USB_PORT_STAT_ENABLE) 3698 if (!(portstatus & USB_PORT_STAT_ENABLE)
3698 && !connect_change 3699 && !connect_change
3699 && hdev->children[i-1]) { 3700 && hub->port_data[i-1].child) {
3700 dev_err (hub_dev, 3701 dev_err (hub_dev,
3701 "port %i " 3702 "port %i "
3702 "disabled by hub (EMI?), " 3703 "disabled by hub (EMI?), "
@@ -4234,3 +4235,15 @@ void usb_queue_reset_device(struct usb_interface *iface)
4234 schedule_work(&iface->reset_ws); 4235 schedule_work(&iface->reset_ws);
4235} 4236}
4236EXPORT_SYMBOL_GPL(usb_queue_reset_device); 4237EXPORT_SYMBOL_GPL(usb_queue_reset_device);
4238
4239struct usb_device *usb_get_hub_child_device(struct usb_device *hdev,
4240 int port1)
4241{
4242 struct usb_hub *hub = hdev_to_hub(hdev);
4243
4244 if (!hub || port1 > hdev->maxchild || port1 < 1)
4245 return NULL;
4246 return hub->port_data[port1 - 1].child;
4247}
4248EXPORT_SYMBOL_GPL(usb_get_hub_child_device);
4249