On Wed, 28 Aug 2013 12:02:03 +0800
Ming Lei <[email protected]> wrote:
 
> Actually the problem only happened when underrun without
> URB_ISO_ASAP.
> 
> I have another fix which uses rebase trick and is simper(less change), could
> you comment on the attachment patch?

Sorry, please ignore last attachment patch, and comment on the below one:

diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 83be03f..4a3ddc9 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1370,6 +1370,21 @@ sitd_slot_ok (
        return 1;
 }
 
+/* rebase in case of underun without ISO_ASAP together */
+static void iso_stream_rebase(struct ehci_hcd *ehci,
+       struct ehci_iso_stream  *stream, u32 mod)
+{
+       u32 i;
+
+       if (ehci->last_base == -1)
+               return;
+
+       for (i = ehci->last_base; i != ehci->last_iso_frame;
+                       i = (i + 1) & (mod - 1))
+               if ((stream->next_uframe & (mod - 1)) == i)
+                       ehci->last_iso_frame = i;
+}
+
 /*
  * This scheduler plans almost as far into the future as it has actual
  * periodic schedule slots.  (Affected by TUNE_FLS, which defaults to
@@ -1409,7 +1424,9 @@ iso_stream_schedule (
         * (irq delays etc).  If there are, the behavior depends on
         * whether URB_ISO_ASAP is set.
         */
-       if (likely (!list_empty (&stream->td_list))) {
+       if (likely (!list_empty (&stream->td_list) ||
+                               hcd_complete_in_progress(
+                               ehci_to_hcd(ehci), urb))) {
 
                /* Take the isochronous scheduling threshold into account */
                if (ehci->i_thresh)
@@ -1417,6 +1434,10 @@ iso_stream_schedule (
                else
                        next = (now + 2 + 7) & ~0x07;   /* full frame cache */
 
+               if (list_empty(&stream->td_list) &&
+                               !(urb->transfer_flags & URB_ISO_ASAP))
+                       iso_stream_rebase(ehci, stream, mod);
+
                /*
                 * Use ehci->last_iso_frame as the base.  There can't be any
                 * TDs scheduled for earlier than that.
@@ -1517,6 +1538,7 @@ iso_stream_schedule (
        /* Make sure scan_isoc() sees these */
        if (ehci->isoc_count == 0)
                ehci->last_iso_frame = now >> 3;
+       ehci->last_base = -1;
        return 0;
 
  fail:
@@ -2255,6 +2277,9 @@ static void scan_isoc(struct ehci_hcd *ehci)
        }
        ehci->now_frame = now_frame;
 
+       if (ehci->last_base == -1)
+               ehci->last_base = ehci->last_iso_frame;
+
        frame = ehci->last_iso_frame;
        for (;;) {
                union ehci_shadow       q, *q_p;


Thanks,
-- 
Ming Lei
--
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