summaryrefslogtreecommitdiff
path: root/drivers/thunderbolt/switch.c
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2019-12-06 18:36:07 +0200
committerMika Westerberg <mika.westerberg@linux.intel.com>2020-09-03 12:06:42 +0300
commitb2911a593a705e54adde6d06d4657c1ff2f16583 (patch)
tree41b38ef2522fa43490f3ddaaaf7ee73cda916268 /drivers/thunderbolt/switch.c
parent341d45188a7800ae3bc18558d62020787b78397e (diff)
thunderbolt: Enable wakes from system suspend
In order for the router and the whole domain to wake up from system suspend states we need to enable wakes for the connected routers. For device routers we enable wakes from PCIe and USB 3.x. This allows devices such as keyboards connected to USB 3.x hub that is tunneled to wake the system up as expected. For all routers we enabled wake on USB4 for each connected ports. This is used to propagate the wake from router to another. Do the same for legacy routers through link controller vendor specific registers as documented in USB4 spec chapter 13. While there correct kernel-doc of usb4_switch_set_sleep() -- it does not enable wakes instead there is a separate function (usb4_switch_set_wake()) that does. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/thunderbolt/switch.c')
-rw-r--r--drivers/thunderbolt/switch.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index 37a81206636f..df119a87ee75 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -2035,7 +2035,7 @@ int tb_switch_configure(struct tb_switch *sw)
route = tb_route(sw);
tb_dbg(tb, "%s Switch at %#llx (depth: %d, up port: %d)\n",
- sw->config.enabled ? "restoring " : "initializing", route,
+ sw->config.enabled ? "restoring" : "initializing", route,
tb_route_length(route), sw->config.upstream_port_number);
sw->config.enabled = 1;
@@ -2501,6 +2501,13 @@ int tb_switch_add(struct tb_switch *sw)
return ret;
}
+ /*
+ * Thunderbolt routers do not generate wakeups themselves but
+ * they forward wakeups from tunneled protocols, so enable it
+ * here.
+ */
+ device_init_wakeup(&sw->dev, true);
+
pm_runtime_set_active(&sw->dev);
if (sw->rpm) {
pm_runtime_set_autosuspend_delay(&sw->dev, TB_AUTOSUSPEND_DELAY);
@@ -2578,6 +2585,18 @@ void tb_sw_set_unplugged(struct tb_switch *sw)
}
}
+static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags)
+{
+ if (flags)
+ tb_sw_dbg(sw, "enabling wakeup: %#x\n", flags);
+ else
+ tb_sw_dbg(sw, "disabling wakeup\n");
+
+ if (tb_switch_is_usb4(sw))
+ return usb4_switch_set_wake(sw, flags);
+ return tb_lc_set_wake(sw, flags);
+}
+
int tb_switch_resume(struct tb_switch *sw)
{
struct tb_port *port;
@@ -2623,6 +2642,9 @@ int tb_switch_resume(struct tb_switch *sw)
if (err)
return err;
+ /* Disable wakes */
+ tb_switch_set_wake(sw, 0);
+
err = tb_switch_tmu_init(sw);
if (err)
return err;
@@ -2658,6 +2680,7 @@ int tb_switch_resume(struct tb_switch *sw)
void tb_switch_suspend(struct tb_switch *sw)
{
+ unsigned int flags = 0;
struct tb_port *port;
int err;
@@ -2670,6 +2693,11 @@ void tb_switch_suspend(struct tb_switch *sw)
tb_switch_suspend(port->remote->sw);
}
+ if (device_may_wakeup(&sw->dev))
+ flags = TB_WAKE_ON_USB4 | TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE;
+
+ tb_switch_set_wake(sw, flags);
+
if (tb_switch_is_usb4(sw))
usb4_switch_set_sleep(sw);
else