aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaeyoon Choi <jaeyoon@FreeBSD.org>2026-08-10 01:31:43 +0000
committerJaeyoon Choi <jaeyoon@FreeBSD.org>2026-08-10 02:28:46 +0000
commit5f3a2b364ea51ea05daa4399693bda2021e39434 (patch)
tree59f9b7009a1271a3ca193135d6386d2284ff94e2
parentcf04a05424f1a79e55303de252e5873abeae7b88 (diff)
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
-rw-r--r--sys/dev/ufshci/ufshci_req_queue.c16
1 files 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;