From fa286188ce0fce994c3fc2bddcafeb948834591f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 14 May 2012 09:20:37 -0700 Subject: 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 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/usbip_common.c | 3 +- drivers/usb/core/devices.c | 3 +- drivers/usb/core/hub.c | 67 +++++++++++++++--------------------- drivers/usb/host/r8a66597-hcd.c | 3 +- include/linux/usb.h | 4 +-- 5 files changed, 33 insertions(+), 47 deletions(-) diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c index 95beb76497d..70f23026932 100644 --- a/drivers/staging/usbip/usbip_common.c +++ b/drivers/staging/usbip/usbip_common.c @@ -157,7 +157,8 @@ static void usbip_dump_usb_device(struct usb_device *udev) dev_dbg(dev, "have_langid %d, string_langid %d\n", udev->have_langid, udev->string_langid); - dev_dbg(dev, "maxchild %d\n", udev->maxchild); + dev_dbg(dev, "maxchild %d, children %p\n", + udev->maxchild, udev->children); } static void usbip_dump_request_type(__u8 rt) diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index a83962b1cce..d9569658476 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, /* Now look at all of this device's children. */ for (chix = 0; chix < usbdev->maxchild; chix++) { - struct usb_device *childdev = - usb_get_hub_child_device(usbdev, chix + 1); + struct usb_device *childdev = usbdev->children[chix]; if (childdev) { usb_lock_device(childdev); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 6bf7124fdf9..0c17d5a91d7 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 @@ static inline int hub_is_superspeed(struct usb_device *hdev) 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 @@ static inline char *portspeed(struct usb_hub *hub, int portstatus) /* 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 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) 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 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) * 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 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) 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 @@ static int hub_configure(struct usb_hub *hub, 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 unsigned highspeed_hubs; 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 @@ static void hub_disconnect(struct usb_interface *intf) highspeed_hubs--; usb_free_urb(hub->urb); + kfree(hdev->children); kfree(hub->port_data); kfree(hub->descriptor); kfree(hub->status); @@ -1394,7 +1397,6 @@ static int 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 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) 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 @@ bool usb_device_is_owned(struct usb_device *udev) 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 @@ static void hub_free_dev(struct usb_device *udev) 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 @@ void usb_disconnect(struct usb_device **pdev) /* 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 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) 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 @@ hub_power_remaining (struct usb_hub *hub) 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 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, #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 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, /* 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 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, && 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 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, 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 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, 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 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, 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 @@ static void hub_events(void) */ 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 @@ void usb_queue_reset_device(struct usb_interface *iface) 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); - diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 4c82fdf5494..c868be65e76 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2040,8 +2040,7 @@ static void collect_usb_address_map(struct usb_device *udev, unsigned long *map) map[udev->devnum/32] |= (1 << (udev->devnum % 32)); for (chix = 0; chix < udev->maxchild; chix++) { - struct usb_device *childdev = - usb_get_hub_child_device(udev, chix + 1); + struct usb_device *childdev = udev->children[chix]; if (childdev) collect_usb_address_map(childdev, map); diff --git a/include/linux/usb.h b/include/linux/usb.h index 69163a0abe9..5483cd70390 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -424,6 +424,7 @@ enum usb_device_removable { * access from userspace * @usbfs_dentry: usbfs dentry entry for the device * @maxchild: number of ports if hub + * @children: child devices - USB devices that are attached to this hub * @quirks: quirks of the whole device * @urbnum: number of URBs submitted for the whole device * @active_duration: total time device is not suspended @@ -490,6 +491,7 @@ struct usb_device { struct list_head filelist; int maxchild; + struct usb_device **children; u32 quirks; atomic_t urbnum; @@ -515,8 +517,6 @@ static inline struct usb_device *interface_to_usbdev(struct usb_interface *intf) extern struct usb_device *usb_get_dev(struct usb_device *dev); extern void usb_put_dev(struct usb_device *dev); -extern struct usb_device *usb_get_hub_child_device(struct usb_device *hdev, - int port1); /* USB device locking */ #define usb_lock_device(udev) device_lock(&(udev)->dev) -- cgit v1.2.3