[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20100330225639.999195448@linux.site>
Date: Tue, 30 Mar 2010 15:55:42 -0700
From: Greg KH <gregkh@...e.de>
To: linux-kernel@...r.kernel.org, stable@...nel.org
Cc: stable-review@...nel.org, torvalds@...ux-foundation.org,
akpm@...ux-foundation.org, alan@...rguk.ukuu.org.uk,
Clemens Ladisch <clemens@...isch.de>,
Greg Kroah-Hartman <gregkh@...e.de>
Subject: [064/116] USB: EHCI: fix ITD list order
2.6.32-stable review patch. If anyone has any objections, please let us know.
------------------
From: Clemens Ladisch <clemens@...isch.de>
commit 92bc3648e6027384479852b770a542722fadee7c upstream.
When isochronous URBs are shorter than one frame and when more than one
ITD in a frame has been completed before the interrupt can be handled,
scan_periodic() completes the URBs in the order in which they are found
in the descriptor list. Therefore, the descriptor list must contain the
ITDs in the correct order, i.e., a new ITD must be linked in after any
previous ITDs of the same endpoint.
This should fix garbled capture data in the USB audio drivers.
Signed-off-by: Clemens Ladisch <clemens@...isch.de>
Reported-by: Colin Fletcher <colin.m.fletcher@...glemail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@...e.de>
---
drivers/usb/host/ehci-sched.c | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1553,13 +1553,27 @@ itd_patch(
static inline void
itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
{
- /* always prepend ITD/SITD ... only QH tree is order-sensitive */
- itd->itd_next = ehci->pshadow [frame];
- itd->hw_next = ehci->periodic [frame];
- ehci->pshadow [frame].itd = itd;
+ union ehci_shadow *prev = &ehci->pshadow[frame];
+ __hc32 *hw_p = &ehci->periodic[frame];
+ union ehci_shadow here = *prev;
+ __hc32 type = 0;
+
+ /* skip any iso nodes which might belong to previous microframes */
+ while (here.ptr) {
+ type = Q_NEXT_TYPE(ehci, *hw_p);
+ if (type == cpu_to_hc32(ehci, Q_TYPE_QH))
+ break;
+ prev = periodic_next_shadow(ehci, prev, type);
+ hw_p = shadow_next_periodic(ehci, &here, type);
+ here = *prev;
+ }
+
+ itd->itd_next = here;
+ itd->hw_next = *hw_p;
+ prev->itd = itd;
itd->frame = frame;
wmb ();
- ehci->periodic[frame] = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
+ *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
}
/* fit urb's itds into the selected schedule slot; activate as needed */
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists