Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F154961432
D49453.id152527.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D49453.id152527.diff
View Options
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, ®);
+ 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, ®);
+ 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, ®);
+ 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, ®);
+ 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
Details
Attached
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)
Attached To
Mode
D49453: USB4 initial work on suspend routine
Attached
Detach File
Event Timeline
Log In to Comment