From nobody Fri Oct 09 17:33:27 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4j1YqX127Fz6vnRg for ; Fri, 09 Oct 2026 17:33:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4j1YqX0Rsdz4l3J for ; Fri, 09 Oct 2026 17:33:28 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791567208; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=ArSKO2SlAGboWmkwwVuirp7cy+acw1+oXz+xHum1EPw=; b=KeNpUuTuN65FskKwBqzHpzie57g9Sval9DMHu9oFLGh8/KGdysbZ+3/O4134Akn1WExp5V qBxbNsQt+LbkV32FV9Nt867fDw/jf8GNzlW+39j6w5IwZryPOAqyws2wMIqBt6VnPcoKrR dYwbRH0j8CFIG49zmooLlyPvn/Rt5r0gRVHmyN7OC59r7TF7++rcuapB0uTvcjphqS+uc+ HqXdlK6syruzbma0S1jIVYy6U8b23HiTm5pjjBL2C4BNEdSqFUfJoGxgMZrtxMshJvyZ4Z ei1vAtUCLEI2YemLS9iMC4YBguZ4Tfc0PhB22/qr2g6t+dootdCdIm3O9ZoX5w== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1791567208; b=ty5k0PX5Oxp9+gSt5b3B2Ocg19gip74wPN7ZAoF+7A0bp8E6Bur6qo8hTp647FlPjp3u5O sI0HJtyLxABqDH4kslM0yQMPs68SMc3AISUSV64LSxFNEefPEPo3JVzd6z1qCL4Xmh0QOb RhzYxe0ZXyZMt1DDFl4Zpb+6aDFQOdtTBaCVpJAoBkiFX3OmSHGlbxi4Xzud2h0tH19zqR moTFdJW70AIQto4SEX4XCHSLvt5u8JvdUFGoNk+VwoMwDM9O6tz7+Ld7l08PBOb/3xbGwQ u1zuM43nhZ2qi03MD2CgbLI0maAfRPf1JBW5bc3N7Lnb54DxdlXjuughk1u0WA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791567208; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=ArSKO2SlAGboWmkwwVuirp7cy+acw1+oXz+xHum1EPw=; b=tTRM02Nf9j+kxpfXKiXQ5WgaYQcAmVnxp6beeYAKy+Ii/tii0MoVV095xIIWS+6/taA1CA jB6V0ssJ9ADapUlsijJ/GlA0t3qpPqCcWua15vHTR83z0B9kERVS410yHGNmB7GDXu3dPs VI4kbny3SHdWGujrhbfD4QtimGXaAyehCnRS8oadgFRWkCrS9l47T7SuJ1wB7FzTPAdgBZ xcw/cV9aExgYH+GDVhjTya3xENgzwSPnkRu22eG2ZHuyUU8PqkaV+TK0phSENOJbraHq85 dptWnnxAzBwc+UIG/CBRF37Rm19Nrf7e1Q92/pbewUmkMRpkTNbZ8RUFtY60Xg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4j1YqW6YzZzJnh for ; Fri, 09 Oct 2026 17:33:27 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1980f by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 09 Oct 2026 17:33:27 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Aymeric Wibo Subject: git: 02880ddf9ed0 - main - thunderbolt: Router suspend routine List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: obiwac X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 02880ddf9ed01a4b3444239309f522309ef11043 Auto-Submitted: auto-generated Date: Fri, 09 Oct 2026 17:33:27 +0000 Message-Id: <6ac92567.1980f.5b918b16@gitrepo.freebsd.org> The branch main has been updated by obiwac: URL: https://cgit.FreeBSD.org/src/commit/?id=02880ddf9ed01a4b3444239309f522309ef11043 commit 02880ddf9ed01a4b3444239309f522309ef11043 Author: Aymeric Wibo AuthorDate: 2025-04-29 20:42:56 +0000 Commit: Aymeric Wibo CommitDate: 2026-10-09 17:32:34 +0000 thunderbolt: Router suspend routine Suspend routine for USB4 v1.0 NHIs. This will work on v2.0 NHIs too for now, but there's ideally a different method we should be using for those in fine. Reviewed by: imp, ngie, emaste Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D49453 --- sys/dev/thunderbolt/nhi.c | 13 +++++++ sys/dev/thunderbolt/nhi_pci.c | 6 ++-- sys/dev/thunderbolt/nhi_reg.h | 5 +++ sys/dev/thunderbolt/nhi_var.h | 2 ++ sys/dev/thunderbolt/router.c | 78 ++++++++++++++++++++++++++++++++++++++++ sys/dev/thunderbolt/router_var.h | 11 ++++++ 6 files changed, 113 insertions(+), 2 deletions(-) diff --git a/sys/dev/thunderbolt/nhi.c b/sys/dev/thunderbolt/nhi.c index e8221136a8e5..a01a01cca92c 100644 --- a/sys/dev/thunderbolt/nhi.c +++ b/sys/dev/thunderbolt/nhi.c @@ -387,6 +387,19 @@ nhi_detach(struct nhi_softc *sc) return (0); } +int +nhi_suspend(struct nhi_softc *sc) +{ + return (tb_router_suspend(sc->root_rsc)); +} + +int +nhi_resume(struct nhi_softc *sc) +{ + /* TODO(Bug 299199): fully flesh out the implementation. */ + return (0); +} + static void nhi_memaddr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error) { diff --git a/sys/dev/thunderbolt/nhi_pci.c b/sys/dev/thunderbolt/nhi_pci.c index 777f8dd5352e..0ba452132523 100644 --- a/sys/dev/thunderbolt/nhi_pci.c +++ b/sys/dev/thunderbolt/nhi_pci.c @@ -178,15 +178,17 @@ nhi_pci_detach(device_t dev) static int nhi_pci_suspend(device_t dev) { + struct nhi_softc *sc = device_get_softc(dev); - return (0); + return (nhi_suspend(sc)); } static int nhi_pci_resume(device_t dev) { + struct nhi_softc *sc = device_get_softc(dev); - return (0); + return (nhi_resume(sc)); } static void diff --git a/sys/dev/thunderbolt/nhi_reg.h b/sys/dev/thunderbolt/nhi_reg.h index a0c13c741554..0adfeccd76b9 100644 --- a/sys/dev/thunderbolt/nhi_reg.h +++ b/sys/dev/thunderbolt/nhi_reg.h @@ -52,6 +52,11 @@ #define DEVICE_PINK_SARDINE_0 0x1668 #define DEVICE_PINK_SARDINE_1 0x1669 +/* Timings */ +#define NHI_SLPR_WAIT_US 50000 /* 50 ms, tSetSR */ +#define NHI_SLPR_POLL_TRIES 100 +#define NHI_SLPR_POLL_US (NHI_SLPR_WAIT_US / NHI_SLPR_POLL_TRIES) + /* * * MMIO Registers * * Ring buffer registers * diff --git a/sys/dev/thunderbolt/nhi_var.h b/sys/dev/thunderbolt/nhi_var.h index 6acac4ed0fa6..026bca7c99a0 100644 --- a/sys/dev/thunderbolt/nhi_var.h +++ b/sys/dev/thunderbolt/nhi_var.h @@ -210,6 +210,8 @@ int nhi_write_lc_mailbox(struct nhi_softc *, u_int reg, uint32_t val); void nhi_get_tunables(struct nhi_softc *); int nhi_attach(struct nhi_softc *); int nhi_detach(struct nhi_softc *); +int nhi_suspend(struct nhi_softc *); +int nhi_resume(struct nhi_softc *); struct nhi_cmd_frame * nhi_alloc_tx_frame(struct nhi_ring_pair *); void nhi_free_tx_frame(struct nhi_ring_pair *, struct nhi_cmd_frame *); diff --git a/sys/dev/thunderbolt/router.c b/sys/dev/thunderbolt/router.c index e35c712e4a00..c4141e22ed20 100644 --- a/sys/dev/thunderbolt/router.c +++ b/sys/dev/thunderbolt/router.c @@ -252,6 +252,7 @@ tb_router_attach_root(struct nhi_softc *nsc, tb_route_t route) sc->ring0 = nsc->ring0; sc->route = route; sc->nsc = nsc; + sc->suspended = false; mtx_init(&sc->mtx, "tbcfg", "Thunderbolt Router Config", MTX_DEF); TAILQ_INIT(&sc->cmd_queue); @@ -345,6 +346,83 @@ tb_router_detach(struct router_softc *sc) return (0); } +/* + * Suspend a USB4 router and it's downstreams. + * + * TODO(Bug 299199): fully flesh out the implementation. + */ +int +tb_router_suspend(struct router_softc *sc) +{ + int err; + uint32_t reg; + + tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "%s called\n", __func__); + if (sc->suspended) { + tb_debug(sc, DBG_ROUTER|DBG_EXTRA, "Already suspended\n"); + return (0); + } + + /* + * TODO Before we do anything, we've first got to make sure that the + * USB3 hub is in the U3 state, and the PCIe endpoint is in D3. + * + * Also check for "USB4 Port is Configured" to know if we support + * sleep state. + */ + + /* First, we've got to set ROUTER_CS_5.SLP (enter sleep). */ + err = tb_config_router_read(sc, ROUTER_CS_5, 1, ®); + if (err != 0) { + tb_debug(sc, DBG_ROUTER, "Cannot read ROUTER_CS5\n"); + return (err); + } + /* + * We want to set the enter sleep bit, as well as preventing wake + * events from: + * - Wake on PCIe (WoP). + * - Wake on USB3 (WoU). + * - Wake on DisplayPort (WoD). + * TODO Eventually, we will want the user to be able to control this. + */ + reg |= ROUTER_SLP; + reg &= ~(ROUTER_WOP | ROUTER_WOU | ROUTER_WOD); + err = tb_config_router_write(sc, ROUTER_CS_5, 1, ®); + if (err != 0) { + tb_debug(sc, DBG_ROUTER, "Cannot write to ROUTER_CS5\n"); + return (err); + } + + /* + * The ROUTER_CS_6.SLPR (sleep ready) bit should be set tSetSR after + * we set the SLP bit. Poll for it to be set. + * + * TODO On a v2 router, we should wait for the ROP_CMPLT notification, + * but in the meantime just polling is also valid. + */ + for (size_t i = 0; i < NHI_SLPR_POLL_TRIES; i++) { + pause_sbt("tbrouter", ustosbt(NHI_SLPR_POLL_US), 0, 0); + err = tb_config_router_read(sc, ROUTER_CS_6, 1, ®); + if (err != 0) { + tb_debug(sc, DBG_ROUTER, "Cannot read ROUTER_CS6\n"); + return (err); + } + if ((reg & ROUTER_SLPR) != 0) + goto ready; + } + tb_printf(sc, "Timed out waiting for the sleep ready bit to be set\n"); + return (ETIMEDOUT); + +ready: + tb_printf(sc, "Ready to enter sleep\n"); + sc->suspended = true; + /* + * TODO We must tell the host router to send LT_LRoff on the sideband + * channel of each DFP. + */ + return (0); +} + static void router_get_config_cb(struct router_softc *sc, struct router_command *cmd, void *arg) diff --git a/sys/dev/thunderbolt/router_var.h b/sys/dev/thunderbolt/router_var.h index a733c36d401e..7c86086974c2 100644 --- a/sys/dev/thunderbolt/router_var.h +++ b/sys/dev/thunderbolt/router_var.h @@ -59,6 +59,7 @@ struct router_softc { tb_route_t route; device_t dev; struct nhi_softc *nsc; + bool suspended; struct mtx mtx; struct nhi_ring_pair *ring0; @@ -89,9 +90,19 @@ struct router_cfg_cap { #define ROUTER_HRR 0x39898 #define ROUTER_HIR 0x39858 +/* Router config space registers */ +#define ROUTER_CS_5 5 +#define ROUTER_SLP (1<<0) /* Enter sleep (CS5). */ +#define ROUTER_WOP (1<<1) /* Wake on PCIe (CS5). */ +#define ROUTER_WOU (1<<2) /* Wake on USB3 (CS5). */ +#define ROUTER_WOD (1<<3) /* Wake on DP (CS5). */ +#define ROUTER_CS_6 6 +#define ROUTER_SLPR (1<<0) /* Sleep ready (CS6). */ + 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 *); +int tb_router_suspend(struct router_softc *); int tb_config_read(struct router_softc *, u_int, u_int, u_int, u_int, uint32_t *); int tb_config_read_polled(struct router_softc *, u_int, u_int, u_int, u_int,