summaryrefslogtreecommitdiff
path: root/drivers/thunderbolt/switch.c
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2020-06-05 14:25:02 +0300
committerMika Westerberg <mika.westerberg@linux.intel.com>2020-09-03 12:06:42 +0300
commit6ac6faee5d7d7d1676a3188286438bed2dadd863 (patch)
treede96d3a7dfe352709d20b4f18ef3acd3dc103a7b /drivers/thunderbolt/switch.c
parentb2be2b05cf3b1c7b499d3b05decdcc524879fea7 (diff)
thunderbolt: Add runtime PM for Software CM
This adds runtime PM support for the Software Connection Manager parts of the driver. This allows to save power when either there is no device attached at all or there is a device attached and all following conditions are true: - Tunneled PCIe root/downstream ports are runtime suspended - Tunneled USB3 ports are runtime suspended - No active DisplayPort stream - No active XDomain connection For the first two we take advantage of device links that were added in previous patch. Difference for the system sleep case is that we also enable wakes when something is geting plugged in/out of the Thunderbolt ports. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/thunderbolt/switch.c')
-rw-r--r--drivers/thunderbolt/switch.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index df119a87ee75..d3c54020a5be 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -2678,23 +2678,40 @@ int tb_switch_resume(struct tb_switch *sw)
return 0;
}
-void tb_switch_suspend(struct tb_switch *sw)
+/**
+ * tb_switch_suspend() - Put a switch to sleep
+ * @sw: Switch to suspend
+ * @runtime: Is this runtime suspend or system sleep
+ *
+ * Suspends router and all its children. Enables wakes according to
+ * value of @runtime and then sets sleep bit for the router. If @sw is
+ * host router the domain is ready to go to sleep once this function
+ * returns.
+ */
+void tb_switch_suspend(struct tb_switch *sw, bool runtime)
{
unsigned int flags = 0;
struct tb_port *port;
int err;
+ tb_sw_dbg(sw, "suspending switch\n");
+
err = tb_plug_events_active(sw, false);
if (err)
return;
tb_switch_for_each_port(sw, port) {
if (tb_port_has_remote(port))
- tb_switch_suspend(port->remote->sw);
+ tb_switch_suspend(port->remote->sw, runtime);
}
- if (device_may_wakeup(&sw->dev))
- flags = TB_WAKE_ON_USB4 | TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE;
+ if (runtime) {
+ /* Trigger wake when something is plugged in/out */
+ flags |= TB_WAKE_ON_CONNECT | TB_WAKE_ON_DISCONNECT;
+ flags |= TB_WAKE_ON_USB4 | TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE;
+ } else 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);