Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: IMX21: upgrade the isochronous API

This patch attempts to update the imx21-hcd driver to the current
standard for the isochronous API. Firstly, urb->start_frame should
always be set by the driver; it is not an input parameter. Secondly,
the URB_ISO_ASAP flag matters only when an URB is submitted to a
stream that has gotten an underrun. It causes the URB to be scheduled
for the next available slot in the future, rather than the earliest
unused (and expired) slot.

Unfortunately, I don't have any way to test these changes.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
CC: Sascha Hauer <kernel@pengutronix.de>
CC: Martin Fuzzey <mfuzzey@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Alan Stern and committed by
Greg Kroah-Hartman
9db33f31 8a1ea51f

+26 -17
+26 -17
drivers/usb/host/imx21-hcd.c
··· 809 809 810 810 /* calculate frame */ 811 811 cur_frame = imx21_hc_get_frame(hcd); 812 - if (urb->transfer_flags & URB_ISO_ASAP) { 813 - if (list_empty(&ep_priv->td_list)) 814 - urb->start_frame = cur_frame + 5; 815 - else 816 - urb->start_frame = list_entry( 817 - ep_priv->td_list.prev, 818 - struct td, list)->frame + urb->interval; 819 - } 820 - urb->start_frame = wrap_frame(urb->start_frame); 821 - if (frame_after(cur_frame, urb->start_frame)) { 822 - dev_dbg(imx21->dev, 823 - "enqueue: adjusting iso start %d (cur=%d) asap=%d\n", 824 - urb->start_frame, cur_frame, 825 - (urb->transfer_flags & URB_ISO_ASAP) != 0); 826 - urb->start_frame = wrap_frame(cur_frame + 1); 812 + i = 0; 813 + if (list_empty(&ep_priv->td_list)) { 814 + urb->start_frame = wrap_frame(cur_frame + 5); 815 + } else { 816 + urb->start_frame = wrap_frame(list_entry(ep_priv->td_list.prev, 817 + struct td, list)->frame + urb->interval); 818 + 819 + if (frame_after(cur_frame, urb->start_frame)) { 820 + dev_dbg(imx21->dev, 821 + "enqueue: adjusting iso start %d (cur=%d) asap=%d\n", 822 + urb->start_frame, cur_frame, 823 + (urb->transfer_flags & URB_ISO_ASAP) != 0); 824 + i = DIV_ROUND_UP(wrap_frame( 825 + cur_frame - urb->start_frame), 826 + urb->interval); 827 + if (urb->transfer_flags & URB_ISO_ASAP) { 828 + urb->start_frame = wrap_frame(urb->start_frame 829 + + i * urb->interval); 830 + i = 0; 831 + } else if (i >= urb->number_of_packets) { 832 + ret = -EXDEV; 833 + goto alloc_dmem_failed; 834 + } 835 + } 827 836 } 828 837 829 838 /* set up transfers */ 839 + urb_priv->isoc_remaining = urb->number_of_packets - i; 830 840 td = urb_priv->isoc_td; 831 - for (i = 0; i < urb->number_of_packets; i++, td++) { 841 + for (; i < urb->number_of_packets; i++, td++) { 832 842 unsigned int offset = urb->iso_frame_desc[i].offset; 833 843 td->ep = ep; 834 844 td->urb = urb; ··· 850 840 list_add_tail(&td->list, &ep_priv->td_list); 851 841 } 852 842 853 - urb_priv->isoc_remaining = urb->number_of_packets; 854 843 dev_vdbg(imx21->dev, "setup %d packets for iso frame %d->%d\n", 855 844 urb->number_of_packets, urb->start_frame, td->frame); 856 845