summaryrefslogtreecommitdiffstats
path: root/drivers/thunderbolt/tb.c
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2020-05-16 15:20:39 +0200
committerMika Westerberg <mika.westerberg@linux.intel.com>2020-09-03 11:06:41 +0200
commit81a2e3e49f1f89cfe30d354b3a5fba27e2e59d91 (patch)
tree28fcc893902ff69d09bdd1679d49fd569352f950 /drivers/thunderbolt/tb.c
parentthunderbolt: Send reset only to first generation routers (diff)
downloadlinux-81a2e3e49f1f89cfe30d354b3a5fba27e2e59d91.tar.xz
linux-81a2e3e49f1f89cfe30d354b3a5fba27e2e59d91.zip
thunderbolt: Tear down DP tunnels when suspending
DP tunnels do not need the same kind of treatment as others because they are created based on hot-plug events on DP adapter ports, and the display stack does not need the tunnels to be enabled when resuming from suspend. Also Tiger Lake Thunderbolt controller sends unplug event on D3 exit so this avoids that as well. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/thunderbolt/tb.c')
-rw-r--r--drivers/thunderbolt/tb.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index a6da2d0567ae..c35d5fec48f4 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -910,6 +910,29 @@ static void tb_dp_resource_available(struct tb *tb, struct tb_port *port)
tb_tunnel_dp(tb);
}
+static void tb_disconnect_and_release_dp(struct tb *tb)
+{
+ struct tb_cm *tcm = tb_priv(tb);
+ struct tb_tunnel *tunnel, *n;
+
+ /*
+ * Tear down all DP tunnels and release their resources. They
+ * will be re-established after resume based on plug events.
+ */
+ list_for_each_entry_safe_reverse(tunnel, n, &tcm->tunnel_list, list) {
+ if (tb_tunnel_is_dp(tunnel))
+ tb_deactivate_and_free_tunnel(tunnel);
+ }
+
+ while (!list_empty(&tcm->dp_resources)) {
+ struct tb_port *port;
+
+ port = list_first_entry(&tcm->dp_resources,
+ struct tb_port, list);
+ list_del_init(&port->list);
+ }
+}
+
static int tb_tunnel_pci(struct tb *tb, struct tb_switch *sw)
{
struct tb_port *up, *down, *port;
@@ -1226,6 +1249,7 @@ static int tb_suspend_noirq(struct tb *tb)
struct tb_cm *tcm = tb_priv(tb);
tb_dbg(tb, "suspending...\n");
+ tb_disconnect_and_release_dp(tb);
tb_switch_suspend(tb->root_switch);
tcm->hotplug_active = false; /* signal tb_handle_hotplug to quit */
tb_dbg(tb, "suspend finished\n");