On Mon, 11 Mar 2013, Adrian Bassett wrote: > > You know, the 6e0c3339a6 commit consists of two hunks, and they are > > pretty much independent of one another. You could try reverting each > > of the hunks separately to narrow things down. Maybe only one of them > > is responsible for your problem. > > Have now been able to do this. > > Using a vanilla 3.8.2 as base but with the following commit reverted > as it's scheduled for removal in 3.8.3 anyway: > > 55bcdce8a8228223ec4d17d8ded8134ed265d2c5 - 'USB: EHCI: remove ASS/PSS polling timeout' > > Then 6e0c3339a6f19d748f16091d0a05adeb1e1f822b - 'USB: EHCI: unlink > one async QH at a time' - was also reverted and two kernels were > built. The first, 'A', incorporated the first part of 6e0c3339 > (changes to drivers/usb/host/ehci-q.c starting at line 1197) while > the second, 'B', had that code reverted in favour of the remainder of > the original composite patch. > > What I found was that 'A' was entirely un-problematic in that I could > not trigger the problem behaviour at all. On the other hand, 'B' > could be made to trigger at first suspend/resume attempt. Moreover, > whilst previously the system with the composite patch in would always > return after a few minutes, with 'B' I eventually gave up waiting and > forced a re-boot. Perhaps the first half of the original patch in > some way mitigates the effects of the second. Ah, that explains a lot. Indeed, there does appear to be a bug. I haven't tried out this patch myself, but I think it will fix your problem. It is based on 3.8 and should apply to 3.8.2. Let me know what happens. Alan Stern Index: 3.8/drivers/usb/host/ehci-hcd.c =================================================================== --- 3.8.orig/drivers/usb/host/ehci-hcd.c +++ 3.8/drivers/usb/host/ehci-hcd.c @@ -302,6 +302,7 @@ static void ehci_quiesce (struct ehci_hc static void end_unlink_async(struct ehci_hcd *ehci); static void unlink_empty_async(struct ehci_hcd *ehci); +static void unlink_empty_async_suspended(struct ehci_hcd *ehci); static void ehci_work(struct ehci_hcd *ehci); static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); Index: 3.8/drivers/usb/host/ehci-hub.c =================================================================== --- 3.8.orig/drivers/usb/host/ehci-hub.c +++ 3.8/drivers/usb/host/ehci-hub.c @@ -328,7 +328,7 @@ static int ehci_bus_suspend (struct usb_ ehci->rh_state = EHCI_RH_SUSPENDED; end_unlink_async(ehci); - unlink_empty_async(ehci); + unlink_empty_async_suspended(ehci); ehci_handle_intr_unlinks(ehci); end_free_itds(ehci); Index: 3.8/drivers/usb/host/ehci-q.c =================================================================== --- 3.8.orig/drivers/usb/host/ehci-q.c +++ 3.8/drivers/usb/host/ehci-q.c @@ -1316,6 +1316,20 @@ static void unlink_empty_async(struct eh } } +/* The root hub is suspended; unlink all the async QHs */ +static void unlink_empty_async_suspended(struct ehci_hcd *ehci) +{ + struct ehci_qh *qh, *qh_to_unlink; + + qh = ehci->async->qh_next.qh; + while (qh) { + qh_to_unlink = qh; + qh = qh->qh_next.qh; + WARN_ON(!list_empty(&qh_to_unlink->qtd_list)); + start_unlink_async(ehci, qh_to_unlink); + } +} + /* makes sure the async qh will become idle */ /* caller must own ehci->lock */ -- 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