git: 4861ef4e8245 - main - ufshci: try the link startup more than once

From: Jaeyoon Choi <jaeyoon_at_FreeBSD.org>
Date: Tue, 03 Nov 2026 04:33:52 UTC
The branch main has been updated by jaeyoon:

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

commit 4861ef4e82451bfb1e5fd58d02a38f6baf20eb24
Author:     Jaeyoon Choi <jaeyoon@FreeBSD.org>
AuthorDate: 2026-11-03 04:26:00 +0000
Commit:     Jaeyoon Choi <jaeyoon@FreeBSD.org>
CommitDate: 2026-11-03 04:29:46 +0000

    ufshci: try the link startup more than once
    
    A device that is still powering on may not answer the first
    DME_LINKSTARTUP, and the driver gave up after one try.
    
    Try up to three times. Both attach and reset use this path.
    
    Reviewed by:            imp
    Sponsored by:           Samsung Electronics
    Differential Revision:  https://reviews.freebsd.org/D61121
---
 sys/dev/ufshci/ufshci_ctrlr.c   | 33 +++++++++++++++++++++------------
 sys/dev/ufshci/ufshci_private.h |  3 +++
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/sys/dev/ufshci/ufshci_ctrlr.c b/sys/dev/ufshci/ufshci_ctrlr.c
index e37764f874b9..32c85f87ffcc 100644
--- a/sys/dev/ufshci/ufshci_ctrlr.c
+++ b/sys/dev/ufshci/ufshci_ctrlr.c
@@ -287,7 +287,7 @@ ufshci_ctrlr_disable(struct ufshci_controller *ctrlr)
 int
 ufshci_ctrlr_enable(struct ufshci_controller *ctrlr)
 {
-	uint32_t ie, hcs;
+	uint32_t ie, hcs, attempt;
 	int error;
 
 	error = ufshci_ctrlr_enable_host_ctrlr(ctrlr);
@@ -295,18 +295,27 @@ ufshci_ctrlr_enable(struct ufshci_controller *ctrlr)
 		return (error);
 
 	/* Send DME_LINKSTARTUP command to start the link startup procedure */
-	error = ufshci_uic_send_dme_link_startup(ctrlr);
-	if (error)
-		return (error);
+	for (attempt = 0; attempt < UFSHCI_MAX_LINK_STARTUP_ATTEMPTS;
+	    attempt++) {
+		error = ufshci_uic_send_dme_link_startup(ctrlr);
+		if (error) {
+			ufshci_printf(ctrlr,
+			    "DME_LINKSTARTUP attempt %u failed: %d\n",
+			    attempt + 1, error);
+			continue;
+		}
 
-	/*
-	 * The device_present(UFSHCI_HCS_REG_DP) bit becomes true if the host
-	 * controller has successfully received a Link Startup UIC command
-	 * response and the UFS device has found a physical link to the
-	 * controller.
-	 */
-	hcs = ufshci_mmio_read_4(ctrlr, hcs);
-	if (!UFSHCIV(UFSHCI_HCS_REG_DP, hcs)) {
+		/*
+		 * The device_present(UFSHCI_HCS_REG_DP) bit becomes true if
+		 * the host controller has successfully received a Link
+		 * Startup UIC command response and the UFS device has found
+		 * a physical link to the controller.
+		 */
+		hcs = ufshci_mmio_read_4(ctrlr, hcs);
+		if (UFSHCIV(UFSHCI_HCS_REG_DP, hcs))
+			break;
+	}
+	if (attempt == UFSHCI_MAX_LINK_STARTUP_ATTEMPTS) {
 		ufshci_printf(ctrlr, "UFS device not found\n");
 		return (ENXIO);
 	}
diff --git a/sys/dev/ufshci/ufshci_private.h b/sys/dev/ufshci/ufshci_private.h
index 69ff9c7f8f51..c75044f39d7f 100644
--- a/sys/dev/ufshci/ufshci_private.h
+++ b/sys/dev/ufshci/ufshci_private.h
@@ -47,6 +47,9 @@ MALLOC_DECLARE(M_UFSHCI);
 
 #define UFSHCI_DEFAULT_RETRY_COUNT    (4)
 
+/* A device that is still powering on does not answer the first one. */
+#define UFSHCI_MAX_LINK_STARTUP_ATTEMPTS (3)
+
 #define UFSHCI_UTR_ENTRIES	      (32)
 #define UFSHCI_UTRM_ENTRIES	      (8)