git: efdb82413963 - main - thunderbolt: Reset controllers

Aymeric Wibo <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src,gmane.os.freebsd.current.scm
Message-ID <[email protected]>
The branch main has been updated by obiwac:

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

commit efdb82413963bea5f4bf2ae52006cceeb6944a3b
Author:     Aymeric Wibo <[email protected]>
AuthorDate: 2026-08-12 17:40:56 +0000
Commit:     Aymeric Wibo <[email protected]>
CommitDate: 2026-08-12 21:53:13 +0000

    thunderbolt: Reset controllers
    
    Reset routine for both v1.0 and v2.0 routes, chosen depending on version
    reported in caps.
    
    Reviewed by:    imp
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D49452
---
 sys/dev/thunderbolt/nhi.c        | 63 ++++++++++++++++++++++++++++++++++++++++
 sys/dev/thunderbolt/router_var.h |  4 +++
 2 files changed, 67 insertions(+)

diff --git a/sys/dev/thunderbolt/nhi.c b/sys/dev/thunderbolt/nhi.c
index 4b45560923c3..75eb4fe6a5d9 100644
--- a/sys/dev/thunderbolt/nhi.c
+++ b/sys/dev/thunderbolt/nhi.c
@@ -235,6 +235,67 @@ nhi_outmail_cmd(struct nhi_softc *sc, uint32_t *val)
 	return (0);
 }
 
+static int
+nhi_reset_v1(struct nhi_softc *sc)
+{
+
+	/* See section 2.4 of HCM guide v2. */
+	nhi_write_reg(sc, ROUTER_HIR, 1);
+	pause_sbt("nhi", ustosbt(10 * 1000), 0, C_HARDCLOCK);
+	return (0);
+}
+
+static int
+nhi_reset_v2(struct nhi_softc *sc)
+{
+	uint32_t reg;
+
+	/*
+	 * TODO "The Connection Manager shall disable all Transmit Descriptor
+	 * Rings and wait for at least 1 millisecond prior to setting the Host
+	 * Router Reset bit to 1b. After the Connection Manager sets the Host
+	 * Router Reset bit to 1b, it shall not access the Receive Descriptor
+	 * Rings until the Host Router Reset bit is set to 0b."
+	 */
+	/* See section 3.5 of HCM guide v2. */
+	nhi_write_reg(sc, ROUTER_HRR, 1);
+	/*
+	 * "The Host Router is required to complete its reset within 500ms
+	 * after the Host Router Reset bit is set to 1b."
+	 */
+	for (size_t i = 0; i < 10 && reg; i++) {
+		/*
+		 * Wait at least 50 ms after writing before reading this
+		 * register.  If this is 1, it means that we are still
+		 * resetting.
+		 */
+		pause_sbt("nhi", ustosbt(50 * 1000), 0, 0);
+		reg = nhi_read_reg(sc, ROUTER_HRR);
+	}
+	if (reg == 0) {
+		tb_debug(sc, DBG_INIT|DBG_EXTRA,
+		    "Succeeded in resetting host router\n");
+		return (0);
+	}
+	tb_printf(sc, "Host router reset timed out\n");
+	return (ETIMEDOUT);
+}
+
+static int
+nhi_reset(struct nhi_softc *sc)
+{
+
+	tb_debug(sc, DBG_INIT, "Resetting host router\n");
+
+	switch (sc->ver) {
+	case NHI_VER_1_0:
+		return (nhi_reset_v1(sc));
+	case NHI_VER_2_0:
+		return (nhi_reset_v2(sc));
+	}
+	return (ENXIO);
+}
+
 int
 nhi_attach(struct nhi_softc *sc)
 {
@@ -272,6 +333,8 @@ nhi_attach(struct nhi_softc *sc)
 	}
 	sc->path_count = val;
 
+	nhi_reset(sc);
+
 	SLIST_INIT(&sc->ring_list);
 
 	error = nhi_pci_configure_interrupts(sc);
diff --git a/sys/dev/thunderbolt/router_var.h b/sys/dev/thunderbolt/router_var.h
index 8366ede852e7..06c41e636121 100644
--- a/sys/dev/thunderbolt/router_var.h
+++ b/sys/dev/thunderbolt/router_var.h
@@ -87,6 +87,10 @@ struct router_cfg_cap {
 	uint16_t	vsec_len;
 };
 
+/* Router reset registers */
+#define ROUTER_HRR	0x39898
+#define ROUTER_HIR	0x39858
+
 int tb_router_attach(struct router_softc *, tb_route_t);
 int tb_router_attach_root(struct nhi_softc *, tb_route_t);
 int tb_router_detach(struct router_softc *);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.