summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd E Brandt <todd.e.brandt@linux.intel.com>2014-05-19 21:55:32 +0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-05-28 03:11:49 +0400
commit6fecd4f2a58c60028b1a75deefcf111516d3f836 (patch)
tree2bb7aded8a2e19b7f54330d6b8a28d910436ecd1
parent0a939993bff117d3657108ca13b011fc0378aedb (diff)
downloadlinux-6fecd4f2a58c60028b1a75deefcf111516d3f836.tar.xz
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: Todd Brandt <todd.e.brandt@linux.intel.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/core/hcd.c1
-rw-r--r--drivers/usb/core/hub.c6
-rw-r--r--include/linux/usb.h2
3 files changed, 5 insertions, 4 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index adddc66c9e8d..174eb857a6b4 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -918,6 +918,7 @@ static void usb_bus_init (struct usb_bus *bus)
bus->bandwidth_allocated = 0;
bus->bandwidth_int_reqs = 0;
bus->bandwidth_isoc_reqs = 0;
+ mutex_init(&bus->usb_address0_mutex);
INIT_LIST_HEAD (&bus->bus_list);
}
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 090469ebfcff..726fa072c3fe 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -4016,8 +4016,6 @@ static int
hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
int retry_counter)
{
- static DEFINE_MUTEX(usb_address0_mutex);
-
struct usb_device *hdev = hub->hdev;
struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
int i, j, retval;
@@ -4040,7 +4038,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
if (oldspeed == USB_SPEED_LOW)
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 */
/* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */
@@ -4317,7 +4315,7 @@ fail:
hub_port_disable(hub, port1, 0);
update_devnum(udev, devnum); /* for disconnect processing */
}
- mutex_unlock(&usb_address0_mutex);
+ mutex_unlock(&hdev->bus->usb_address0_mutex);
return retval;
}
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 6b7ec376fb4d..d2465bc0e73c 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -352,6 +352,8 @@ struct usb_bus {
struct usb_bus *hs_companion; /* Companion EHCI bus, if any */
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
* reserved for periodic (intr/iso)
* requests is used, on average?