Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Apr 2026 12:12:51 +0000
From:      Aymeric Wibo <obiwac@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: bb36c457ea49 - main - thunderbolt: Support generic USB4 NHIs
Message-ID:  <69df80c3.3bd7d.59a4f11d@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by obiwac:

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

commit bb36c457ea49d80ca3109ef25ca41a614f9738b8
Author:     Aymeric Wibo <obiwac@FreeBSD.org>
AuthorDate: 2026-04-15 12:04:17 +0000
Commit:     Aymeric Wibo <obiwac@FreeBSD.org>
CommitDate: 2026-04-15 12:10:24 +0000

    thunderbolt: Support generic USB4 NHIs
    
    Check a PCI device's class, subclass, and progif to figure out if it is
    a USB4 NHI. nhi_identifiers is completely removed as only these generic
    USB4 NHIs are supported anyway, and all remnants of ICM-supporting code
    are removed too. All devices now use the HCM.
    
    PR:             290827
    Reviewed by:    jhb, ngie
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D52861
---
 sys/dev/pci/pcireg.h          |   1 +
 sys/dev/thunderbolt/nhi.c     |  49 ++---------------
 sys/dev/thunderbolt/nhi_pci.c | 121 ++----------------------------------------
 sys/dev/thunderbolt/nhi_var.h |  18 -------
 sys/dev/thunderbolt/tb_pcib.c |  12 -----
 5 files changed, 9 insertions(+), 192 deletions(-)

diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h
index f6aaf30611e4..3ec7879b8a09 100644
--- a/sys/dev/pci/pcireg.h
+++ b/sys/dev/pci/pcireg.h
@@ -464,6 +464,7 @@
 #define	PCIP_SERIALBUS_USB_OHCI		0x10
 #define	PCIP_SERIALBUS_USB_EHCI		0x20
 #define	PCIP_SERIALBUS_USB_XHCI		0x30
+#define	PCIP_SERIALBUS_USB_USB4		0x40
 #define	PCIP_SERIALBUS_USB_DEVICE	0xfe
 #define	PCIS_SERIALBUS_FC	0x04
 #define	PCIS_SERIALBUS_SMBUS	0x05
diff --git a/sys/dev/thunderbolt/nhi.c b/sys/dev/thunderbolt/nhi.c
index 30a72652535a..74cefbb50ca1 100644
--- a/sys/dev/thunderbolt/nhi.c
+++ b/sys/dev/thunderbolt/nhi.c
@@ -84,11 +84,6 @@ MALLOC_DEFINE(M_NHI, "nhi", "nhi driver memory");
 #define NHI_DEBUG_LEVEL 0
 #endif
 
-/* 0 = default, 1 = force-on, 2 = force-off */
-#ifndef NHI_FORCE_HCM
-#define NHI_FORCE_HCM 0
-#endif
-
 void
 nhi_get_tunables(struct nhi_softc *sc)
 {
@@ -100,7 +95,6 @@ nhi_get_tunables(struct nhi_softc *sc)
 	/* Set local defaults */
 	sc->debug = NHI_DEBUG_LEVEL;
 	sc->max_ring_count = NHI_DEFAULT_NUM_RINGS;
-	sc->force_hcm = NHI_FORCE_HCM;
 
 	/* Inherit setting from the upstream thunderbolt switch node */
 	val = TB_GET_DEBUG(sc->dev, &sc->debug);
@@ -128,8 +122,6 @@ nhi_get_tunables(struct nhi_softc *sc)
 		val = min(val, NHI_MAX_NUM_RINGS);
 		sc->max_ring_count = max(val, 1);
 	}
-	if (TUNABLE_INT_FETCH("hw.nhi.force_hcm", &val) != 0)
-		sc->force_hcm = val;
 
 	/* Grab instance variables */
 	bzero(oid, 80);
@@ -143,24 +135,10 @@ nhi_get_tunables(struct nhi_softc *sc)
 		val = min(val, NHI_MAX_NUM_RINGS);
 		sc->max_ring_count = max(val, 1);
 	}
