[PATCH] USB: EHCI: fix problems involving ehci->iaa_in_progress flag

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch fixes the way ehci-hcd handles the iaa_in_progress flag.
The current code is very careless about it.

The flag is meaningless when the root hub isn't running, most
particularly after the root hub has been suspended.  But in
start_iaa_cycle(), the driver checks the flag before checking the
root-hub's state.  That routine also sets the flag too early, before
it has definitely committed to starting an IAA cycle.  Finally, when
the root hub resumes we need to clear the flag, because any IAA cycle
that was in progress when the suspend occurred will no longer be
valid.

The symptom of these problems is that following a bus resume (for
example, the first time a new device is plugged into an unused EHCI
controller), devices may not be detected properly and the khubd worker
thread can hang.  This happens because a QH unlink never finishes --
it's waiting for an IAA cycle that never got started because the
iaa_in_progress flag was set when it shouldn't have been.

This problem has existed for a long time, but recent changes have made
it more likely to occur (the timing of QH unlinks has been changed).

Signed-off-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>
Fixes: 214ac7a0771d ("USB: EHCI: improve end_unlink_async()")
CC: <stable@xxxxxxxxxxxxxxx>

---


[as1794]


 drivers/usb/host/ehci-hub.c |    3 +++
 drivers/usb/host/ehci-q.c   |   11 ++++-------
 2 files changed, 7 insertions(+), 7 deletions(-)

Index: usb-4.4/drivers/usb/host/ehci-hub.c
===================================================================
--- usb-4.4.orig/drivers/usb/host/ehci-hub.c
+++ usb-4.4/drivers/usb/host/ehci-hub.c
@@ -418,6 +418,9 @@ static int ehci_bus_resume (struct usb_h
 	ehci_writel(ehci, ehci->command, &ehci->regs->command);
 	ehci->rh_state = EHCI_RH_RUNNING;
 
+	/* If an IAA was in progress when we suspended, it's done by now */
+	ehci->iaa_in_progress = false;
+
 	/*
 	 * According to Bugzilla #8190, the port status for some controllers
 	 * will be wrong without a delay. At their wrong status, the port
Index: usb-4.4/drivers/usb/host/ehci-q.c
===================================================================
--- usb-4.4.orig/drivers/usb/host/ehci-q.c
+++ usb-4.4/drivers/usb/host/ehci-q.c
@@ -1283,17 +1283,13 @@ static void single_unlink_async(struct e
 
 static void start_iaa_cycle(struct ehci_hcd *ehci)
 {
-	/* Do nothing if an IAA cycle is already running */
-	if (ehci->iaa_in_progress)
-		return;
-	ehci->iaa_in_progress = true;
-
 	/* If the controller isn't running, we don't have to wait for it */
 	if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) {
 		end_unlink_async(ehci);
 
-	/* Otherwise start a new IAA cycle */
-	} else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) {
+	/* Otherwise start a new IAA cycle if one isn't already running */
+	} else if (ehci->rh_state == EHCI_RH_RUNNING &&
+			!ehci->iaa_in_progress) {
 
 		/* Make sure the unlinks are all visible to the hardware */
 		wmb();
@@ -1301,6 +1297,7 @@ static void start_iaa_cycle(struct ehci_
 		ehci_writel(ehci, ehci->command | CMD_IAAD,
 				&ehci->regs->command);
 		ehci_readl(ehci, &ehci->regs->command);
+		ehci->iaa_in_progress = true;
 		ehci_enable_event(ehci, EHCI_HRTIMER_IAA_WATCHDOG, true);
 	}
 }

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux