git: 0d5fdcb63c9d - main - ufshci: enable the ufshci module to load at boot time

From: Warner Losh <imp_at_FreeBSD.org>
Date: Wed, 16 Jul 2025 23:21:32 UTC
The branch main has been updated by imp:

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

commit 0d5fdcb63c9df9a28dda04861c30c84d495257b4
Author:     Jaeyoon Choi <j_yoon.choi@samsung.com>
AuthorDate: 2025-07-16 23:14:28 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2025-07-16 23:20:59 +0000

    ufshci: enable the ufshci module to load at boot time
    
    The ufshci driver tried to allocate a single 256KB segment for the UTP
    command descriptor during boot, but failed due to memory fragmentation.
    I fixed it to allocate the buffer in 8KB segments instead.
    
    Sponsored by:           Samsung Electronics
    Reviewed by:            imp
    Differential Revision:  https://reviews.freebsd.org/D50933
---
 sys/conf/files                  | 13 ++++++++++++
 sys/dev/ufshci/ufshci_private.h |  4 ++--
 sys/dev/ufshci/ufshci_req_sdb.c | 45 ++++++++++++++++++++++++++++++++---------
 3 files changed, 51 insertions(+), 11 deletions(-)

diff --git a/sys/conf/files b/sys/conf/files
index 74d251c2b608..dd0d390962f2 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -3227,6 +3227,19 @@ dev/uart/uart_if.m		optional uart
 dev/uart/uart_subr.c		optional uart
 dev/uart/uart_tty.c		optional uart
 #
+# Universal Flash Storage Host Controller Interface drivers
+#
+dev/ufshci/ufshci.c		optional ufshci
+dev/ufshci/ufshci_ctrlr.c	optional ufshci
+dev/ufshci/ufshci_ctrlr_cmd.c	optional ufshci
+dev/ufshci/ufshci_dev.c		optional ufshci
+dev/ufshci/ufshci_pci.c		optional ufshci
+dev/ufshci/ufshci_req_queue.c	optional ufshci
+dev/ufshci/ufshci_req_sdb.c	optional ufshci
+dev/ufshci/ufshci_sim.c		optional ufshci
+dev/ufshci/ufshci_sysctl.c	optional ufshci
+dev/ufshci/ufshci_uic_cmd.c	optional ufshci
+#
 # USB controller drivers
 #
 dev/usb/controller/musb_otg.c		optional musb
diff --git a/sys/dev/ufshci/ufshci_private.h b/sys/dev/ufshci/ufshci_private.h
index cac743884ee6..ac58d44102a0 100644
--- a/sys/dev/ufshci/ufshci_private.h
+++ b/sys/dev/ufshci/ufshci_private.h
@@ -149,6 +149,8 @@ struct ufshci_hw_queue {
 	bus_dmamap_t queuemem_map;
 	bus_addr_t req_queue_addr;
 
+	bus_addr_t *ucd_bus_addr;
+
 	uint32_t num_entries;
 	uint32_t num_trackers;
 
@@ -198,8 +200,6 @@ struct ufshci_req_queue {
 	bus_dma_tag_t dma_tag_payload;
 
 	bus_dmamap_t ucdmem_map;
-
-	bus_addr_t ucd_addr;
 };
 
 struct ufshci_device {
diff --git a/sys/dev/ufshci/ufshci_req_sdb.c b/sys/dev/ufshci/ufshci_req_sdb.c
index 4670281d367a..b1f303afaef5 100644
--- a/sys/dev/ufshci/ufshci_req_sdb.c
+++ b/sys/dev/ufshci/ufshci_req_sdb.c
@@ -48,6 +48,29 @@ ufshci_req_sdb_cmd_desc_destroy(struct ufshci_req_queue *req_queue)
 	}
 }
 
+static void
+ufshci_ucd_map(void *arg, bus_dma_segment_t *seg, int nseg, int error)
+{
+	struct ufshci_hw_queue *hwq = arg;
+	int i;
+
+	if (error != 0) {
+		printf("ufshci: Failed to map UCD, error = %d\n", error);
+		return;
+	}
+
+	if (hwq->num_trackers != nseg) {
+		printf(
+		    "ufshci: Failed to map UCD, num_trackers = %d, nseg = %d\n",
+		    hwq->num_trackers, nseg);
+		return;
+	}
+
+	for (i = 0; i < nseg; i++) {
+		hwq->ucd_bus_addr[i] = seg[i].ds_addr;
+	}
+}
+
 static int
 ufshci_req_sdb_cmd_desc_construct(struct ufshci_req_queue *req_queue,
     uint32_t num_entries, struct ufshci_controller *ctrlr)
