Hi Alan,

On Wed, Jan 16, 2013 at 10:55:50AM -0500, Alan Stern wrote:
[...]
> I changed my mind -- it turns out that adding the fix is somewhat
> easier than unlinking one QH at a time.
> 
> So now we're ready for some serious testing.  The patch below is based 
> on the 3.7 kernel, and it doesn't include any of the debugging stuff 
> you have been using.  Remove all the old patches and apply this one 
> instead.  It has two changes: the increase in the schedule polling time 
> and the fix for multiple unlinks.
> 
> If this causes the problem to go away then I will submit it for 
> inclusion in the stable kernel series.

I tried the patch below with kernel 3.7, I updated
my local git copy to that version.

I'm sorry to say it does not seem to fix the issue.

Some explanation, I made three trials, with reboot
inbetween, of course.
The first one got the error -110 almost immediately,
the second did not show any problem, even with some
load of the CPU, the third did show the error, but
after some time, specifically after I loaded the
I/O sub system with a kernel recompilation.
Note that, during the compilation (make -j5) the transfer
rate of the USB HDDs went up and down, with about a
decrease of 10% from the usual one (from 4100 KB/sec to
3700 KB/sec) as minimum. This I did not notice before,
but maybe I just did not notice...

I also tried to run twice the USB HDDs reading, in
this case, while the problem did not show up, I could
see that the transfer rate did not change, maybe the
multiple queue operation did have some positive effects.

Nevertheless, bottom line is that I got the problem two
out of three times, so it seems to me the fix was not
completely effective.

I've some log, but there's a lot of garbage in it, I
esitate to post here or on the bugzilla page, if you
want I can dig something or I can retry in order to
get a cleaner one.

Hope this helps,

bye,

pg

> Alan Stern
> 
> 
> 
> Index: 3.7/drivers/usb/host/ehci-timer.c
> ===================================================================
> --- 3.7.orig/drivers/usb/host/ehci-timer.c
> +++ 3.7/drivers/usb/host/ehci-timer.c
> @@ -113,21 +113,22 @@ static void ehci_poll_ASS(struct ehci_hc
>  
>       if (want != actual) {
>  
> -             /* Poll again later, but give up after about 20 ms */
> -             if (ehci->ASS_poll_count++ < 20) {
> -                     ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
> -                     return;
> -             }
> -             ehci_dbg(ehci, "Waited too long for the async schedule status 
> (%x/%x), giving up\n",
> -                             want, actual);
> +             /* Poll again later */
> +             ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
> +             ++ehci->ASS_poll_count;
> +             return;
>       }
> +
> +     if (ehci->ASS_poll_count > 20)
> +             ehci_dbg(ehci, "ASS poll count reached %d\n",
> +                             ehci->ASS_poll_count);
>       ehci->ASS_poll_count = 0;
>  
>       /* The status is up-to-date; restart or stop the schedule as needed */
>       if (want == 0) {        /* Stopped */
> -             if (ehci->async_count > 0)
> +             if (ehci->async_count > 0) {
>                       ehci_set_command_bit(ehci, CMD_ASE);
> -
> +             }
>       } else {                /* Running */
>               if (ehci->async_count == 0) {
>  
> @@ -159,14 +160,14 @@ static void ehci_poll_PSS(struct ehci_hc
>  
>       if (want != actual) {
>  
> -             /* Poll again later, but give up after about 20 ms */
> -             if (ehci->PSS_poll_count++ < 20) {
> -                     ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
> -                     return;
> -             }
> -             ehci_dbg(ehci, "Waited too long for the periodic schedule 
> status (%x/%x), giving up\n",
> -                             want, actual);
> +             /* Poll again later */
> +             ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
> +             return;
>       }
> +
> +     if (ehci->PSS_poll_count > 20)
> +             ehci_dbg(ehci, "PSS poll count reached %d\n",
> +                             ehci->PSS_poll_count);
>       ehci->PSS_poll_count = 0;
>  
>       /* The status is up-to-date; restart or stop the schedule as needed */
> Index: 3.7/drivers/usb/host/ehci-q.c
> ===================================================================
> --- 3.7.orig/drivers/usb/host/ehci-q.c
> +++ 3.7/drivers/usb/host/ehci-q.c
> @@ -1174,6 +1174,18 @@ submit_async (
>  static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
>  {
>       struct ehci_qh          *prev;
> +     __hc32                  dma = QH_NEXT(ehci, qh->qh_dma);
> +     __hc32                  dma_next = qh->hw->hw_next;
> +
> +     /* No QH on the unlink lists should point to qh */
> +     for (prev = ehci->async_unlink; prev; prev = prev->unlink_next) {
> +             if (prev->hw->hw_next == dma)
> +                     prev->hw->hw_next = dma_next;
> +     }
> +     for (prev = ehci->async_iaa; prev; prev = prev->unlink_next) {
> +             if (prev->hw->hw_next == dma)
> +                     prev->hw->hw_next = dma_next;
> +     }
>  
>       /* Add to the end of the list of QHs waiting for the next IAAD */
>       qh->qh_state = QH_STATE_UNLINK;
> @@ -1188,7 +1200,7 @@ static void single_unlink_async(struct e
>       while (prev->qh_next.qh != qh)
>               prev = prev->qh_next.qh;
>  
> -     prev->hw->hw_next = qh->hw->hw_next;
> +     prev->hw->hw_next = dma_next;
>       prev->qh_next = qh->qh_next;
>       if (ehci->qh_scan_next == qh)
>               ehci->qh_scan_next = qh->qh_next.qh;

-- 

piergiorgio
--
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