The branch main has been updated by jaeyoon:

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

commit 5f3a2b364ea51ea05daa4399693bda2021e39434
Author:     Jaeyoon Choi <[email protected]>
AuthorDate: 2026-08-10 01:31:43 +0000
Commit:     Jaeyoon Choi <[email protected]>
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;

Reply via email to