diff options
| author | Lan Tianyu <tianyu.lan@intel.com> | 2012-09-05 13:44:32 +0800 | 
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-09-10 12:59:42 -0700 | 
| commit | ff823c79a5c33194c2e5594f7c4686ea3547910c (patch) | |
| tree | 0685b5aee627d7f3440dc09865a7715406cfee54 | |
| parent | fa2a9566257a3b62c328ea5d621ccf5952079dac (diff) | |
| download | olio-linux-3.10-ff823c79a5c33194c2e5594f7c4686ea3547910c.tar.xz olio-linux-3.10-ff823c79a5c33194c2e5594f7c4686ea3547910c.zip  | |
usb: move children to struct usb_port
The usb_device structure contains an array of usb_device "children".
This array is only valid if the usb_device is a hub, so it makes no
sense to store it there.  Instead, store the usb_device child
in its parent usb_port structure.
Since usb_port is an internal USB core structure, add a new function to
get the USB device child, usb_hub_find_child().  Add a new macro,
usb_hub_get_each_child(), to iterate over all the children attached to a
particular USB hub.
Remove the printing the USB children array pointer from the usb-ip
driver, since it's really not necessary.
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Lan Tianyu <tianyu.lan@intel.com>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
| -rw-r--r-- | drivers/staging/usbip/usbip_common.c | 3 | ||||
| -rw-r--r-- | drivers/usb/core/devices.c | 7 | ||||
| -rw-r--r-- | drivers/usb/core/hub.c | 73 | ||||
| -rw-r--r-- | drivers/usb/host/r8a66597-hcd.c | 5 | ||||
| -rw-r--r-- | include/linux/usb.h | 15 | 
5 files changed, 68 insertions, 35 deletions
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c index 70f23026932..95beb76497d 100644 --- a/drivers/staging/usbip/usbip_common.c +++ b/drivers/staging/usbip/usbip_common.c @@ -157,8 +157,7 @@ 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, children %p\n", -		udev->maxchild, udev->children); +	dev_dbg(dev, "maxchild %d\n", udev->maxchild);  }  static void usbip_dump_request_type(__u8 rt) diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index d9569658476..f4ead129682 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -496,6 +496,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,  	char *pages_start, *data_end, *speed;  	unsigned int length;  	ssize_t total_written = 0; +	struct usb_device *childdev = NULL;  	/* don't bother with anything else if we're not writing any data */  	if (*nbytes <= 0) @@ -589,14 +590,12 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,  	free_pages((unsigned long)pages_start, 1);  	/* Now look at all of this device's children. */ -	for (chix = 0; chix < usbdev->maxchild; chix++) { -		struct usb_device *childdev = usbdev->children[chix]; - +	usb_hub_for_each_child(usbdev, chix, childdev) {  		if (childdev) {  			usb_lock_device(childdev);  			ret = usb_device_dump(buffer, nbytes, skip_bytes,  					      file_offset, childdev, bus, -					      level + 1, chix, ++cnt); +					      level + 1, chix - 1, ++cnt);  			usb_unlock_device(childdev);  			if (ret == -EFAULT)  				return total_written; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 87df22eef49..cdbade14899 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -40,6 +40,7 @@  #endif  struct usb_port { +	struct usb_device *child;  	struct device dev;  	struct dev_state *port_owner;  }; @@ -181,7 +182,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) +	if (!hdev || !hdev->actconfig || !hdev->maxchild)  		return NULL;  	return usb_get_intfdata(hdev->actconfig->interface[0]);  } @@ -876,8 +877,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 (hdev->children[port1-1] && set_state) -		usb_set_device_state(hdev->children[port1-1], +	if (hub->ports[port1 - 1]->child && set_state) +		usb_set_device_state(hub->ports[port1 - 1]->child,  				USB_STATE_NOTATTACHED);  	if (!hub->error && !hub_is_superspeed(hub->hdev))  		ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); @@ -1033,7 +1034,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 = hdev->children[port1-1]; +		struct usb_device *udev = hub->ports[port1 - 1]->child;  		u16 portstatus, portchange;  		portstatus = portchange = 0; @@ -1198,8 +1199,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 (hdev->children[i]) -				usb_disconnect(&hdev->children[i]); +			if (hub->ports[i]->child) +				usb_disconnect(&hub->ports[i]->child);  		}  	} @@ -1324,11 +1325,9 @@ 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->ports = kzalloc(hdev->maxchild * sizeof(struct usb_port *),  			     GFP_KERNEL); -	if (!hdev->children || !hub->ports) { +	if (!hub->ports) {  		ret = -ENOMEM;  		goto fail;  	} @@ -1591,7 +1590,6 @@ static void hub_disconnect(struct usb_interface *intf)  		highspeed_hubs--;  	usb_free_urb(hub->urb); -	kfree(hdev->children);  	kfree(hub->ports);  	kfree(hub->descriptor);  	kfree(hub->status); @@ -1679,6 +1677,7 @@ 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 = hdev_to_hub(hdev);  	/* assert ifno == 0 (part of hub spec) */  	switch (code) { @@ -1692,11 +1691,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 (hdev->children[i] == NULL) +				if (hub->ports[i]->child == NULL)  					info->port[i] = 0;  				else  					info->port[i] = -						hdev->children[i]->devnum; +						hub->ports[i]->child->devnum;  			}  		}  		spin_unlock_irq(&device_state_lock); @@ -1784,11 +1783,12 @@ 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 (udev->children[i]) -			recursively_mark_NOTATTACHED(udev->children[i]); +		if (hub->ports[i]->child) +			recursively_mark_NOTATTACHED(hub->ports[i]->child);  	}  	if (udev->state == USB_STATE_SUSPENDED)  		udev->active_duration -= jiffies; @@ -1952,6 +1952,7 @@ 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 @@ -1966,8 +1967,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 (udev->children[i]) -			usb_disconnect(&udev->children[i]); +		if (hub->ports[i]->child) +			usb_disconnect(&hub->ports[i]->child);  	}  	/* deallocate hcd/hardware state ... nuking all pending urbs and @@ -3131,7 +3132,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 = hdev->children [port1-1]; +		udev = hub->ports[port1 - 1]->child;  		if (udev && udev->can_submit) {  			dev_warn(&intf->dev, "port %d nyet suspended\n", port1);  			if (PMSG_IS_AUTO(msg)) @@ -4058,7 +4059,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 = hdev->children[port1 - 1]; +		struct usb_device	*udev = hub->ports[port1 - 1]->child;  		int			delta;  		if (!udev) @@ -4122,7 +4123,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  #endif  	/* Try to resuscitate an existing device */ -	udev = hdev->children[port1-1]; +	udev = hub->ports[port1 - 1]->child;  	if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&  			udev->state != USB_STATE_NOTATTACHED) {  		usb_lock_device(udev); @@ -4151,7 +4152,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  	/* Disconnect any existing devices under this port */  	if (udev) -		usb_disconnect(&hdev->children[port1-1]); +		usb_disconnect(&hub->ports[port1 - 1]->child);  	clear_bit(port1, hub->change_bits);  	/* We can forget about a "removed" device when there's a physical @@ -4287,7 +4288,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  		if (hdev->state == USB_STATE_NOTATTACHED)  			status = -ENOTCONN;  		else -			hdev->children[port1-1] = udev; +			hub->ports[port1 - 1]->child = udev;  		spin_unlock_irq(&device_state_lock);  		/* Run it through the hoops (find a driver, etc) */ @@ -4295,7 +4296,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); -				hdev->children[port1-1] = NULL; +				hub->ports[port1 - 1]->child = NULL;  				spin_unlock_irq(&device_state_lock);  			}  		} @@ -4341,7 +4342,7 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port,  	int ret;  	hdev = hub->hdev; -	udev = hdev->children[port-1]; +	udev = hub->ports[port - 1]->child;  	if (!hub_is_superspeed(hdev)) {  		if (!(portchange & USB_PORT_STAT_C_SUSPEND))  			return 0; @@ -4495,7 +4496,7 @@ static void hub_events(void)  				 */  				if (!(portstatus & USB_PORT_STAT_ENABLE)  				    && !connect_change -				    && hdev->children[i-1]) { +				    && hub->ports[i - 1]->child) {  					dev_err (hub_dev,  					    "port %i "  					    "disabled by hub (EMI?), " @@ -5052,3 +5053,27 @@ void usb_queue_reset_device(struct usb_interface *iface)  	schedule_work(&iface->reset_ws);  }  EXPORT_SYMBOL_GPL(usb_queue_reset_device); + +/** + * usb_hub_find_child - Get the pointer of child device + * attached to the port which is specified by @port1. + * @hdev: USB device belonging to the usb hub + * @port1: port num to indicate which port the child device + *	is attached to. + * + * USB drivers call this function to get hub's child device + * pointer. + * + * Return NULL if input param is invalid and + * child's usb_device pointer if non-NULL. + */ +struct usb_device *usb_hub_find_child(struct usb_device *hdev, +		int port1) +{ +	struct usb_hub *hub = hdev_to_hub(hdev); + +	if (port1 < 1 || port1 > hdev->maxchild) +		return NULL; +	return hub->ports[port1 - 1]->child; +} +EXPORT_SYMBOL_GPL(usb_hub_find_child); diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 4c634eb5635..fcc09e5ec0a 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2029,15 +2029,14 @@ static int r8a66597_get_frame(struct usb_hcd *hcd)  static void collect_usb_address_map(struct usb_device *udev, unsigned long *map)  {  	int chix; +	struct usb_device *childdev;  	if (udev->state == USB_STATE_CONFIGURED &&  	    udev->parent && udev->parent->devnum > 1 &&  	    udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB)  		map[udev->devnum/32] |= (1 << (udev->devnum % 32)); -	for (chix = 0; chix < udev->maxchild; chix++) { -		struct usb_device *childdev = udev->children[chix]; - +	usb_hub_for_each_child(udev, chix, childdev) {  		if (childdev)  			collect_usb_address_map(childdev, map);  	} diff --git a/include/linux/usb.h b/include/linux/usb.h index 30d1ae38eab..ff8ef2d2858 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -469,7 +469,6 @@ struct usb3_lpm_parameters {   *	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 @@ -543,7 +542,6 @@ struct usb_device {  	struct list_head filelist;  	int maxchild; -	struct usb_device **children;  	u32 quirks;  	atomic_t urbnum; @@ -572,6 +570,19 @@ 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_hub_find_child(struct usb_device *hdev, +	int port1); + +/** + * usb_hub_for_each_child - iterate over all child devices on the hub + * @hdev:  USB device belonging to the usb hub + * @port1: portnum associated with child device + * @child: child device pointer + */ +#define usb_hub_for_each_child(hdev, port1, child) \ +	for (port1 = 1,	child =	usb_hub_find_child(hdev, port1); \ +		port1 <= hdev->maxchild; \ +		child = usb_hub_find_child(hdev, ++port1))  /* USB device locking */  #define usb_lock_device(udev)		device_lock(&(udev)->dev)  |