Commit ff823c79 authored by Lan Tianyu's avatar Lan Tianyu Committed by Greg Kroah-Hartman

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: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarLan Tianyu <tianyu.lan@intel.com>
Signed-off-by: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent fa2a9566
...@@ -157,8 +157,7 @@ static void usbip_dump_usb_device(struct usb_device *udev) ...@@ -157,8 +157,7 @@ static void usbip_dump_usb_device(struct usb_device *udev)
dev_dbg(dev, "have_langid %d, string_langid %d\n", dev_dbg(dev, "have_langid %d, string_langid %d\n",
udev->have_langid, udev->string_langid); udev->have_langid, udev->string_langid);
dev_dbg(dev, "maxchild %d, children %p\n", dev_dbg(dev, "maxchild %d\n", udev->maxchild);
udev->maxchild, udev->children);
} }
static void usbip_dump_request_type(__u8 rt) static void usbip_dump_request_type(__u8 rt)
......
...@@ -496,6 +496,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, ...@@ -496,6 +496,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
char *pages_start, *data_end, *speed; char *pages_start, *data_end, *speed;
unsigned int length; unsigned int length;
ssize_t total_written = 0; ssize_t total_written = 0;
struct usb_device *childdev = NULL;
/* don't bother with anything else if we're not writing any data */ /* don't bother with anything else if we're not writing any data */
if (*nbytes <= 0) if (*nbytes <= 0)
...@@ -589,14 +590,12 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, ...@@ -589,14 +590,12 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
free_pages((unsigned long)pages_start, 1); free_pages((unsigned long)pages_start, 1);
/* Now look at all of this device's children. */ /* Now look at all of this device's children. */
for (chix = 0; chix < usbdev->maxchild; chix++) { usb_hub_for_each_child(usbdev, chix, childdev) {
struct usb_device *childdev = usbdev->children[chix];
if (childdev) { if (childdev) {
usb_lock_device(childdev); usb_lock_device(childdev);
ret = usb_device_dump(buffer, nbytes, skip_bytes, ret = usb_device_dump(buffer, nbytes, skip_bytes,
file_offset, childdev, bus, file_offset, childdev, bus,
level + 1, chix, ++cnt); level + 1, chix - 1, ++cnt);
usb_unlock_device(childdev); usb_unlock_device(childdev);
if (ret == -EFAULT) if (ret == -EFAULT)
return total_written; return total_written;
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#endif #endif
struct usb_port { struct usb_port {
struct usb_device *child;
struct device dev; struct device dev;
struct dev_state *port_owner; struct dev_state *port_owner;
}; };
...@@ -181,7 +182,7 @@ static inline char *portspeed(struct usb_hub *hub, int portstatus) ...@@ -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! */ /* Note that hdev or one of its children must be locked! */
static struct usb_hub *hdev_to_hub(struct usb_device *hdev) static struct usb_hub *hdev_to_hub(struct usb_device *hdev)
{ {
if (!hdev || !hdev->actconfig) if (!hdev || !hdev->actconfig || !hdev->maxchild)
return NULL; return NULL;
return usb_get_intfdata(hdev->actconfig->interface[0]); 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) ...@@ -876,8 +877,8 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
struct usb_device *hdev = hub->hdev; struct usb_device *hdev = hub->hdev;
int ret = 0; int ret = 0;
if (hdev->children[port1-1] && set_state) if (hub->ports[port1 - 1]->child && set_state)
usb_set_device_state(hdev->children[port1-1], usb_set_device_state(hub->ports[port1 - 1]->child,
USB_STATE_NOTATTACHED); USB_STATE_NOTATTACHED);
if (!hub->error && !hub_is_superspeed(hub->hdev)) if (!hub->error && !hub_is_superspeed(hub->hdev))
ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); 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) ...@@ -1033,7 +1034,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
* which ports need attention. * which ports need attention.
*/ */
for (port1 = 1; port1 <= hdev->maxchild; ++port1) { 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; u16 portstatus, portchange;
portstatus = portchange = 0; portstatus = portchange = 0;
...@@ -1198,8 +1199,8 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) ...@@ -1198,8 +1199,8 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
if (type != HUB_SUSPEND) { if (type != HUB_SUSPEND) {
/* Disconnect all the children */ /* Disconnect all the children */
for (i = 0; i < hdev->maxchild; ++i) { for (i = 0; i < hdev->maxchild; ++i) {
if (hdev->children[i]) if (hub->ports[i]->child)
usb_disconnect(&hdev->children[i]); usb_disconnect(&hub->ports[i]->child);
} }
} }
...@@ -1324,11 +1325,9 @@ static int hub_configure(struct usb_hub *hub, ...@@ -1324,11 +1325,9 @@ static int hub_configure(struct usb_hub *hub,
dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild, dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild,
(hdev->maxchild == 1) ? "" : "s"); (hdev->maxchild == 1) ? "" : "s");
hdev->children = kzalloc(hdev->maxchild *
sizeof(struct usb_device *), GFP_KERNEL);
hub->ports = kzalloc(hdev->maxchild * sizeof(struct usb_port *), hub->ports = kzalloc(hdev->maxchild * sizeof(struct usb_port *),
GFP_KERNEL); GFP_KERNEL);
if (!hdev->children || !hub->ports) { if (!hub->ports) {
ret = -ENOMEM; ret = -ENOMEM;
goto fail; goto fail;
} }
...@@ -1591,7 +1590,6 @@ static void hub_disconnect(struct usb_interface *intf) ...@@ -1591,7 +1590,6 @@ static void hub_disconnect(struct usb_interface *intf)
highspeed_hubs--; highspeed_hubs--;
usb_free_urb(hub->urb); usb_free_urb(hub->urb);
kfree(hdev->children);
kfree(hub->ports); kfree(hub->ports);
kfree(hub->descriptor); kfree(hub->descriptor);
kfree(hub->status); kfree(hub->status);
...@@ -1679,6 +1677,7 @@ static int ...@@ -1679,6 +1677,7 @@ static int
hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
{ {
struct usb_device *hdev = interface_to_usbdev (intf); struct usb_device *hdev = interface_to_usbdev (intf);
struct usb_hub *hub = hdev_to_hub(hdev);
/* assert ifno == 0 (part of hub spec) */ /* assert ifno == 0 (part of hub spec) */
switch (code) { switch (code) {
...@@ -1692,11 +1691,11 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) ...@@ -1692,11 +1691,11 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
else { else {
info->nports = hdev->maxchild; info->nports = hdev->maxchild;
for (i = 0; i < info->nports; i++) { for (i = 0; i < info->nports; i++) {
if (hdev->children[i] == NULL) if (hub->ports[i]->child == NULL)
info->port[i] = 0; info->port[i] = 0;
else else
info->port[i] = info->port[i] =
hdev->children[i]->devnum; hub->ports[i]->child->devnum;
} }
} }
spin_unlock_irq(&device_state_lock); spin_unlock_irq(&device_state_lock);
...@@ -1784,11 +1783,12 @@ bool usb_device_is_owned(struct usb_device *udev) ...@@ -1784,11 +1783,12 @@ bool usb_device_is_owned(struct usb_device *udev)
static void recursively_mark_NOTATTACHED(struct usb_device *udev) static void recursively_mark_NOTATTACHED(struct usb_device *udev)
{ {
struct usb_hub *hub = hdev_to_hub(udev);
int i; int i;
for (i = 0; i < udev->maxchild; ++i) { for (i = 0; i < udev->maxchild; ++i) {
if (udev->children[i]) if (hub->ports[i]->child)
recursively_mark_NOTATTACHED(udev->children[i]); recursively_mark_NOTATTACHED(hub->ports[i]->child);
} }
if (udev->state == USB_STATE_SUSPENDED) if (udev->state == USB_STATE_SUSPENDED)
udev->active_duration -= jiffies; udev->active_duration -= jiffies;
...@@ -1952,6 +1952,7 @@ static void hub_free_dev(struct usb_device *udev) ...@@ -1952,6 +1952,7 @@ static void hub_free_dev(struct usb_device *udev)
void usb_disconnect(struct usb_device **pdev) void usb_disconnect(struct usb_device **pdev)
{ {
struct usb_device *udev = *pdev; struct usb_device *udev = *pdev;
struct usb_hub *hub = hdev_to_hub(udev);
int i; int i;
/* mark the device as inactive, so any further urb submissions for /* mark the device as inactive, so any further urb submissions for
...@@ -1966,8 +1967,8 @@ void usb_disconnect(struct usb_device **pdev) ...@@ -1966,8 +1967,8 @@ void usb_disconnect(struct usb_device **pdev)
/* Free up all the children before we remove this device */ /* Free up all the children before we remove this device */
for (i = 0; i < udev->maxchild; i++) { for (i = 0; i < udev->maxchild; i++) {
if (udev->children[i]) if (hub->ports[i]->child)
usb_disconnect(&udev->children[i]); usb_disconnect(&hub->ports[i]->child);
} }
/* deallocate hcd/hardware state ... nuking all pending urbs and /* 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) ...@@ -3131,7 +3132,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
for (port1 = 1; port1 <= hdev->maxchild; port1++) { for (port1 = 1; port1 <= hdev->maxchild; port1++) {
struct usb_device *udev; struct usb_device *udev;
udev = hdev->children [port1-1]; udev = hub->ports[port1 - 1]->child;
if (udev && udev->can_submit) { if (udev && udev->can_submit) {
dev_warn(&intf->dev, "port %d nyet suspended\n", port1); dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
if (PMSG_IS_AUTO(msg)) if (PMSG_IS_AUTO(msg))
...@@ -4058,7 +4059,7 @@ hub_power_remaining (struct usb_hub *hub) ...@@ -4058,7 +4059,7 @@ hub_power_remaining (struct usb_hub *hub)
remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent; remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent;
for (port1 = 1; port1 <= hdev->maxchild; ++port1) { 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; int delta;
if (!udev) if (!udev)
...@@ -4122,7 +4123,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, ...@@ -4122,7 +4123,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
#endif #endif
/* Try to resuscitate an existing device */ /* Try to resuscitate an existing device */
udev = hdev->children[port1-1]; udev = hub->ports[port1 - 1]->child;
if ((portstatus & USB_PORT_STAT_CONNECTION) && udev && if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
udev->state != USB_STATE_NOTATTACHED) { udev->state != USB_STATE_NOTATTACHED) {
usb_lock_device(udev); usb_lock_device(udev);
...@@ -4151,7 +4152,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, ...@@ -4151,7 +4152,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
/* Disconnect any existing devices under this port */ /* Disconnect any existing devices under this port */
if (udev) if (udev)
usb_disconnect(&hdev->children[port1-1]); usb_disconnect(&hub->ports[port1 - 1]->child);
clear_bit(port1, hub->change_bits); clear_bit(port1, hub->change_bits);
/* We can forget about a "removed" device when there's a physical /* 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, ...@@ -4287,7 +4288,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
if (hdev->state == USB_STATE_NOTATTACHED) if (hdev->state == USB_STATE_NOTATTACHED)
status = -ENOTCONN; status = -ENOTCONN;
else else
hdev->children[port1-1] = udev; hub->ports[port1 - 1]->child = udev;
spin_unlock_irq(&device_state_lock); spin_unlock_irq(&device_state_lock);
/* Run it through the hoops (find a driver, etc) */ /* 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, ...@@ -4295,7 +4296,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
status = usb_new_device(udev); status = usb_new_device(udev);
if (status) { if (status) {
spin_lock_irq(&device_state_lock); spin_lock_irq(&device_state_lock);
hdev->children[port1-1] = NULL; hub->ports[port1 - 1]->child = NULL;
spin_unlock_irq(&device_state_lock); spin_unlock_irq(&device_state_lock);
} }
} }
...@@ -4341,7 +4342,7 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, ...@@ -4341,7 +4342,7 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port,
int ret; int ret;
hdev = hub->hdev; hdev = hub->hdev;
udev = hdev->children[port-1]; udev = hub->ports[port - 1]->child;
if (!hub_is_superspeed(hdev)) { if (!hub_is_superspeed(hdev)) {
if (!(portchange & USB_PORT_STAT_C_SUSPEND)) if (!(portchange & USB_PORT_STAT_C_SUSPEND))
return 0; return 0;
...@@ -4495,7 +4496,7 @@ static void hub_events(void) ...@@ -4495,7 +4496,7 @@ static void hub_events(void)
*/ */
if (!(portstatus & USB_PORT_STAT_ENABLE) if (!(portstatus & USB_PORT_STAT_ENABLE)
&& !connect_change && !connect_change
&& hdev->children[i-1]) { && hub->ports[i - 1]->child) {
dev_err (hub_dev, dev_err (hub_dev,
"port %i " "port %i "
"disabled by hub (EMI?), " "disabled by hub (EMI?), "
...@@ -5052,3 +5053,27 @@ void usb_queue_reset_device(struct usb_interface *iface) ...@@ -5052,3 +5053,27 @@ void usb_queue_reset_device(struct usb_interface *iface)
schedule_work(&iface->reset_ws); schedule_work(&iface->reset_ws);
} }
EXPORT_SYMBOL_GPL(usb_queue_reset_device); 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);
...@@ -2029,15 +2029,14 @@ static int r8a66597_get_frame(struct usb_hcd *hcd) ...@@ -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) static void collect_usb_address_map(struct usb_device *udev, unsigned long *map)
{ {
int chix; int chix;
struct usb_device *childdev;
if (udev->state == USB_STATE_CONFIGURED && if (udev->state == USB_STATE_CONFIGURED &&
udev->parent && udev->parent->devnum > 1 && udev->parent && udev->parent->devnum > 1 &&
udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB) udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB)
map[udev->devnum/32] |= (1 << (udev->devnum % 32)); map[udev->devnum/32] |= (1 << (udev->devnum % 32));
for (chix = 0; chix < udev->maxchild; chix++) { usb_hub_for_each_child(udev, chix, childdev) {
struct usb_device *childdev = udev->children[chix];
if (childdev) if (childdev)
collect_usb_address_map(childdev, map); collect_usb_address_map(childdev, map);
} }
......
...@@ -469,7 +469,6 @@ struct usb3_lpm_parameters { ...@@ -469,7 +469,6 @@ struct usb3_lpm_parameters {
* access from userspace * access from userspace
* @usbfs_dentry: usbfs dentry entry for the device * @usbfs_dentry: usbfs dentry entry for the device
* @maxchild: number of ports if hub * @maxchild: number of ports if hub
* @children: child devices - USB devices that are attached to this hub
* @quirks: quirks of the whole device * @quirks: quirks of the whole device
* @urbnum: number of URBs submitted for the whole device * @urbnum: number of URBs submitted for the whole device
* @active_duration: total time device is not suspended * @active_duration: total time device is not suspended
...@@ -543,7 +542,6 @@ struct usb_device { ...@@ -543,7 +542,6 @@ struct usb_device {
struct list_head filelist; struct list_head filelist;
int maxchild; int maxchild;
struct usb_device **children;
u32 quirks; u32 quirks;
atomic_t urbnum; atomic_t urbnum;
...@@ -572,6 +570,19 @@ static inline struct usb_device *interface_to_usbdev(struct usb_interface *intf) ...@@ -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 struct usb_device *usb_get_dev(struct usb_device *dev);
extern void usb_put_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 */ /* USB device locking */
#define usb_lock_device(udev) device_lock(&(udev)->dev) #define usb_lock_device(udev) device_lock(&(udev)->dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment