git: 7682b8f37669 - main - ufshci: claim trackers before failing them

From: Jaeyoon Choi <jaeyoon_at_FreeBSD.org>
Date: Thu, 27 Aug 2026 05:12:46 UTC
The branch main has been updated by jaeyoon:

URL: https://cgit.FreeBSD.org/src/commit/?id=7682b8f37669671844fedd94a382ec0c459b9b2c

commit 7682b8f37669671844fedd94a382ec0c459b9b2c
Author:     Jaeyoon Choi <jaeyoon@FreeBSD.org>
AuthorDate: 2026-08-27 05:00:41 +0000
Commit:     Jaeyoon Choi <jaeyoon@FreeBSD.org>
CommitDate: 2026-08-27 05:08:37 +0000

    ufshci: claim trackers before failing them
    
    ufshci_req_queue_fail() drops the queue lock to complete each
    tracker. In that window the completion path could complete the
    same tracker again.
    
    Claim the slot before dropping the lock, so the completion scan
    skips it. Reserved slots are left to their submit thread, which
    completes them itself. The manual request completion helper
    lost its only caller, so drop it.
    
    Reviewed by:            imp (mentor)
    Sponsored by:           Samsung Electronics
    Differential Revision:  https://reviews.freebsd.org/D58945
---
 sys/dev/ufshci/ufshci_req_queue.c | 60 +++++++++++++--------------------------
 1 file changed, 20 insertions(+), 40 deletions(-)

diff --git a/sys/dev/ufshci/ufshci_req_queue.c b/sys/dev/ufshci/ufshci_req_queue.c
index db96d13fad24..97eccd082176 100644
--- a/sys/dev/ufshci/ufshci_req_queue.c
+++ b/sys/dev/ufshci/ufshci_req_queue.c
@@ -182,29 +182,6 @@ ufshci_req_queue_manual_complete_tracker(struct ufshci_tracker *tr, uint8_t ocs,
 	ufshci_req_queue_complete_tracker(tr);
 }
 
-static void
-ufshci_req_queue_manual_complete_request(struct ufshci_req_queue *req_queue,
-    struct ufshci_request *req, uint8_t ocs, uint8_t rc)
-{
-	struct ufshci_completion cpl;
-	bool error;
-
-	memset(&cpl, 0, sizeof(cpl));
-	cpl.response_upiu.header.response = rc;
-	error = ufshci_req_queue_response_is_error(req_queue, ocs,
-	    &cpl.response_upiu);
-
-	if (error) {
-		ufshci_printf(req_queue->ctrlr,
-		    "Manual complete request error:0x%x", error);
-	}
-
-	if (req->cb_fn)
-		req->cb_fn(req->cb_arg, &cpl, error);
-
-	ufshci_free_request(req);
-}
-
 void
 ufshci_req_queue_fail(struct ufshci_controller *ctrlr,
     struct ufshci_req_queue *req_queue)
@@ -221,23 +198,26 @@ ufshci_req_queue_fail(struct ufshci_controller *ctrlr,
 	for (i = 0; i < req_queue->num_trackers; i++) {
 		tr = hwq->act_tr[i];
 
-		if (tr->slot_state == UFSHCI_SLOT_STATE_RESERVED) {
-			mtx_unlock(&hwq->qlock);
-			ufshci_req_queue_manual_complete_request(req_queue,
-			    tr->req, UFSHCI_DESC_ABORTED,
-			    UFSHCI_RESPONSE_CODE_GENERAL_FAILURE);
-			mtx_lock(&hwq->qlock);
-		} else if (tr->slot_state == UFSHCI_SLOT_STATE_SCHEDULED) {
-			/*
-			 * Do not remove the tracker. The abort_tracker path
-			 * will do that for us.
-			 */
-			mtx_unlock(&hwq->qlock);
-			ufshci_req_queue_manual_complete_tracker(tr,
-			    UFSHCI_DESC_ABORTED,
-			    UFSHCI_RESPONSE_CODE_GENERAL_FAILURE);
-			mtx_lock(&hwq->qlock);
-		}
+		/*
+		 * A slot in UFSHCI_SLOT_STATE_RESERVED is visible here
+		 * only while its submit thread is failing a PRDT setup.
+		 * That thread completes the request, so leave the slot
+		 * alone.
+		 */
+		if (tr->slot_state != UFSHCI_SLOT_STATE_SCHEDULED)
+			continue;
+
+		/*
+		 * Claim the tracker under the lock. The completion
+		 * scan only completes SCHEDULED slots, so it will
+		 * skip this one while the lock is dropped.
+		 */
+		tr->slot_state = UFSHCI_SLOT_STATE_NEED_ERROR_HANDLING;
+		mtx_unlock(&hwq->qlock);
+		ufshci_req_queue_manual_complete_tracker(tr,
+		    UFSHCI_DESC_ABORTED,
+		    UFSHCI_RESPONSE_CODE_GENERAL_FAILURE);
+		mtx_lock(&hwq->qlock);
 	}
 
 	mtx_unlock(&hwq->qlock);