USB: EHCI: stagger frames for interrupt transfers
authorAlan Stern <stern@rowland.harvard.edu>
Fri, 22 May 2009 21:02:33 +0000 (17:02 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 16 Jun 2009 04:44:46 +0000 (21:44 -0700)
This patch (as1243) tries to improve ehci-hcd's scheduling of
interrupt transfers.  Instead of trying to cram all transfers with the
same period into the same frame, the new code will spread the
transfers out among lots of different frames.  This should reduce the
periodic schedule load in any one frame -- some host controllers have
trouble when there's too much work to do.

A more thorough approach would stagger the uframe values as well.  But
this is enough to make a big improvement.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Tested-by: Dwayne Fontenot <dwayne.fontenot@att.net>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci.h

index 556d0ec0c1f81048044a7b6e51019a5a1d4443e5..9d1babc7ff6553c64de8cec32fcfcff3f5ce5967 100644 (file)
@@ -760,8 +760,10 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
        if (status) {
                /* "normal" case, uframing flexible except with splits */
                if (qh->period) {
-                       frame = qh->period - 1;
-                       do {
+                       int             i;
+
+                       for (i = qh->period; status && i > 0; --i) {
+                               frame = ++ehci->random_frame % qh->period;
                                for (uframe = 0; uframe < 8; uframe++) {
                                        status = check_intr_schedule (ehci,
                                                        frame, uframe, qh,
@@ -769,7 +771,7 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
                                        if (status == 0)
                                                break;
                                }
-                       } while (status && frame--);
+                       }
 
                /* qh->period == 0 means every uframe */
                } else {
index 6cff195e1a365e46d739bc42263b57381365bb3b..90ad3395bb21f0f96923ab21431dc7c44165badb 100644 (file)
@@ -116,6 +116,7 @@ struct ehci_hcd {                   /* one per controller */
        struct timer_list       watchdog;
        unsigned long           actions;
        unsigned                stamp;
+       unsigned                random_frame;
        unsigned long           next_statechange;
        u32                     command;