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