On 18 April 2011 20:51, Matej Kenda <matejken@xxxxxxxxx> wrote: > On 18 April 2011 17:28, Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote: >>> >>> A bug report 701011 in Launchpad contains additional description of >>> the problem and kernel logs with traces created with >>> options: >>> >>> CONFIG_USB_STORAGE_DEBUG=y >>> CONFIG_USB=y >>> CONFIG_USB_DEBUG=y >>> >>> https://bugs.launchpad.net/linux/+bug/701011 >>> https://launchpadlibrarian.net/62011653/hudson-slave-last-part.log >> >> Here's a patch for you to test. ÂIt isn't exactly a reversion of the >> "USB: ehci-hcd unlink speedups" commit. > > Thank you. I'll try the patch. It took me some time to set up the test environment with patched kernel. There was some other work that I needed to complete. I had to upgrade my LKM for custom piece of hardware to be able to run the test. I applied the patch to Linux kernel from Ubuntu Natty (2.6.38-10). I needed to modify the patch slightly. I will report how it works in a week or so. Regards, Matej
diff --git a/debian.master/changelog b/debian.master/changelog index 7936595..9d4cb21 100644 --- a/debian.master/changelog +++ b/debian.master/changelog @@ -1,3 +1,10 @@ +linux (2.6.38-10.99) natty; urgency=low + + * USB disconnect: Test patch from Alan Stern + - LP: #701011 + + -- Matej Kenda <matej.kenda@xxxxxxxxx> Tue, 19 Apr 2011 13:16:59 +0200 + linux (2.6.38-9.43) natty-proposed; urgency=low [ Brad Figg ] diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 74dcf49..bbce753 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -90,7 +90,7 @@ static const char hcd_name [] = "ehci_hcd"; #define EHCI_IAA_MSECS 10 /* arbitrary */ #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ -#define EHCI_SHRINK_FRAMES 5 /* async qh unlink delay */ +#define EHCI_SHRINK_JIFFIES (HZ/200 + 2) /* async qh unlink delay */ /* Initial IRQ latency: faster than hw default */ static int log2_irq_thresh = 0; // 0 to 6 @@ -150,10 +150,7 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action) break; /* case TIMER_ASYNC_SHRINK: */ default: - /* add a jiffie since we synch against the - * 8 KHz uframe counter. - */ - t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1; + t = EHCI_SHRINK_JIFFIES; break; } mod_timer(&ehci->watchdog, t + jiffies); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index baf7362..35e8957 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1249,7 +1249,8 @@ static void scan_async (struct ehci_hcd *ehci) struct ehci_qh *qh; enum ehci_timer_action action = TIMER_IO_WATCHDOG; - ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index); + ehci->stamp++; + ehci->stamp += !ehci->stamp; timer_action_done (ehci, TIMER_ASYNC_SHRINK); rescan: stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state); @@ -1272,6 +1273,7 @@ rescan: temp = qh_completions (ehci, qh); if (qh->needs_rescan) unlink_async(ehci, qh); + qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES; qh_put (qh); if (temp != 0) { goto rescan; @@ -1286,9 +1288,8 @@ rescan: */ if (list_empty(&qh->qtd_list) && qh->qh_state == QH_STATE_LINKED) { - if (!ehci->reclaim && (stopped || - ((ehci->stamp - qh->stamp) & 0x1fff) - >= EHCI_SHRINK_FRAMES * 8)) + if (!ehci->reclaim && (stopped || + time_after_eq(jiffies, qh->unlink_time))) start_unlink_async(ehci, qh); else action = TIMER_ASYNC_SHRINK; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 799ac16..8fd4cc9 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -336,6 +336,8 @@ struct ehci_qh { struct ehci_qh *reclaim; /* next to reclaim */ struct ehci_hcd *ehci; + unsigned long unlink_time; + unsigned stamp; /* * Do NOT use atomic operations for QH refcounting. On some CPUs @@ -344,7 +346,6 @@ struct ehci_qh { * Spinlocks are used to protect all QH fields. */ u32 refcount; - unsigned stamp; u8 needs_rescan; /* Dequeue during giveback */ u8 qh_state;