-	snprintf(tmpstr, sizeof(tmpstr), "dev, nhi.%d.force_hcm",
-	    device_get_unit(sc->dev));
-	if (TUNABLE_INT_FETCH(tmpstr, &val) != 0)
-		sc->force_hcm = val;
 
 	return;
 }
 
-static void
-nhi_configure_caps(struct nhi_softc *sc)
-{
-
-	if (NHI_IS_USB4(sc) || (sc->force_hcm == NHI_FORCE_HCM_ON))
-		sc->caps |= NHI_CAP_HCM;
-	if (sc->force_hcm == NHI_FORCE_HCM_OFF)
-		sc->caps &= ~NHI_CAP_HCM;
-}
-
 struct nhi_cmd_frame *
 nhi_alloc_tx_frame(struct nhi_ring_pair *r)
 {
@@ -268,16 +246,14 @@ nhi_attach(struct nhi_softc *sc)
 
 	mtx_init(&sc->nhi_mtx, "nhimtx", "NHI Control Mutex", MTX_DEF);
 
-	nhi_configure_caps(sc);
-
 	/*
 	 * Get the number of TX/RX paths.  This sizes some of the register
 	 * arrays during allocation and initialization.  USB4 spec says that
-	 * the max is 21.  Alpine Ridge appears to default to 12.
+	 * the max is 21.
 	 */
 	val = GET_HOST_CAPS_PATHS(nhi_read_reg(sc, NHI_HOST_CAPS));
 	tb_debug(sc, DBG_INIT|DBG_NOISY, "Total Paths= %d\n", val);
-	if ((val == 0) || (val > 21) || ((NHI_IS_AR(sc) && val != 12))) {
+	if (val == 0 || val > 21) {
 		tb_printf(sc, "WARN: unexpected number of paths: %d\n", val);
 		/* return (ENXIO); */
 	}
@@ -297,10 +273,6 @@ nhi_attach(struct nhi_softc *sc)
 	if (error == 0)
 		error = tbdev_add_interface(sc);
 
-	if ((error == 0) && (NHI_USE_ICM(sc)))
-		tb_printf(sc, "WARN: device uses an internal connection manager\n");
-	if ((error == 0) && (NHI_USE_HCM(sc)))
-		;
 	error = hcm_attach(sc);
 
 	if (error == 0)
@@ -312,9 +284,7 @@ nhi_attach(struct nhi_softc *sc)
 int
 nhi_detach(struct nhi_softc *sc)
 {
-
-	if (NHI_USE_HCM(sc))
-		hcm_detach(sc);
+	hcm_detach(sc);
 
 	if (sc->root_rsc != NULL)
 		tb_router_detach(sc->root_rsc);
@@ -706,16 +676,6 @@ nhi_init(struct nhi_softc *sc)
 	tb_debug(sc, DBG_INIT, "Setting interrupt auto-ACK, 0x%08x\n", val);
 	nhi_write_reg(sc, NHI_DMA_MISC, val);
 
-	if (NHI_IS_AR(sc) || NHI_IS_TR(sc) || NHI_IS_ICL(sc))
-		tb_printf(sc, "WARN: device uses an internal connection manager\n");
-
-	/*
-	 * Populate the controller (local) UUID, necessary for cross-domain
-	 * communications.
-	if (NHI_IS_ICL(sc))
-		nhi_pci_get_uuid(sc);
-	 */
-
 	/*
 	 * Attach the router to the root thunderbolt bridge now that the DMA
 	 * channel is configured and ready.
@@ -1163,9 +1123,6 @@ nhi_setup_sysctl(struct nhi_softc *sc)
 	SYSCTL_ADD_U16(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 	    "max_rings", CTLFLAG_RD, &sc->max_ring_count, 0,
 	    "Max number of rings available");
-	SYSCTL_ADD_U8(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
-	    "force_hcm", CTLFLAG_RD, &sc->force_hcm, 0,
-	    "Force on/off the function of the host connection manager");
 
 	return (0);
 }
diff --git a/sys/dev/thunderbolt/nhi_pci.c b/sys/dev/thunderbolt/nhi_pci.c
index 14cae7427448..777f8dd5352e 100644
--- a/sys/dev/thunderbolt/nhi_pci.c
+++ b/sys/dev/thunderbolt/nhi_pci.c
@@ -68,7 +68,6 @@ static int	nhi_pci_resume(device_t);
 static void	nhi_pci_free(struct nhi_softc *);
 static int	nhi_pci_allocate_interrupts(struct nhi_softc *);
 static void	nhi_pci_free_resources(struct nhi_softc *);
-static int	nhi_pci_icl_poweron(struct nhi_softc *);
 
 static device_method_t nhi_methods[] = {
 	DEVMETHOD(device_probe, 	nhi_pci_probe),
@@ -89,67 +88,18 @@ static driver_t nhi_pci_driver = {
 	sizeof(struct nhi_softc)
 };
 
-struct nhi_ident {
-	uint16_t	vendor;
-	uint16_t	device;
-	uint16_t	subvendor;
-	uint16_t	subdevice;
-	uint32_t	flags;
-	const char	*desc;
-} nhi_identifiers[] = {
-	{ VENDOR_INTEL, DEVICE_AR_2C_NHI, 0xffff, 0xffff, NHI_TYPE_AR,
-	    "Thunderbolt 3 NHI (Alpine Ridge 2C)" },
-	{ VENDOR_INTEL, DEVICE_AR_DP_B_NHI, 0xffff, 0xffff, NHI_TYPE_AR,
-	    "Thunderbolt 3 NHI (Alpine Ridge 4C Rev B)" },
-	{ VENDOR_INTEL, DEVICE_AR_DP_C_NHI, 0xffff, 0xffff, NHI_TYPE_AR,
-	    "Thunderbolt 3 NHI (Alpine Ridge 4C Rev C)" },
-	{ VENDOR_INTEL, DEVICE_AR_LP_NHI, 0xffff, 0xffff, NHI_TYPE_AR,
-	    "Thunderbolt 3 NHI (Alpine Ridge LP 2C)" },
-	{ VENDOR_INTEL, DEVICE_ICL_NHI_0, 0xffff, 0xffff, NHI_TYPE_ICL,
-	    "Thunderbolt 3 NHI Port 0 (IceLake)" },
-	{ VENDOR_INTEL, DEVICE_ICL_NHI_1, 0xffff, 0xffff, NHI_TYPE_ICL,
-	    "Thunderbolt 3 NHI Port 1 (IceLake)" },
-	{ VENDOR_AMD, DEVICE_PINK_SARDINE_0, 0xffff, 0xffff, NHI_TYPE_USB4,
-	    "USB4 NHI Port 0 (Pink Sardine)" },
-	{ VENDOR_AMD, DEVICE_PINK_SARDINE_1, 0xffff, 0xffff, NHI_TYPE_USB4,
-	    "USB4 NHI Port 1 (Pink Sardine)" },
-	{ 0, 0, 0, 0, 0, NULL }
-};
-
 DRIVER_MODULE_ORDERED(nhi, pci, nhi_pci_driver, NULL, NULL,
     SI_ORDER_ANY);
 
-static struct nhi_ident *
-nhi_find_ident(device_t dev)
-{
-	struct nhi_ident *n;
-
-	for (n = nhi_identifiers; n->vendor != 0; n++) {
-		if (n->vendor != pci_get_vendor(dev))
-			continue;
-		if (n->device != pci_get_device(dev))
-			continue;
-		if ((n->subvendor != 0xffff) &&
-		    (n->subvendor != pci_get_subvendor(dev)))
-			continue;
-		if ((n->subdevice != 0xffff) &&
-		    (n->subdevice != pci_get_subdevice(dev)))
-			continue;
-		return (n);
-	}
-
-	return (NULL);
-}
-
 static int
 nhi_pci_probe(device_t dev)
 {
-	struct nhi_ident *n;
-
 	if (resource_disabled("tb", 0))
 		return (ENXIO);
-	if ((n = nhi_find_ident(dev)) != NULL) {
-		device_set_desc(dev, n->desc);
+	if ((pci_get_class(dev) == PCIC_SERIALBUS)
+	    && (pci_get_subclass(dev) == PCIS_SERIALBUS_USB)
+	    && (pci_get_progif(dev) == PCIP_SERIALBUS_USB_USB4)) {
+		device_set_desc(dev, "Generic USB4 NHI");
 		return (BUS_PROBE_DEFAULT);
 	}
 	return (ENXIO);
@@ -161,14 +111,12 @@ nhi_pci_attach(device_t dev)
 	devclass_t dc;
 	bus_dma_template_t t;
 	struct nhi_softc *sc;
-	struct nhi_ident *n;
 	int error = 0;
 
 	sc = device_get_softc(dev);
 	bzero(sc, sizeof(*sc));
 	sc->dev = dev;
-	n = nhi_find_ident(dev);
-	sc->hwflags = n->flags;
+	sc->hwflags = NHI_TYPE_USB4;
 	nhi_get_tunables(sc);
 
 	tb_debug(sc, DBG_INIT|DBG_FULL, "busmaster status was %s\n",
@@ -188,12 +136,6 @@ nhi_pci_attach(device_t dev)
 		tb_printf(sc, "Upstream Facing Port is %s\n",
 		    device_get_nameunit(sc->ufp));
 
-	if (NHI_IS_ICL(sc)) {
-		if ((error = nhi_pci_icl_poweron(sc)) != 0)
-			return (error);
-	}
-
-
 	/* Allocate BAR0 DMA registers */
 	sc->regs_rid = PCIR_BAR(0);
 	if ((sc->regs_resource = bus_alloc_resource_any(dev,
@@ -476,56 +418,3 @@ nhi_pci_disable_interrupts(struct nhi_softc *sc)
 	nhi_read_reg(sc, NHI_ISR0);
 	nhi_read_reg(sc, NHI_ISR1);
 }
-
-/*
- * Icelake controllers need to be notified of power-on
- */
-static int
-nhi_pci_icl_poweron(struct nhi_softc *sc)
-{
-	device_t dev;
-	uint32_t val;
-	int i, error = 0;
-
-	dev = sc->dev;
-	val = pci_read_config(dev, ICL_VSCAP_9, 4);
-	tb_debug(sc, DBG_INIT, "icl_poweron val= 0x%x\n", val);
-	if (val & ICL_VSCAP9_FWREADY)
-		return (0);
-
-	val = pci_read_config(dev, ICL_VSCAP_22, 4);
-	val |= ICL_VSCAP22_FORCEPWR;
-	tb_debug(sc, DBG_INIT|DBG_FULL, "icl_poweron writing 0x%x\n", val);
-	pci_write_config(dev, ICL_VSCAP_22, val, 4);
-
-	error = ETIMEDOUT;
-	for (i = 0; i < 15; i++) {
-		DELAY(1000000);
-		val = pci_read_config(dev, ICL_VSCAP_9, 4);
-		if (val & ICL_VSCAP9_FWREADY) {
-			error = 0;
-			break;
-		}
-	}
-
-	return (error);
-}
-
-/*
- * Icelake and Alderlake controllers store their UUID in PCI config space
- */
-int
-nhi_pci_get_uuid(struct nhi_softc *sc)
-{
-	device_t dev;
-	uint32_t val[4];
-
-	dev = sc->dev;
-	val[0] = pci_read_config(dev, ICL_VSCAP_10, 4);
-	val[1] = pci_read_config(dev, ICL_VSCAP_11, 4);
-	val[2] = 0xffffffff;
-	val[3] = 0xffffffff;
-
-	bcopy(val, &sc->uuid, 16);
-	return (0);
-}
diff --git a/sys/dev/thunderbolt/nhi_var.h b/sys/dev/thunderbolt/nhi_var.h
index e79ecc954c1f..e22c0f4a2bae 100644
--- a/sys/dev/thunderbolt/nhi_var.h
+++ b/sys/dev/thunderbolt/nhi_var.h
@@ -142,19 +142,9 @@ struct nhi_softc {
 	u_int			debug;
 	u_int			hwflags;
 #define NHI_TYPE_UNKNOWN	0x00
-#define NHI_TYPE_AR		0x01		/* Alpine Ridge */
-#define NHI_TYPE_TR		0x02		/* Titan Ridge */
-#define NHI_TYPE_ICL		0x03		/* IceLake */
-#define NHI_TYPE_MR		0x04		/* Maple Ridge */
-#define NHI_TYPE_ADL		0x05		/* AlderLake */
 #define NHI_TYPE_USB4		0x0f
 #define NHI_TYPE_MASK		0x0f
 #define NHI_MBOX_BUSY		0x10
-	u_int			caps;
-#define NHI_CAP_ICM		0x01
-#define NHI_CAP_HCM		0x02
-#define NHI_USE_ICM(sc)		((sc)->caps & NHI_CAP_ICM)
-#define NHI_USE_HCM(sc)		((sc)->caps & NHI_CAP_HCM)
 	struct hcm_softc	*hcm;
 	struct router_softc	*root_rsc;
 
@@ -194,11 +184,6 @@ struct nhi_softc {
 
 	struct intr_config_hook	ich;
 
-	uint8_t			force_hcm;
-#define NHI_FORCE_HCM_DEFAULT	0x00
-#define NHI_FORCE_HCM_ON	0x01
-#define NHI_FORCE_HCM_OFF	0x02
-
 	uint8_t			uuid[16];
 	uint8_t			lc_uuid[16];
 };
@@ -209,9 +194,6 @@ struct nhi_dispatch {
 	void			*context;
 };
 
-#define NHI_IS_AR(sc)	(((sc)->hwflags & NHI_TYPE_MASK) == NHI_TYPE_AR)
-#define NHI_IS_TR(sc)	(((sc)->hwflags & NHI_TYPE_MASK) == NHI_TYPE_TR)
-#define NHI_IS_ICL(sc)	(((sc)->hwflags & NHI_TYPE_MASK) == NHI_TYPE_ICL)
 #define NHI_IS_USB4(sc)	(((sc)->hwflags & NHI_TYPE_MASK) == NHI_TYPE_USB4)
 
 int nhi_pci_configure_interrupts(struct nhi_softc *sc);
diff --git a/sys/dev/thunderbolt/tb_pcib.c b/sys/dev/thunderbolt/tb_pcib.c
index ffb85ebec9ae..b30de5a7493c 100644
--- a/sys/dev/thunderbolt/tb_pcib.c
+++ b/sys/dev/thunderbolt/tb_pcib.c
@@ -90,18 +90,6 @@ struct tb_pcib_ident {
 	uint32_t	flags;		/* This follows the tb_softc flags */
 	const char	*desc;
 } tb_pcib_identifiers[] = {
-	{ VENDOR_INTEL, TB_DEV_AR_2C, 0xffff, 0xffff, TB_GEN_TB3|TB_HWIF_AR,
-	    "Thunderbolt 3 PCI-PCI Bridge (Alpine Ridge 2C)" },
-	{ VENDOR_INTEL, TB_DEV_AR_LP, 0xffff, 0xffff, TB_GEN_TB3|TB_HWIF_AR,
-	    "Thunderbolt 3 PCI-PCI Bridge (Alpine Ridge LP)" },
-	{ VENDOR_INTEL, TB_DEV_AR_C_4C, 0xffff, 0xffff, TB_GEN_TB3|TB_HWIF_AR,
-	    "Thunderbolt 3 PCI-PCI Bridge (Alpine Ridge C 4C)" },
-	{ VENDOR_INTEL, TB_DEV_AR_C_2C, 0xffff, 0xffff, TB_GEN_TB3|TB_HWIF_AR,
-	    "Thunderbolt 3 PCI-PCI Bridge C (Alpine Ridge C 2C)" },
-	{ VENDOR_INTEL, TB_DEV_ICL_0, 0xffff, 0xffff, TB_GEN_TB3|TB_HWIF_ICL,
-	    "Thunderbolt 3 PCI-PCI Bridge (IceLake)" },
-	{ VENDOR_INTEL, TB_DEV_ICL_1, 0xffff, 0xffff, TB_GEN_TB3|TB_HWIF_ICL,
-	    "Thunderbolt 3 PCI-PCI Bridge (IceLake)" },
 	{ 0, 0, 0, 0, 0, NULL }
 };
 


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69df80c3.3bd7d.59a4f11d>