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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html