frame->actual_length = frame->length;
td->urb->actual_length += frame->length;
} else {
+ if (urb_priv->finishing_short_td &&
+ (event_trb == td->last_trb)) {
+ urb_priv->finishing_short_td = false;
+ /* get event for last trb, can finish this short td */
+ goto finish_td;
+ }
for (cur_trb = ep_ring->dequeue,
cur_seg = ep_ring->deq_seg; cur_trb != event_trb;
next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
frame->actual_length = len;
td->urb->actual_length += len;
}
+ if ((trb_comp_code == COMP_SHORT_TX) &&
+ (event_trb != td->last_trb)) {
+ /* last trb has IOC, expect HC to send event for it */
+ while (ep_ring->dequeue != td->last_trb)
+ inc_deq(xhci, ep_ring);
+ urb_priv->finishing_short_td = true;
+ return 0;
+ }
}
+finish_td:
return finish_td(xhci, td, event_trb, event, ep, status, false);
}