Page MenuHomeFreeBSD

D49453.id152527.diff
No OneTemporary

D49453.id152527.diff

diff --git a/sys/dev/thunderbolt/nhi.c b/sys/dev/thunderbolt/nhi.c
--- a/sys/dev/thunderbolt/nhi.c
+++ b/sys/dev/thunderbolt/nhi.c
@@ -415,6 +415,20 @@
return (0);
}
+int
+nhi_suspend(struct nhi_softc *sc)
+{
+
+ return (tb_router_suspend(sc->root_rsc));
+}
+
+int
+nhi_resume(struct nhi_softc *sc)
+{
+
+ 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
--- a/sys/dev/thunderbolt/nhi_pci.c
+++ b/sys/dev/thunderbolt/nhi_pci.c
@@ -242,15 +242,17 @@
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
--- a/sys/dev/thunderbolt/nhi_reg.h
+++ b/sys/dev/thunderbolt/nhi_reg.h
@@ -58,14 +58,6 @@
#define NHI_SLPR_WAIT_US 50000 /* 50 ms, tSetSR */
#define NHI_SLPR_WAIT_MAX 100
-/* Router config space registers */
-#define NHI_HRR 0x39898
-#define NHI_HIR 0x39858
-#define ROUTER_CS5 5
-#define NHI_SLP 1 /* Enter sleep (CS5). */
-#define ROUTER_CS6 6
-#define NHI_SLPR 1 /* Sleep ready (CS6). */
-
/* * * MMIO Registers
* * Ring buffer registers
*
diff --git a/sys/dev/thunderbolt/nhi_var.h b/sys/dev/thunderbolt/nhi_var.h
--- a/sys/dev/thunderbolt/nhi_var.h
+++ b/sys/dev/thunderbolt/nhi_var.h
@@ -229,6 +229,8 @@
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
--- a/sys/dev/thunderbolt/router.c
+++ b/sys/dev/thunderbolt/router.c
@@ -253,6 +253,7 @@
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);
@@ -344,6 +345,90 @@
return (0);
}
+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, &reg);
+ 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).
+ */
+ reg |= ROUTER_SLP;
+ reg &= ~(ROUTER_WOP | ROUTER_WOU | ROUTER_WOD);
+ err = tb_config_router_write(sc, ROUTER_CS_5, 1, &reg);
+ 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.
+ */
+ pause_sbt("tbrouter", ustosbt(NHI_SLPR_WAIT_US), 0, C_HARDCLOCK);
+ err = tb_config_router_read(sc, ROUTER_CS_6, 1, &reg);
+ 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, "Sleep ready bit not set after 50 ms after "
+ "asking to enter sleep, waiting...\n");
+ for (size_t i = 0; i < NHI_SLPR_WAIT_MAX; i++) {
+ pause_sbt("tbrouter", ustosbt(NHI_SLPR_WAIT_US), 0,
+ C_HARDCLOCK);
+ err = tb_config_router_read(sc, ROUTER_CS_6, 1, &reg);
+ 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. (I thought we weren't allowed to send anything
+ * on the sideband channel after setting the sleep entry bit?)
+ */
+ 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
--- a/sys/dev/thunderbolt/router_var.h
+++ b/sys/dev/thunderbolt/router_var.h
@@ -61,6 +61,7 @@
tb_route_t route;
device_t dev;
struct nhi_softc *nsc;
+ bool suspended;
struct mtx mtx;
struct nhi_ring_pair *ring0;
@@ -87,9 +88,21 @@
uint16_t vsec_len;
};
+/* Router config space registers */
+#define ROUTER_HRR 0x39898
+#define ROUTER_HIR 0x39858
+#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,

File Metadata

Mime Type
text/plain
Expires
Fri, May 1, 8:23 AM (15 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32565625
Default Alt Text
D49453.id152527.diff (5 KB)

Event Timeline