OK, here's a patch that I suspect will help a lot ... I ran a version
of it on 2.4.21-pre4 (plus ehci24-0201 and the usb-storage patch that
Tom Collins recently forwarded) and it sped up "hdparm -tT" on a VT8235
by a factor of four (!).  It worked on a VT6202 too (which I usually see
just on 2.5), but not as fast.

What the patch does is make the driver avoid a qh reactivation path that
seems to be slow and troublesome on those VIA controllers.  Easy to avoid:
use the timer, it already handles such delayed scans.  The cost is some
wasted memory accesses (DMA reads) from the controller, for up to 5msec
(HZ/200).

The patch is against 2.5.60 but should apply to that latest 2.4 code.

- Dave

--- ./drivers/usb-dist/host/ehci-q.c    Tue Feb 11 08:37:47 2003
+++ ./drivers/usb/host/ehci-q.c Sun Feb 16 15:49:55 2003
@@ -800,6 +800,7 @@
                                && !usb_pipecontrol (urb->pipe)) {
                        /* "never happens": drivers do stall cleanup right */
                        if (qh->qh_state != QH_STATE_IDLE
+                                       && !list_empty (&qh->qtd_list)
                                        && qh->qh_state != QH_STATE_COMPLETING)
                                ehci_warn (ehci, "clear toggle dev%d "
                                                "ep%d%s: not idle\n",
@@ -1014,6 +1015,7 @@
 scan_async (struct ehci_hcd *ehci, struct pt_regs *regs)
 {
        struct ehci_qh          *qh;
+       int                     unlink_delay = 0;
 
        if (!++(ehci->stamp))
                ehci->stamp++;
@@ -1040,17 +1042,25 @@
                                }
                        }
 
-                       /* unlink idle entries, reducing HC PCI usage as
-                        * well as HCD schedule-scanning costs.
-                        *
-                        * FIXME don't unlink idle entries so quickly; it
-                        * can penalize (common) half duplex protocols.
+                       /* unlink idle entries, reducing HC PCI usage as well
+                        * as HCD schedule-scanning costs.  delay for any qh
+                        * we just scanned, there's a not-unusual case that it
+                        * doesn't stay idle for long.
+                        * (plus, avoids some kind of re-activation race.)
                         */
-                       if (list_empty (&qh->qtd_list) && !ehci->reclaim) {
-                               start_unlink_async (ehci, qh);
+                       if (list_empty (&qh->qtd_list)) {
+                               if (qh->stamp == ehci->stamp)
+                                       unlink_delay = 1;
+                               else if (!ehci->reclaim) {
+                                       start_unlink_async (ehci, qh);
+                                       unlink_delay = 0;
+                               }
                        }
 
                        qh = qh->qh_next.qh;
                } while (qh);
        }
+
+       if (unlink_delay && !timer_pending (&ehci->watchdog))
+               mod_timer (&ehci->watchdog, jiffies + EHCI_WATCHDOG_JIFFIES/2);
 }

Reply via email to