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>
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 6bf7124..0c17d5a 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -39,7 +39,6 @@
 
 struct usb_hub_port {
 	void			*port_owner;
-	struct usb_device	*child;
 };
 
 struct usb_hub {
@@ -94,7 +93,7 @@
 	return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS);
 }
 
-/* Protect struct usb_device->state and struct usb_hub_port->child members
+/* Protect struct usb_device->state and ->children members
  * Note: Both are also protected by ->dev.sem, except that ->state can
  * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
 static DEFINE_SPINLOCK(device_state_lock);
@@ -177,7 +176,7 @@
 /* Note that hdev or one of its children must be locked! */
 static struct usb_hub *hdev_to_hub(struct usb_device *hdev)
 {
-	if (!hdev || !hdev->actconfig || !hdev->maxchild)
+	if (!hdev || !hdev->actconfig)
 		return NULL;
 	return usb_get_intfdata(hdev->actconfig->interface[0]);
 }
@@ -650,8 +649,8 @@
 	struct usb_device *hdev = hub->hdev;
 	int ret = 0;
 
-	if (hub->port_data[port1-1].child && set_state)
-		usb_set_device_state(hub->port_data[port1-1].child,
+	if (hdev->children[port1-1] && set_state)
+		usb_set_device_state(hdev->children[port1-1],
 				USB_STATE_NOTATTACHED);
 	if (!hub->error && !hub_is_superspeed(hub->hdev))
 		ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
@@ -807,7 +806,7 @@
 	 * which ports need attention.
 	 */
 	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
-		struct usb_device *udev = hub->port_data[port1-1].child;
+		struct usb_device *udev = hdev->children[port1-1];
 		u16 portstatus, portchange;
 
 		portstatus = portchange = 0;
@@ -972,8 +971,8 @@
 	if (type != HUB_SUSPEND) {
 		/* Disconnect all the children */
 		for (i = 0; i < hdev->maxchild; ++i) {
-			if (hub->port_data[i].child)
-				usb_disconnect(&hub->port_data[i].child);
+			if (hdev->children[i])
+				usb_disconnect(&hdev->children[i]);
 		}
 	}
 
@@ -1052,9 +1051,11 @@
 	dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild,
 		(hdev->maxchild == 1) ? "" : "s");
 
+	hdev->children = kzalloc(hdev->maxchild *
+				sizeof(struct usb_device *), GFP_KERNEL);
 	hub->port_data = kzalloc(hdev->maxchild * sizeof(struct usb_hub_port),
 			GFP_KERNEL);
