forked from luck/tmp_suning_uos_patched
USB: EHCI: fix ITD list order
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@ladisch.de> Reported-by: Colin Fletcher <colin.m.fletcher@googlemail.com> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
bf162019b7
commit
92bc3648e6
|
@ -1565,13 +1565,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 */
|
||||
|
|
Loading…
Reference in New Issue
Block a user