struct td *fhci_remove_td_from_ed(struct ed *ed)
{ struct td *td;
if (!list_empty(&ed->td_list)) {
td = list_entry(ed->td_list.next, struct td, node);
list_del_init(ed->td_list.next);
/* if this TD was the ED's head, find next TD */ if (!list_empty(&ed->td_list))
ed->td_head = list_entry(ed->td_list.next, struct td,
node); else
ed->td_head = NULL;
} else
td = NULL;
/* If this TD was the ED's head,find next TD */ if (!list_empty(&ed->td_list))
ed->td_head = list_entry(ed->td_list.next, struct td, node); else {
ed->td_head = NULL;
ed->state = FHCI_ED_SKIP;
}
ed->toggle_carry = td->toggle;
list_add_tail(&td->node, &usb->hc_list->done_list); if (td->ioc)
usb->transfer_confirm(usb->fhci);
}
/* free done FHCI URB resource such as ED and TD */ staticvoid free_urb_priv(struct fhci_hcd *fhci, struct urb *urb)
{ int i; struct urb_priv *urb_priv = urb->hcpriv; struct ed *ed = urb_priv->ed;
for (i = 0; i < urb_priv->num_of_tds; i++) {
list_del_init(&urb_priv->tds[i]->node);
fhci_recycle_empty_td(fhci, urb_priv->tds[i]);
}
/* if this TD was the ED's head,find the next TD */ if (!list_empty(&ed->td_list))
ed->td_head = list_entry(ed->td_list.next, struct td, node); else
ed->td_head = NULL;
/* * caculate transfer length/stats and update the urb * Precondition: irqsafe(only for urb-?status locking)
*/ void fhci_done_td(struct urb *urb, struct td *td)
{ struct ed *ed = td->ed;
u32 cc = td->status;
/* ISO...drivers see per-TD length/status */ if (ed->mode == FHCI_TF_ISO) {
u32 len; if (!(urb->transfer_flags & URB_SHORT_NOT_OK &&
cc == USB_TD_RX_DATA_UNDERUN))
cc = USB_TD_OK;
if (usb_pipeout(urb->pipe))
len = urb->iso_frame_desc[td->iso_index].length; else
len = td->actual_len;
/* BULK,INT,CONTROL... drivers see aggregate length/status, * except that "setup" bytes aren't counted and "short" transfers * might not be reported as errors.
*/ else { if (td->error_cnt >= 3)
urb->error_count = 3;
/* control endpoint only have soft stalls */
/* update packet status if needed(short may be ok) */ if (!(urb->transfer_flags & URB_SHORT_NOT_OK) &&
cc == USB_TD_RX_DATA_UNDERUN) {
ed->state = FHCI_ED_OPER;
cc = USB_TD_OK;
} if (cc != USB_TD_OK) { if (urb->status == -EINPROGRESS)
urb->status = status_to_error(cc);
}
/* count all non-empty packets except control SETUP packet */ if (td->type != FHCI_TA_SETUP || td->iso_index != 0)
urb->actual_length += td->actual_len;
}
}
/* there are some pedning request to unlink */ void fhci_del_ed_list(struct fhci_hcd *fhci, struct ed *ed)
{ struct td *td = peek_td_from_ed(ed); struct urb *urb = td->urb; struct urb_priv *urb_priv = urb->hcpriv;
if (urb_priv->state == URB_DEL) {
td = fhci_remove_td_from_ed(ed); /* HC may have partly processed this TD */ if (td->status != USB_TD_INPROGRESS)
fhci_done_td(urb, td);
/* URB is done;clean up */ if (++(urb_priv->tds_cnt) == urb_priv->num_of_tds)
fhci_urb_complete_free(fhci, urb);
}
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.