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 | |||