aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/imx21-hcd.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2013-05-29 13:20:00 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-05-30 08:34:30 -0400
commit9db33f317432d1a9e22116092c6455ae71bf73fc (patch)
tree955504b8b7659bf2a9c912d7add3b10da2e7e543 /drivers/usb/host/imx21-hcd.c
parent8a1ea51f87a6149c3263a63e9c60d852bedbecd7 (diff)
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>
Diffstat (limited to 'drivers/usb/host/imx21-hcd.c')
-rw-r--r--drivers/usb/host/imx21-hcd.c43
1 files changed, 26 insertions, 17 deletions
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
index f0ebe8e7c58b..03dc4d9cbeca 100644
--- a/drivers/usb/host/imx21-hcd.c
+++ b/drivers/usb/host/imx21-hcd.c
@@ -809,26 +809,36 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
809 809
810 /* calculate frame */ 810 /* calculate frame */
811 cur_frame = imx21_hc_get_frame(hcd); 811 cur_frame = imx21_hc_get_frame(hcd);
812 if (urb->transfer_flags & URB_ISO_ASAP) { 812 i = 0;
813 if (list_empty(&ep_priv->td_list)) 813 if (list_empty(&ep_priv->td_list)) {
814 urb->start_frame = cur_frame + 5; 814 urb->start_frame = wrap_frame(cur_frame + 5);
815 else 815 } else {
816 urb->start_frame = list_entry( 816 urb->start_frame = wrap_frame(list_entry(ep_priv->td_list.prev,
817 ep_priv->td_list.prev, 817 struct td, list)->frame + urb->interval);
818 struct td, list)->frame + urb->interval; 818
819 } 819 if (frame_after(cur_frame, urb->start_frame)) {
820 urb->start_frame = wrap_frame(urb->start_frame); 820 dev_dbg(imx21->dev,
821 if (frame_after(cur_frame, urb->start_frame)) { 821 "enqueue: adjusting iso start %d (cur=%d) asap=%d\n",
822 dev_dbg(imx21->dev, 822 urb->start_frame, cur_frame,
823 "enqueue: adjusting iso start %d (cur=%d) asap=%d\n", 823 (urb->transfer_flags & URB_ISO_ASAP) != 0);
824 urb->start_frame, cur_frame, 824 i = DIV_ROUND_UP(wrap_frame(
825 (urb->transfer_flags & URB_ISO_ASAP) != 0); 825 cur_frame - urb->start_frame),
826 urb->start_frame = wrap_frame(cur_frame + 1); 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 /* set up transfers */ 838 /* set up transfers */
839 urb_priv->isoc_remaining = urb->number_of_packets - i;
830 td = urb_priv->isoc_td; 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 unsigned int offset = urb->iso_frame_desc[i].offset; 842 unsigned int offset = urb->iso_frame_desc[i].offset;
833 td->ep = ep; 843 td->ep = ep;
834 td->urb = urb; 844 td->urb = urb;
@@ -840,7 +850,6 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
840 list_add_tail(&td->list, &ep_priv->td_list); 850 list_add_tail(&td->list, &ep_priv->td_list);
841 } 851 }
842 852
843 urb_priv->isoc_remaining = urb->number_of_packets;
844 dev_vdbg(imx21->dev, "setup %d packets for iso frame %d->%d\n", 853 dev_vdbg(imx21->dev, "setup %d packets for iso frame %d->%d\n",
845 urb->number_of_packets, urb->start_frame, td->frame); 854 urb->number_of_packets, urb->start_frame, td->frame);
846 855