[PATCH 2/4] usb: xhci: handle Set TR Deq Slot Not Enabled Error

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The Set TR Deq Slot Not Enabled error occurs when the Endpoint State is
disabled. In this state, the slot's Doorbell register is disabled, meaning
it cannot receive or handle Transfer Descriptors (TDs).

Because the slot cannot receive or handle TDs, it should not have any TDs.
Consequently, all cancelled TDs are released.
(The goto 'td_cleanup' is used for other cases in later patches)

Case 'COMP_SLOT_NOT_ENABLED_ERROR' (11) is moved between 'COMP_TRB_ERROR'
(5) and 'COMP_CONTEXT_STATE_ERROR' (19).

xHCI specification, rev 1.2:
 Slot State		section 4.5.3

Signed-off-by: Niklas Neronin <niklas.neronin@xxxxxxxxxxxxxxx>
---
 drivers/usb/host/xhci-ring.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 7bd559294742..79c15dbae43b 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1461,6 +1461,9 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
 			xhci_warn(xhci, "Set TR Deq error stream %u boundary check failed TRB @%pad slot %d ep %u\n",
 				  stream_id, &deq, slot_id, ep_index);
 			break;
+		case COMP_SLOT_NOT_ENABLED_ERROR:
+			xhci_warn(xhci, "Set TR Deq error slot %d is Disabled\n", slot_id);
+			goto td_cleanup;
 		case COMP_CONTEXT_STATE_ERROR:
 			xhci_warn(xhci, "WARN Set TR Deq Ptr cmd failed due to incorrect slot or ep state.\n");
 			ep_state = GET_EP_CTX_STATE(ep_ctx);
@@ -1470,10 +1473,6 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
 					"Slot state = %u, EP state = %u",
 					slot_state, ep_state);
 			break;
-		case COMP_SLOT_NOT_ENABLED_ERROR:
-			xhci_warn(xhci, "WARN Set TR Deq Ptr cmd failed because slot %u was not enabled.\n",
-					slot_id);
-			break;
 		default:
 			xhci_warn(xhci, "WARN Set TR Deq Ptr cmd with unknown completion code of %u.\n",
 					cmd_comp_code);
@@ -1554,6 +1553,17 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
 		xhci_dbg(ep->xhci, "%s: All TDs cleared, ring doorbell\n", __func__);
 		ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
 	}
+	return;
+td_cleanup:
+	ep->ep_state &= ~SET_DEQ_PENDING;
+	ep->queued_deq_seg = NULL;
+	ep->queued_deq_ptr = NULL;
+
+	list_for_each_entry_safe(td, tmp_td, &ep->cancelled_td_list, cancelled_td_list) {
+		td->cancel_status = TD_CLEARED;
+		ep_ring = xhci_urb_to_transfer_ring(xhci, td->urb);
+		xhci_td_cleanup(xhci, td, ep_ring, td->status);
+	}
 }
 
 static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id,
-- 
2.50.1





[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux