|
@@ -1813,72 +1813,65 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|
|
if (skip)
|
|
|
goto td_cleanup;
|
|
|
|
|
|
- if (trb_comp_code == COMP_STOP_INVAL ||
|
|
|
- trb_comp_code == COMP_STOP) {
|
|
|
+ if (trb_comp_code == COMP_STOP_INVAL || trb_comp_code == COMP_STOP) {
|
|
|
/* The Endpoint Stop Command completion will take care of any
|
|
|
* stopped TDs. A stopped TD may be restarted, so don't update
|
|
|
* the ring dequeue pointer or take this TD off any lists yet.
|
|
|
*/
|
|
|
ep->stopped_td = td;
|
|
|
return 0;
|
|
|
+ }
|
|
|
+ if (trb_comp_code == COMP_STALL ||
|
|
|
+ xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
|
|
|
+ trb_comp_code)) {
|
|
|
+ /* Issue a reset endpoint command to clear the host side
|
|
|
+ * halt, followed by a set dequeue command to move the
|
|
|
+ * dequeue pointer past the TD.
|
|
|
+ * The class driver clears the device side halt later.
|
|
|
+ */
|
|
|
+ xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index,
|
|
|
+ ep_ring->stream_id, td, event_trb);
|
|
|
} else {
|
|
|
- if (trb_comp_code == COMP_STALL ||
|
|
|
- xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
|
|
|
- trb_comp_code)) {
|
|
|
- /* Issue a reset endpoint command to clear the host side
|
|
|
- * halt, followed by a set dequeue command to move the
|
|
|
- * dequeue pointer past the TD.
|
|
|
- * The class driver clears the device side halt later.
|
|
|
- */
|
|
|
- xhci_cleanup_halted_endpoint(xhci,
|
|
|
- slot_id, ep_index, ep_ring->stream_id,
|
|
|
- td, event_trb);
|
|
|
- } else {
|
|
|
- /* Update ring dequeue pointer */
|
|
|
- while (ep_ring->dequeue != td->last_trb)
|
|
|
- inc_deq(xhci, ep_ring);
|
|
|
+ /* Update ring dequeue pointer */
|
|
|
+ while (ep_ring->dequeue != td->last_trb)
|
|
|
inc_deq(xhci, ep_ring);
|
|
|
- }
|
|
|
+ inc_deq(xhci, ep_ring);
|
|
|
+ }
|
|
|
|
|
|
td_cleanup:
|
|
|
- /* Clean up the endpoint's TD list */
|
|
|
- urb = td->urb;
|
|
|
- urb_priv = urb->hcpriv;
|
|
|
-
|
|
|
- /* Do one last check of the actual transfer length.
|
|
|
- * If the host controller said we transferred more data than
|
|
|
- * the buffer length, urb->actual_length will be a very big
|
|
|
- * number (since it's unsigned). Play it safe and say we didn't
|
|
|
- * transfer anything.
|
|
|
- */
|
|
|
- if (urb->actual_length > urb->transfer_buffer_length) {
|
|
|
- xhci_warn(xhci, "URB transfer length is wrong, "
|
|
|
- "xHC issue? req. len = %u, "
|
|
|
- "act. len = %u\n",
|
|
|
- urb->transfer_buffer_length,
|
|
|
- urb->actual_length);
|
|
|
- urb->actual_length = 0;
|
|
|
- if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
|
|
|
- *status = -EREMOTEIO;
|
|
|
- else
|
|
|
- *status = 0;
|
|
|
- }
|
|
|
- list_del_init(&td->td_list);
|
|
|
- /* Was this TD slated to be cancelled but completed anyway? */
|
|
|
- if (!list_empty(&td->cancelled_td_list))
|
|
|
- list_del_init(&td->cancelled_td_list);
|
|
|
-
|
|
|
- urb_priv->td_cnt++;
|
|
|
- /* Giveback the urb when all the tds are completed */
|
|
|
- if (urb_priv->td_cnt == urb_priv->length) {
|
|
|
- ret = 1;
|
|
|
- if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
|
|
|
- xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs--;
|
|
|
- if (xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs
|
|
|
- == 0) {
|
|
|
- if (xhci->quirks & XHCI_AMD_PLL_FIX)
|
|
|
- usb_amd_quirk_pll_enable();
|
|
|
- }
|
|
|
+ /* Clean up the endpoint's TD list */
|
|
|
+ urb = td->urb;
|
|
|
+ urb_priv = urb->hcpriv;
|
|
|
+
|
|
|
+ /* Do one last check of the actual transfer length.
|
|
|
+ * If the host controller said we transferred more data than the buffer
|
|
|
+ * length, urb->actual_length will be a very big number (since it's
|
|
|
+ * unsigned). Play it safe and say we didn't transfer anything.
|
|
|
+ */
|
|
|
+ if (urb->actual_length > urb->transfer_buffer_length) {
|
|
|
+ xhci_warn(xhci, "URB transfer length is wrong, xHC issue? req. len = %u, act. len = %u\n",
|
|
|
+ urb->transfer_buffer_length,
|
|
|
+ urb->actual_length);
|
|
|
+ urb->actual_length = 0;
|
|
|
+ if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
|
|
|
+ *status = -EREMOTEIO;
|
|
|
+ else
|
|
|
+ *status = 0;
|
|
|
+ }
|
|
|
+ list_del_init(&td->td_list);
|
|
|
+ /* Was this TD slated to be cancelled but completed anyway? */
|
|
|
+ if (!list_empty(&td->cancelled_td_list))
|
|
|
+ list_del_init(&td->cancelled_td_list);
|
|
|
+
|
|
|
+ urb_priv->td_cnt++;
|
|
|
+ /* Giveback the urb when all the tds are completed */
|
|
|
+ if (urb_priv->td_cnt == urb_priv->length) {
|
|
|
+ ret = 1;
|
|
|
+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
|
|
|
+ xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs--;
|
|
|
+ if (xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs == 0) {
|
|
|
+ if (xhci->quirks & XHCI_AMD_PLL_FIX)
|
|
|
+ usb_amd_quirk_pll_enable();
|
|
|
}
|
|
|
}
|
|
|
}
|