mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-04-14 10:16:04 +00:00
UHCI: implement new semantics for URB_ISO_ASAP
This patch (as1613) updates the isochronous scheduling in uhci-hcd to match the new semantics for URB_ISO_ASAP. The amount of code alteration is smaller than it looks because of a change in the indentation level. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
4005ad4390
commit
c44b225077
1 changed files with 34 additions and 35 deletions
|
@ -1256,7 +1256,8 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
|
||||||
struct uhci_qh *qh)
|
struct uhci_qh *qh)
|
||||||
{
|
{
|
||||||
struct uhci_td *td = NULL; /* Since urb->number_of_packets > 0 */
|
struct uhci_td *td = NULL; /* Since urb->number_of_packets > 0 */
|
||||||
int i, frame;
|
int i;
|
||||||
|
unsigned frame, next;
|
||||||
unsigned long destination, status;
|
unsigned long destination, status;
|
||||||
struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
|
struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
|
||||||
|
|
||||||
|
@ -1265,37 +1266,29 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
|
||||||
urb->number_of_packets >= UHCI_NUMFRAMES)
|
urb->number_of_packets >= UHCI_NUMFRAMES)
|
||||||
return -EFBIG;
|
return -EFBIG;
|
||||||
|
|
||||||
|
uhci_get_current_frame_number(uhci);
|
||||||
|
|
||||||
/* Check the period and figure out the starting frame number */
|
/* Check the period and figure out the starting frame number */
|
||||||
if (!qh->bandwidth_reserved) {
|
if (!qh->bandwidth_reserved) {
|
||||||
qh->period = urb->interval;
|
qh->period = urb->interval;
|
||||||
if (urb->transfer_flags & URB_ISO_ASAP) {
|
qh->phase = -1; /* Find the best phase */
|
||||||
qh->phase = -1; /* Find the best phase */
|
i = uhci_check_bandwidth(uhci, qh);
|
||||||
i = uhci_check_bandwidth(uhci, qh);
|
if (i)
|
||||||
if (i)
|
return i;
|
||||||
return i;
|
|
||||||
|
|
||||||
/* Allow a little time to allocate the TDs */
|
/* Allow a little time to allocate the TDs */
|
||||||
uhci_get_current_frame_number(uhci);
|
next = uhci->frame_number + 10;
|
||||||
frame = uhci->frame_number + 10;
|
frame = qh->phase;
|
||||||
|
|
||||||
/* Move forward to the first frame having the
|
/* Round up to the first available slot */
|
||||||
* correct phase */
|
frame += (next - frame + qh->period - 1) & -qh->period;
|
||||||
urb->start_frame = frame + ((qh->phase - frame) &
|
|
||||||
(qh->period - 1));
|
|
||||||
} else {
|
|
||||||
i = urb->start_frame - uhci->last_iso_frame;
|
|
||||||
if (i <= 0 || i >= UHCI_NUMFRAMES)
|
|
||||||
return -EINVAL;
|
|
||||||
qh->phase = urb->start_frame & (qh->period - 1);
|
|
||||||
i = uhci_check_bandwidth(uhci, qh);
|
|
||||||
if (i)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (qh->period != urb->interval) {
|
} else if (qh->period != urb->interval) {
|
||||||
return -EINVAL; /* Can't change the period */
|
return -EINVAL; /* Can't change the period */
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
next = uhci->frame_number + 2;
|
||||||
|
|
||||||
/* Find the next unused frame */
|
/* Find the next unused frame */
|
||||||
if (list_empty(&qh->queue)) {
|
if (list_empty(&qh->queue)) {
|
||||||
frame = qh->iso_frame;
|
frame = qh->iso_frame;
|
||||||
|
@ -1308,25 +1301,31 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
|
||||||
lurb->number_of_packets *
|
lurb->number_of_packets *
|
||||||
lurb->interval;
|
lurb->interval;
|
||||||
}
|
}
|
||||||
if (urb->transfer_flags & URB_ISO_ASAP) {
|
|
||||||
/* Skip some frames if necessary to insure
|
/* Fell behind? */
|
||||||
* the start frame is in the future.
|
if (uhci_frame_before_eq(frame, next)) {
|
||||||
|
|
||||||
|
/* USB_ISO_ASAP: Round up to the first available slot */
|
||||||
|
if (urb->transfer_flags & URB_ISO_ASAP)
|
||||||
|
frame += (next - frame + qh->period - 1) &
|
||||||
|
-qh->period;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Not ASAP: Use the next slot in the stream. If
|
||||||
|
* the entire URB falls before the threshold, fail.
|
||||||
*/
|
*/
|
||||||
uhci_get_current_frame_number(uhci);
|
else if (!uhci_frame_before_eq(next,
|
||||||
if (uhci_frame_before_eq(frame, uhci->frame_number)) {
|
frame + (urb->number_of_packets - 1) *
|
||||||
frame = uhci->frame_number + 1;
|
qh->period))
|
||||||
frame += ((qh->phase - frame) &
|
return -EXDEV;
|
||||||
(qh->period - 1));
|
}
|
||||||
}
|
|
||||||
} /* Otherwise pick up where the last URB leaves off */
|
|
||||||
urb->start_frame = frame;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure we won't have to go too far into the future */
|
/* Make sure we won't have to go too far into the future */
|
||||||
if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES,
|
if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES,
|
||||||
urb->start_frame + urb->number_of_packets *
|
frame + urb->number_of_packets * urb->interval))
|
||||||
urb->interval))
|
|
||||||
return -EFBIG;
|
return -EFBIG;
|
||||||
|
urb->start_frame = frame;
|
||||||
|
|
||||||
status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
|
status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
|
||||||
destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
|
destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
|
||||||
|
|
Loading…
Add table
Reference in a new issue