@@ -55,7 +78,6 @@ ufshci_req_sdb_cmd_desc_construct(struct ufshci_req_queue *req_queue,
 	struct ufshci_hw_queue *hwq = &req_queue->hwq[UFSHCI_SDB_Q];
 	struct ufshci_tracker *tr;
 	size_t ucd_allocsz, payload_allocsz;
-	uint64_t ucdmem_phys;
 	uint8_t *ucdmem;
 	int i, error;
 
@@ -71,10 +93,11 @@ ufshci_req_sdb_cmd_desc_construct(struct ufshci_req_queue *req_queue,
 	 * Allocate physical memory for UTP Command Descriptor (UCD)
 	 * Note: UFSHCI UCD format is restricted to 128-byte alignment.
 	 */
-	error = bus_dma_tag_create(bus_get_dma_tag(ctrlr->dev), 128,
-	    ctrlr->page_size, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
-	    ucd_allocsz, howmany(ucd_allocsz, ctrlr->page_size),
-	    ctrlr->page_size, 0, NULL, NULL, &req_queue->dma_tag_ucd);
+	error = bus_dma_tag_create(bus_get_dma_tag(ctrlr->dev), 128, 0,
+	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, ucd_allocsz,
+	    howmany(ucd_allocsz, sizeof(struct ufshci_utp_cmd_desc)),
+	    sizeof(struct ufshci_utp_cmd_desc), 0, NULL, NULL,
+	    &req_queue->dma_tag_ucd);
 	if (error != 0) {
 		ufshci_printf(ctrlr, "request cmd desc tag create failed %d\n",
 		    error);
@@ -88,7 +111,7 @@ ufshci_req_sdb_cmd_desc_construct(struct ufshci_req_queue *req_queue,
 	}
 
 	if (bus_dmamap_load(req_queue->dma_tag_ucd, req_queue->ucdmem_map,
-		ucdmem, ucd_allocsz, ufshci_single_map, &ucdmem_phys, 0) != 0) {
+		ucdmem, ucd_allocsz, ufshci_ucd_map, hwq, 0) != 0) {
 		ufshci_printf(ctrlr, "failed to load cmd desc memory\n");
 		bus_dmamem_free(req_queue->dma_tag_ucd, req_queue->ucd,
 		    req_queue->ucdmem_map);
@@ -96,7 +119,6 @@ ufshci_req_sdb_cmd_desc_construct(struct ufshci_req_queue *req_queue,
 	}
 
 	req_queue->ucd = (struct ufshci_utp_cmd_desc *)ucdmem;
-	req_queue->ucd_addr = ucdmem_phys;
 
 	/*
 	 * Allocate physical memory for PRDT
@@ -128,10 +150,9 @@ ufshci_req_sdb_cmd_desc_construct(struct ufshci_req_queue *req_queue,
 		tr->slot_state = UFSHCI_SLOT_STATE_FREE;
 
 		tr->ucd = (struct ufshci_utp_cmd_desc *)ucdmem;
-		tr->ucd_bus_addr = ucdmem_phys;
+		tr->ucd_bus_addr = hwq->ucd_bus_addr[i];
 
 		ucdmem += sizeof(struct ufshci_utp_cmd_desc);
-		ucdmem_phys += sizeof(struct ufshci_utp_cmd_desc);
 
 		hwq->act_tr[i] = tr;
 	}
@@ -175,6 +196,11 @@ ufshci_req_sdb_construct(struct ufshci_controller *ctrlr,
 	req_queue->hwq = malloc(sizeof(struct ufshci_hw_queue), M_UFSHCI,
 	    M_ZERO | M_NOWAIT);
 	hwq = &req_queue->hwq[UFSHCI_SDB_Q];
+	hwq->num_entries = req_queue->num_entries;
+	hwq->num_trackers = req_queue->num_trackers;
+	req_queue->hwq->ucd_bus_addr = malloc(sizeof(bus_addr_t) *
+		req_queue->num_trackers,
+	    M_UFSHCI, M_ZERO | M_NOWAIT);
 
 	mtx_init(&hwq->qlock, "ufshci req_queue lock", NULL, MTX_DEF);
 
@@ -277,6 +303,7 @@ ufshci_req_sdb_destroy(struct ufshci_controller *ctrlr,
 	if (mtx_initialized(&hwq->qlock))
 		mtx_destroy(&hwq->qlock);
 
+	free(req_queue->hwq->ucd_bus_addr, M_UFSHCI);
 	free(req_queue->hwq, M_UFSHCI);
 }