diff options
author | Petr Mladek <pmladek@suse.cz> | 2014-09-19 11:32:24 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-09-24 01:33:19 -0400 |
commit | 638139eb95d2d241781330a321e88c8dafe46078 (patch) | |
tree | ccb7df7cabe74a62e0bd707f7700f0e4efb5516e /drivers/usb | |
parent | 37ebb54915dc42944f6ae92fe53b9531c3903801 (diff) |
usb: hub: allow to process more usb hub events in parallel
It seems that only choose_devnum() was not ready to process more hub
events at the same time.
All should be fine if we take bus->usb_address0_mutex there. It will
make sure that more devnums will not be chosen for the given bus and
the related devices at the same time.
Signed-off-by: Petr Mladek <pmladek@suse.cz>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/hub.c | 9 |
1 files changed, 4 insertions, 5 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 12a4c67667b1..374b3f93071c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -2045,7 +2045,8 @@ static void choose_devnum(struct usb_device *udev) | |||
2045 | int devnum; | 2045 | int devnum; |
2046 | struct usb_bus *bus = udev->bus; | 2046 | struct usb_bus *bus = udev->bus; |
2047 | 2047 | ||
2048 | /* If hub_wq ever becomes multithreaded, this will need a lock */ | 2048 | /* be safe when more hub events are proceed in parallel */ |
2049 | mutex_lock(&bus->usb_address0_mutex); | ||
2049 | if (udev->wusb) { | 2050 | if (udev->wusb) { |
2050 | devnum = udev->portnum + 1; | 2051 | devnum = udev->portnum + 1; |
2051 | BUG_ON(test_bit(devnum, bus->devmap.devicemap)); | 2052 | BUG_ON(test_bit(devnum, bus->devmap.devicemap)); |
@@ -2063,6 +2064,7 @@ static void choose_devnum(struct usb_device *udev) | |||
2063 | set_bit(devnum, bus->devmap.devicemap); | 2064 | set_bit(devnum, bus->devmap.devicemap); |
2064 | udev->devnum = devnum; | 2065 | udev->devnum = devnum; |
2065 | } | 2066 | } |
2067 | mutex_unlock(&bus->usb_address0_mutex); | ||
2066 | } | 2068 | } |
2067 | 2069 | ||
2068 | static void release_devnum(struct usb_device *udev) | 2070 | static void release_devnum(struct usb_device *udev) |
@@ -5164,11 +5166,8 @@ int usb_hub_init(void) | |||
5164 | * USB-PERSIST port handover. Otherwise it might see that a full-speed | 5166 | * USB-PERSIST port handover. Otherwise it might see that a full-speed |
5165 | * device was gone before the EHCI controller had handed its port | 5167 | * device was gone before the EHCI controller had handed its port |
5166 | * over to the companion full-speed controller. | 5168 | * over to the companion full-speed controller. |
5167 | * | ||
5168 | * Also we use ordered workqueue because the code is not ready | ||
5169 | * for parallel execution of hub events, see choose_devnum(). | ||
5170 | */ | 5169 | */ |
5171 | hub_wq = alloc_ordered_workqueue("usb_hub_wq", WQ_FREEZABLE); | 5170 | hub_wq = alloc_workqueue("usb_hub_wq", WQ_FREEZABLE, 0); |
5172 | if (hub_wq) | 5171 | if (hub_wq) |
5173 | return 0; | 5172 | return 0; |
5174 | 5173 | ||