summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2013-03-07 16:23:30 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-03-14 11:26:37 -0700
commit4b996365813db4759bf923cec9647e92ca1c213d (patch)
tree2de746a6f7d652ec7076219732677c6b120a7182
parent9f677cf27341b7a53915ad0e018912dc022a2a24 (diff)
USB: Don't use EHCI port sempahore for USB 3.0 hubs.
[This is upstream commit 0fe51aa5eee51db7c7ecd201d42a977ad79c58b6. It needs to be backported to kernels as old as 3.2, because it fixes the buggy commit 65bdac5effd15d6af619b3b7218627ef4d84ed6a "USB: Handle warm reset failure on empty port."] The EHCI host controller needs to prevent EHCI initialization when the UHCI or OHCI companion controller is in the middle of a port reset. It uses ehci_cf_port_reset_rwsem to do this. USB 3.0 hubs can't be under an EHCI host controller, so it makes no sense to down the semaphore for USB 3.0 hubs. It also makes the warm port reset code more complex. Don't down ehci_cf_port_reset_rwsem for USB 3.0 hubs. Signed-off-by: Sarah Sharp <sarah.a.sharp@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/hub.c15
1 files changed, 7 insertions, 8 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index cbf7168e3ce7..f9de94eb3c40 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2661,17 +2661,16 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
{
int i, status;
- if (!warm) {
- /* Block EHCI CF initialization during the port reset.
- * Some companion controllers don't like it when they mix.
- */
- down_read(&ehci_cf_port_reset_rwsem);
- } else {
- if (!hub_is_superspeed(hub->hdev)) {
+ if (!hub_is_superspeed(hub->hdev)) {
+ if (warm) {
dev_err(hub->intfdev, "only USB3 hub support "
"warm reset\n");
return -EINVAL;
}
+ /* Block EHCI CF initialization during the port reset.
+ * Some companion controllers don't like it when they mix.
+ */
+ down_read(&ehci_cf_port_reset_rwsem);
}
/* Reset the port */
@@ -2709,7 +2708,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
port1);
done:
- if (!warm)
+ if (!hub_is_superspeed(hub->hdev))
up_read(&ehci_cf_port_reset_rwsem);
return status;