Am Montag, 7. Januar 2008 schrieb David Brownell:
> This has some bugfixes for the EHCI driver's ISO transfer scanning
> logic.  It was leaving ITDs and SITDs on the schedule too long, for
> a few different reasons, which caused trouble.
> 
>   (a) Look at all microframes for high speed transfers, not just
>       the ones we expect to have finished.  This way transfers
>       ending mid-frame will complete without needing another IRQ.
>       This also minimizes bogus scheduling underruns (e.g. EL2NSYNC).
> 
>   (b) When we encounter an ISO transfer (either speed, but this
>       hits mostly at full speed) that's not yet been completed,
>       immediately stop scanning; we've caught up to the hardware,
>       no matter what other indications might say.
> 
>   (c) Always clean up ITDs (for high speed transfers) when the HC
>       is no longer running.
>       
> I'm not sure whether the last one has been observed before, but both
> the others have been reported with "real world" audio and video code.
> 
> Signed-off-by: David Brownell <[EMAIL PROTECTED]>
> ---
> Updated version ... primarily adding (b) to address another bug
> in this same area.  Against RC7.

This + not yet fully cooked patch at bottom on-top RC7 let snd-usb-us122l
work :-)
Still to fix: There are itds leaking, the printk() below executes every
now and then. Likely caused by patch below.

      Karsten


--- drivers/usb/host/ehci-sched.c.dave  2008-01-09 16:05:31.000000000 +0100
+++ drivers/usb/host/ehci-sched.c       2008-01-09 16:05:50.000000000 +0100
@@ -1180,12 +1180,17 @@
                if (likely (!list_empty(&stream->free_list))) {
                        itd = list_entry (stream->free_list.prev,
                                        struct ehci_itd, itd_list);
-                       list_del (&itd->itd_list);
-                       itd_dma = itd->itd_dma;
+                       if (itd->frame == ehci->clock >> 3) {
+                               itd = NULL;
+                       } else {
+                               list_del (&itd->itd_list);
+                               itd_dma = itd->itd_dma;
+                       }
                } else
                        itd = NULL;
 
                if (!itd) {
+                       printk(KERN_DEBUG"%s:%i\n", __FUNCTION__, __LINE__);
                        spin_unlock_irqrestore (&ehci->lock, flags);
                        itd = dma_pool_alloc (ehci->itd_pool, mem_flags,
                                        &itd_dma);
@@ -2107,7 +2112,7 @@
 static void
 scan_periodic (struct ehci_hcd *ehci)
 {
-       unsigned        frame, clock, now_uframe, mod;
+       unsigned        frame, now_uframe, mod;
        unsigned        modified;
 
        mod = ehci->periodic_size << 3;
@@ -2119,10 +2124,10 @@
         */
        now_uframe = ehci->next_uframe;
        if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
-               clock = ehci_readl(ehci, &ehci->regs->frame_index);
+               ehci->clock = ehci_readl(ehci, &ehci->regs->frame_index);
        else
-               clock = now_uframe + mod - 1;
-       clock %= mod;
+               ehci->clock = now_uframe + mod - 1;
+       ehci->clock %= mod;
 
        for (;;) {
                union ehci_shadow       q, *q_p;
@@ -2253,7 +2258,7 @@
 
                // FIXME:  likewise assumes HC doesn't halt mid-scan
 
-               if (now_uframe == clock) {
+               if (now_uframe == ehci->clock) {
                        unsigned        now;
 
                        if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
@@ -2264,7 +2269,7 @@
                                break;
 
                        /* rescan the rest of this frame, then ... */
-                       clock = now;
+                       ehci->clock = now;
                } else {
                        now_uframe++;
                        now_uframe %= mod;
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -86,6 +86,7 @@ struct ehci_hcd {                     /* one per controller */

        union ehci_shadow       *pshadow;       /* mirror hw periodic table */
        int                     next_uframe;    /* scan periodic, start here */
+       unsigned                clock;
        unsigned                periodic_sched; /* periodic activity count */

        /* per root hub port */


-
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

Reply via email to