mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-05 10:29:37 +00:00
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>
This commit is contained in:
parent
8a1ea51f87
commit
9db33f3174
1 changed files with 26 additions and 17 deletions
|
@ -809,26 +809,36 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
|
|||
|
||||
/* calculate frame */
|
||||
cur_frame = imx21_hc_get_frame(hcd);
|
||||
if (urb->transfer_flags & URB_ISO_ASAP) {
|
||||
if (list_empty(&ep_priv->td_list))
|
||||
urb->start_frame = cur_frame + 5;
|
||||
else
|
||||
urb->start_frame = list_entry(
|
||||
ep_priv->td_list.prev,
|
||||
struct td, list)->frame + urb->interval;
|
||||
}
|
||||
urb->start_frame = wrap_frame(urb->start_frame);
|
||||
if (frame_after(cur_frame, urb->start_frame)) {
|
||||
dev_dbg(imx21->dev,
|
||||
"enqueue: adjusting iso start %d (cur=%d) asap=%d\n",
|
||||
urb->start_frame, cur_frame,
|
||||
(urb->transfer_flags & URB_ISO_ASAP) != 0);
|
||||
urb->start_frame = wrap_frame(cur_frame + 1);
|
||||
i = 0;
|
||||
if (list_empty(&ep_priv->td_list)) {
|
||||
urb->start_frame = wrap_frame(cur_frame + 5);
|
||||
} else {
|
||||
urb->start_frame = wrap_frame(list_entry(ep_priv->td_list.prev,
|
||||
struct td, list)->frame + urb->interval);
|
||||
|
||||
if (frame_after(cur_frame, urb->start_frame)) {
|
||||
dev_dbg(imx21->dev,
|
||||
"enqueue: adjusting iso start %d (cur=%d) asap=%d\n",
|
||||
urb->start_frame, cur_frame,
|
||||
(urb->transfer_flags & URB_ISO_ASAP) != 0);
|
||||
i = DIV_ROUND_UP(wrap_frame(
|
||||
cur_frame - urb->start_frame),
|
||||
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 */
|
||||
urb_priv->isoc_remaining = urb->number_of_packets - i;
|
||||
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;
|
||||
td->ep = ep;
|
||||
td->urb = urb;
|
||||
|
@ -840,7 +850,6 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
|
|||
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",
|
||||
urb->number_of_packets, urb->start_frame, td->frame);
|
||||
|
||||
|
|
Loading…
Reference in a new issue