-	if (!hub->port_data) {
+	if (!hub->port_data || !hdev->children) {
 		ret = -ENOMEM;
 		goto fail;
 	}
@@ -1286,6 +1287,7 @@
 static void hub_disconnect(struct usb_interface *intf)
 {
 	struct usb_hub *hub = usb_get_intfdata(intf);
+	struct usb_device *hdev = interface_to_usbdev(intf);
 
 	/* Take the hub off the event list and don't let it be added again */
 	spin_lock_irq(&hub_event_lock);
@@ -1307,6 +1309,7 @@
 		highspeed_hubs--;
 
 	usb_free_urb(hub->urb);
+	kfree(hdev->children);
 	kfree(hub->port_data);
 	kfree(hub->descriptor);
 	kfree(hub->status);
@@ -1394,7 +1397,6 @@
 hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
 {
 	struct usb_device *hdev = interface_to_usbdev (intf);
-	struct usb_hub *hub = usb_get_intfdata(intf);
 
 	/* assert ifno == 0 (part of hub spec) */
 	switch (code) {
@@ -1408,11 +1410,11 @@
 		else {
 			info->nports = hdev->maxchild;
 			for (i = 0; i < info->nports; i++) {
-				if (hub->port_data[i].child == NULL)
+				if (hdev->children[i] == NULL)
 					info->port[i] = 0;
 				else
 					info->port[i] =
-						hub->port_data[i].child->devnum;
+						hdev->children[i]->devnum;
 			}
 		}
 		spin_unlock_irq(&device_state_lock);
@@ -1499,13 +1501,11 @@
 
 static void recursively_mark_NOTATTACHED(struct usb_device *udev)
 {
-	struct usb_hub	*hub = hdev_to_hub(udev);
 	int i;
 
 	for (i = 0; i < udev->maxchild; ++i) {
-		if (hub->port_data[i].child)
-			recursively_mark_NOTATTACHED(
-				hub->port_data[i].child);
+		if (udev->children[i])
+			recursively_mark_NOTATTACHED(udev->children[i]);
 	}
 	if (udev->state == USB_STATE_SUSPENDED)
 		udev->active_duration -= jiffies;
@@ -1669,7 +1669,6 @@
 void usb_disconnect(struct usb_device **pdev)
 {
 	struct usb_device	*udev = *pdev;
-	struct usb_hub	*hub = hdev_to_hub(udev);
 	int			i;
 
 	/* mark the device as inactive, so any further urb submissions for
@@ -1684,8 +1683,8 @@
 
 	/* Free up all the children before we remove this device */
 	for (i = 0; i < udev->maxchild; i++) {
-		if (hub->port_data[i].child)
-			usb_disconnect(&hub->port_data[i].child);
+		if (udev->children[i])
+			usb_disconnect(&udev->children[i]);
 	}
 
 	/* deallocate hcd/hardware state ... nuking all pending urbs and
@@ -2766,7 +2765,7 @@
 	for (port1 = 1; port1 <= hdev->maxchild; port1++) {
 		struct usb_device	*udev;
 
-		udev = hub->port_data[port1-1].child;
+		udev = hdev->children [port1-1];
 		if (udev && udev->can_submit) {
 			dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
 			if (PMSG_IS_AUTO(msg))
@@ -3267,7 +3266,7 @@
 
 	remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent;
 	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
-		struct usb_device	*udev = hub->port_data[port1 - 1].child;
+		struct usb_device	*udev = hdev->children[port1 - 1];
 		int			delta;
 
 		if (!udev)
@@ -3331,7 +3330,7 @@
 #endif
 
 	/* Try to resuscitate an existing device */
-	udev = hub->port_data[port1-1].child;
+	udev = hdev->children[port1-1];
 	if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
 			udev->state != USB_STATE_NOTATTACHED) {
 		usb_lock_device(udev);
@@ -3360,7 +3359,7 @@
 
 	/* Disconnect any existing devices under this port */
 	if (udev)
-		usb_disconnect(&hub->port_data[port1-1].child);
+		usb_disconnect(&hdev->children[port1-1]);
 	clear_bit(port1, hub->change_bits);
 
 	/* We can forget about a "removed" device when there's a physical
@@ -3475,7 +3474,7 @@
 				&& highspeed_hubs != 0)
 			check_highspeed (hub, udev, port1);
 
-		/* Store the hub port's child pointer.  At this point
+		/* Store the parent's children[] pointer.  At this point
 		 * udev becomes globally accessible, although presumably
 		 * no one will look at it until hdev is unlocked.
 		 */
@@ -3489,7 +3488,7 @@
 		if (hdev->state == USB_STATE_NOTATTACHED)
 			status = -ENOTCONN;
 		else
-			hub->port_data[port1-1].child = udev;
+			hdev->children[port1-1] = udev;
 		spin_unlock_irq(&device_state_lock);
 
 		/* Run it through the hoops (find a driver, etc) */
@@ -3497,7 +3496,7 @@
 			status = usb_new_device(udev);
 			if (status) {
 				spin_lock_irq(&device_state_lock);
-				hub->port_data[port1-1].child = NULL;
+				hdev->children[port1-1] = NULL;
 				spin_unlock_irq(&device_state_lock);
 			}
 		}
@@ -3543,7 +3542,7 @@
 	int ret;
 
 	hdev = hub->hdev;
-	udev = hub->port_data[port - 1].child;
+	udev = hdev->children[port-1];
 	if (!hub_is_superspeed(hdev)) {
 		if (!(portchange & USB_PORT_STAT_C_SUSPEND))
 			return 0;
@@ -3697,7 +3696,7 @@
 				 */
 				if (!(portstatus & USB_PORT_STAT_ENABLE)
 				    && !connect_change
-				    && hub->port_data[i-1].child) {
+				    && hdev->children[i-1]) {
 					dev_err (hub_dev,
 					    "port %i "
 					    "disabled by hub (EMI?), "
@@ -4235,15 +4234,3 @@
 	schedule_work(&iface->reset_ws);
 }
 EXPORT_SYMBOL_GPL(usb_queue_reset_device);
-
-struct usb_device *usb_get_hub_child_device(struct usb_device *hdev,
-	int port1)
-{
-	struct usb_hub *hub = hdev_to_hub(hdev);
-
-	if (!hub || port1 > hdev->maxchild || port1 < 1)
-		return NULL;
-	return hub->port_data[port1 - 1].child;
-}
-EXPORT_SYMBOL_GPL(usb_get_hub_child_device);
-