Commit 6fecd4f2 authored by Todd E Brandt's avatar Todd E Brandt Committed by Greg Kroah-Hartman

USB: separate usb_address0 mutexes for each bus

This patch creates a separate instance of the usb_address0 mutex for each USB
bus, and attaches it to the usb_bus device struct. This allows devices on
separate buses to be enumerated in parallel; saving time.

In the current code, there is a single, global instance of the usb_address0
mutex which is used for all devices on all buses. This isn't completely
necessary, as this mutex is only needed to prevent address0 collisions for
devices on the *same* bus (usb 2.0 spec, sec 4.6.1). This superfluous coverage
can cause additional delay in system resume on systems with multiple hosts
(up to several seconds depending on what devices are attached).
Signed-off-by: default avatarTodd Brandt <todd.e.brandt@linux.intel.com>
Acked-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0a939993
...@@ -918,6 +918,7 @@ static void usb_bus_init (struct usb_bus *bus) ...@@ -918,6 +918,7 @@ static void usb_bus_init (struct usb_bus *bus)
bus->bandwidth_allocated = 0; bus->bandwidth_allocated = 0;
bus->bandwidth_int_reqs = 0; bus->bandwidth_int_reqs = 0;
bus->bandwidth_isoc_reqs = 0; bus->bandwidth_isoc_reqs = 0;
mutex_init(&bus->usb_address0_mutex);
INIT_LIST_HEAD (&bus->bus_list); INIT_LIST_HEAD (&bus->bus_list);
} }
......
...@@ -4016,8 +4016,6 @@ static int ...@@ -4016,8 +4016,6 @@ static int
hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
int retry_counter) int retry_counter)
{ {
static DEFINE_MUTEX(usb_address0_mutex);
struct usb_device *hdev = hub->hdev; struct usb_device *hdev = hub->hdev;
struct usb_hcd *hcd = bus_to_hcd(hdev->bus); struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
int i, j, retval; int i, j, retval;
...@@ -4040,7 +4038,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, ...@@ -4040,7 +4038,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
if (oldspeed == USB_SPEED_LOW) if (oldspeed == USB_SPEED_LOW)
delay = HUB_LONG_RESET_TIME; delay = HUB_LONG_RESET_TIME;
mutex_lock(&usb_address0_mutex); mutex_lock(&hdev->bus->usb_address0_mutex);
/* Reset the device; full speed may morph to high speed */ /* Reset the device; full speed may morph to high speed */
/* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */ /* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */
...@@ -4317,7 +4315,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, ...@@ -4317,7 +4315,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
hub_port_disable(hub, port1, 0); hub_port_disable(hub, port1, 0);
update_devnum(udev, devnum); /* for disconnect processing */ update_devnum(udev, devnum); /* for disconnect processing */
} }
mutex_unlock(&usb_address0_mutex); mutex_unlock(&hdev->bus->usb_address0_mutex);
return retval; return retval;
} }
......
...@@ -352,6 +352,8 @@ struct usb_bus { ...@@ -352,6 +352,8 @@ struct usb_bus {
struct usb_bus *hs_companion; /* Companion EHCI bus, if any */ struct usb_bus *hs_companion; /* Companion EHCI bus, if any */
struct list_head bus_list; /* list of busses */ struct list_head bus_list; /* list of busses */
struct mutex usb_address0_mutex; /* unaddressed device mutex */
int bandwidth_allocated; /* on this bus: how much of the time int bandwidth_allocated; /* on this bus: how much of the time
* reserved for periodic (intr/iso) * reserved for periodic (intr/iso)
* requests is used, on average? * requests is used, on average?
......
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