On Mon, 2 Nov 2015, Michael Reutman wrote:

> On Wed, Oct 28, 2015 at 10:48 AM, Alan Stern <st...@rowland.harvard.edu> 
> wrote:
> > The patch below is meant to apply on top of the previous patch.  It's a
> > quick-and-dirty workaround which ought to prevent the problem from
> > occurring.  Let's see if it does.
> 
> Unfortunately, I have some bad news. It appears that the last patch
> just pushes the issue further on down in time. Ran the test fresh
> today and usb got "stuck" in around 15 to 20 minutes. This has
> definitely improved things from before where it took less than a
> minute to get everything out of sorts, so maybe we are on the right
> track?

Here's a revised quick-and-dirty workaround.  It replaces the earlier 
one.  (And like the earlier one, it is meant to apply on top of 
the usbfs-snoop patch, but I don't think that makes any difference 
now.)

The idea is to wait until the QH has remain unchanged for at least 2 ms 
before deciding that the host controller has stopped using it.  If this 
doesn't fix the problem then I will be completely out of ideas and will 
have to ask for help from someone at AMD.

When testing this, don't bother with the usbfs-snoop stuff.  With luck 
it won't matter, because the test program won't hang.

Alan Stern




Index: usb-4.3/drivers/usb/host/ehci-q.c
===================================================================
--- usb-4.3.orig/drivers/usb/host/ehci-q.c
+++ usb-4.3/drivers/usb/host/ehci-q.c
@@ -1341,8 +1341,22 @@ static void end_unlink_async(struct ehci
        }
 
        /* Otherwise process only the first waiting QH (NVIDIA bug?) */
-       else
+       else {
+               __hc32          qh_current, qh_token, old_current, old_token;
+
                list_move_tail(&qh->unlink_node, &ehci->async_idle);
+               old_current = qh->hw->hw_current;
+               old_token = qh->hw->hw_token;
+               for (;;) {
+                       udelay(2000);
+                       qh_current = READ_ONCE(qh->hw->hw_current);
+                       qh_token = READ_ONCE(qh->hw->hw_token);
+                       if (qh_current == old_current && qh_token == old_token)
+                               break;
+                       old_current = qh_current;
+                       old_token = qh_token;
+               }
+       }
 
        /* Start a new IAA cycle if any QHs are waiting for it */
        if (!list_empty(&ehci->async_unlink))

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

Reply via email to