Commit 9db33f31 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

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: default avatarAlan Stern <stern@rowland.harvard.edu>
CC: Sascha Hauer <kernel@pengutronix.de>
CC: Martin Fuzzey <mfuzzey@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 8a1ea51f
...@@ -809,26 +809,36 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd, ...@@ -809,26 +809,36 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
/* calculate frame */ /* calculate frame */
cur_frame = imx21_hc_get_frame(hcd); cur_frame = imx21_hc_get_frame(hcd);
if (urb->transfer_flags & URB_ISO_ASAP) { i = 0;
if (list_empty(&ep_priv->td_list)) if (list_empty(&ep_priv->td_list)) {
urb->start_frame = cur_frame + 5; urb->start_frame = wrap_frame(cur_frame + 5);
else } else {
urb->start_frame = list_entry( urb->start_frame = wrap_frame(list_entry(ep_priv->td_list.prev,
ep_priv->td_list.prev, struct td, list)->frame + urb->interval);
struct td, list)->frame + urb->interval;
} if (frame_after(cur_frame, urb->start_frame)) {
urb->start_frame = wrap_frame(urb->start_frame); dev_dbg(imx21->dev,
if (frame_after(cur_frame, urb->start_frame)) { "enqueue: adjusting iso start %d (cur=%d) asap=%d\n",
dev_dbg(imx21->dev, urb->start_frame, cur_frame,
"enqueue: adjusting iso start %d (cur=%d) asap=%d\n", (urb->transfer_flags & URB_ISO_ASAP) != 0);
urb->start_frame, cur_frame, i = DIV_ROUND_UP(wrap_frame(
(urb->transfer_flags & URB_ISO_ASAP) != 0); cur_frame - urb->start_frame),
urb->start_frame = wrap_frame(cur_frame + 1); urb->interval);
if (urb->transfer_flags & URB_ISO_ASAP) {
urb->start_frame = wrap_frame(urb->start_frame
+ i * urb->interval);
i = 0;
} else if (i >= urb->number_of_packets) {
ret = -EXDEV;
goto alloc_dmem_failed;
}
}
} }
/* set up transfers */ /* set up transfers */
urb_priv->isoc_remaining = urb->number_of_packets - i;
td = urb_priv->isoc_td; td = urb_priv->isoc_td;
for (i = 0; i < urb->number_of_packets; i++, td++) { for (; i < urb->number_of_packets; i++, td++) {
unsigned int offset = urb->iso_frame_desc[i].offset; unsigned int offset = urb->iso_frame_desc[i].offset;
td->ep = ep; td->ep = ep;
td->urb = urb; td->urb = urb;
...@@ -840,7 +850,6 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd, ...@@ -840,7 +850,6 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
list_add_tail(&td->list, &ep_priv->td_list); list_add_tail(&td->list, &ep_priv->td_list);
} }
urb_priv->isoc_remaining = urb->number_of_packets;
dev_vdbg(imx21->dev, "setup %d packets for iso frame %d->%d\n", dev_vdbg(imx21->dev, "setup %d packets for iso frame %d->%d\n",
urb->number_of_packets, urb->start_frame, td->frame); urb->number_of_packets, urb->start_frame, td->frame);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment