git: b90c2b13e975 - main - nvme: complete requests when payload DMA mapping fails

From: Abdelkader Boudih <seuros_at_FreeBSD.org>
Date: Thu, 03 Sep 2026 15:34:30 UTC
The branch main has been updated by seuros:

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

commit b90c2b13e975c803e426a6e6f080a6089d08e6ab
Author:     Abdelkader Boudih <seuros@FreeBSD.org>
AuthorDate: 2026-09-03 15:33:49 +0000
Commit:     Abdelkader Boudih <seuros@FreeBSD.org>
CommitDate: 2026-09-03 15:33:49 +0000

    nvme: complete requests when payload DMA mapping fails
    
    bus_dmamap_load_mem() reports most mapping failures, including EFBIG,
    only through its callback and then returns zero. nvme_payload_map()
    logged the error without telling the submission path, so the tracker
    stayed on the outstanding list with no command submitted and no
    timeout armed, stalling all later I/O on the queue behind it.
    
    Approved by: ngie (co-mentor)
    MFC after:      1 week
    
    Reviewed by:    ngie, imp
    Differential Revision:  https://reviews.freebsd.org/D59151
---
 sys/dev/nvme/nvme_qpair.c | 37 +++++++++++--------------------------
 1 file changed, 11 insertions(+), 26 deletions(-)

diff --git a/sys/dev/nvme/nvme_qpair.c b/sys/dev/nvme/nvme_qpair.c
index 29e373e1b00c..6411a3909917 100644
--- a/sys/dev/nvme/nvme_qpair.c
+++ b/sys/dev/nvme/nvme_qpair.c
@@ -1053,7 +1053,6 @@ nvme_qpair_submit_tracker(struct nvme_qpair *qpair, struct nvme_tracker *tr)
 	mtx_assert(&qpair->lock, MA_OWNED);
 
 	req = tr->req;
-	req->cmd.cid = qpair->cid_base + tr->cid;
 	qpair->act_tr[tr->cid] = tr;
 	ctrlr = qpair->ctrlr;
 
@@ -1089,16 +1088,16 @@ static void
 nvme_payload_map(void *arg, bus_dma_segment_t *seg, int nseg, int error)
 {
 	struct nvme_tracker 	*tr = arg;
+	struct nvme_qpair	*qpair = tr->qpair;
 	uint32_t		cur_nseg;
 
-	/*
-	 * If the mapping operation failed, return immediately.  The caller
-	 *  is responsible for detecting the error status and failing the
-	 *  tracker manually.
-	 */
 	if (error != 0) {
-		nvme_printf(tr->qpair->ctrlr,
-		    "nvme_payload_map err %d\n", error);
+		nvme_printf(qpair->ctrlr,
+		    "payload DMA mapping failed with error %d\n", error);
+		mtx_unlock(&qpair->lock);
+		nvme_qpair_manual_complete_tracker(tr, NVME_SCT_GENERIC,
+		    NVME_SC_DATA_TRANSFER_ERROR, DO_NOT_RETRY, ERROR_PRINT_ALL);
+		mtx_lock(&qpair->lock);
 		return;
 	}
 
@@ -1137,7 +1136,6 @@ static void
 _nvme_qpair_submit_request(struct nvme_qpair *qpair, struct nvme_request *req)
 {
 	struct nvme_tracker	*tr;
-	int			err = 0;
 	bool			is_admin = qpair == &qpair->ctrlr->adminq;
 
 	mtx_assert(&qpair->lock, MA_OWNED);
@@ -1180,6 +1178,7 @@ _nvme_qpair_submit_request(struct nvme_qpair *qpair, struct nvme_request *req)
 	TAILQ_INSERT_TAIL(&qpair->outstanding_tr, tr, tailq);
 	tr->deadline = SBT_MAX;
 	tr->req = req;
+	req->cmd.cid = qpair->cid_base + tr->cid;
 
 	if (!req->payload_valid) {
 		nvme_qpair_submit_tracker(tr->qpair, tr);
@@ -1191,23 +1190,9 @@ _nvme_qpair_submit_request(struct nvme_qpair *qpair, struct nvme_request *req)
 	 * nvme_qpair_submit_tracker (we call it above directly
 	 * when there's no map to load).
 	 */
-	err = bus_dmamap_load_mem(tr->qpair->dma_tag_payload,
-	    tr->payload_dma_map, &req->payload, nvme_payload_map, tr, 0);
-	if (err != 0) {
-		/*
-		 * The dmamap operation failed, so we manually fail the
-		 *  tracker here with DATA_TRANSFER_ERROR status.
-		 *
-		 * nvme_qpair_manual_complete_tracker must not be called
-		 *  with the qpair lock held.
-		 */
-		nvme_printf(qpair->ctrlr,
-		    "bus_dmamap_load_mem returned 0x%x!\n", err);
-		mtx_unlock(&qpair->lock);
-		nvme_qpair_manual_complete_tracker(tr, NVME_SCT_GENERIC,
-		    NVME_SC_DATA_TRANSFER_ERROR, DO_NOT_RETRY, ERROR_PRINT_ALL);
-		mtx_lock(&qpair->lock);
-	}
+	(void)bus_dmamap_load_mem(tr->qpair->dma_tag_payload,
+	    tr->payload_dma_map, &req->payload, nvme_payload_map, tr,
+	    BUS_DMA_NOWAIT);
 }
 
 void