git: 5f3a2b364ea5 - main - ufshci: abort submission when payload DMA mapping fails

From: Jaeyoon Choi <jaeyoon_at_FreeBSD.org>
Date: Mon, 10 Aug 2026 02:31:16 UTC
The branch main has been updated by jaeyoon:

URL: https://cgit.FreeBSD.org/src/commit/?id=5f3a2b364ea51ea05daa4399693bda2021e39434

commit 5f3a2b364ea51ea05daa4399693bda2021e39434
Author:     Jaeyoon Choi <jaeyoon@FreeBSD.org>
AuthorDate: 2026-08-10 01:31:43 +0000
Commit:     Jaeyoon Choi <jaeyoon@FreeBSD.org>
CommitDate: 2026-08-10 02:28:46 +0000

    ufshci: abort submission when payload DMA mapping fails
    
    When bus_dmamap_load_mem() failed, ufshci_req_queue_prepare_prdt()
    manually completed and released the tracker, but its caller kept going:
    it built the UTRD, set the slot back to SCHEDULED, and rang the
    doorbell for a tracker whose request had already been freed. Return the
    mapping error and stop the submission so the released tracker is not
    resurrected.
    
    Sponsored by:           Samsung Electronics
    Reviewed by:            imp (mentor)
    Differential Revision:  https://reviews.freebsd.org/D58653
---
 sys/dev/ufshci/ufshci_req_queue.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/sys/dev/ufshci/ufshci_req_queue.c b/sys/dev/ufshci/ufshci_req_queue.c
index 4c82b79d0e26..395801274f0e 100644
--- a/sys/dev/ufshci/ufshci_req_queue.c
+++ b/sys/dev/ufshci/ufshci_req_queue.c
@@ -371,7 +371,7 @@ ufshci_payload_map(void *arg, bus_dma_segment_t *seg, int nseg, int error)
 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 }
 
-static void
+static int
 ufshci_req_queue_prepare_prdt(struct ufshci_tracker *tr)
 {
 	struct ufshci_request *req = tr->req;
@@ -403,6 +403,8 @@ ufshci_req_queue_prepare_prdt(struct ufshci_tracker *tr)
 		    UFSHCI_RESPONSE_CODE_GENERAL_FAILURE);
 		mtx_lock(&tr->hwq->qlock);
 	}
+
+	return (error);
 }
 
 static void
@@ -716,9 +718,15 @@ ufshci_req_queue_submit_tracker(struct ufshci_req_queue *req_queue,
 		memcpy(tr->ucd, &req->request_upiu, request_len);
 		memset((uint8_t *)tr->ucd + response_off, 0, response_len);
 
-		/* Prepare PRDT */
-		if (req->payload_valid)
-			ufshci_req_queue_prepare_prdt(tr);
+		/*
+		 * Prepare PRDT. If the payload could not be mapped, the
+		 * tracker has already been completed and released by the
+		 * manual completion path, so the descriptor must not be
+		 * built and the doorbell must not be rung.
+		 */
+		if (req->payload_valid &&
+		    ufshci_req_queue_prepare_prdt(tr) != 0)
+			return;
 
 		/* Prepare UTP Transfer Request Descriptor. */
 		ucd_paddr = tr->ucd_bus_addr;