summaryrefslogtreecommitdiff
path: root/drivers/thunderbolt/tb.c
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2022-01-07 14:00:47 +0300
committerMika Westerberg <mika.westerberg@linux.intel.com>2022-02-02 13:56:51 +0300
commit30a4eca69b76c0ed5a2f34dd2a3e195c9bf6bed1 (patch)
tree00596d61cefc48c5f5ad681f822bb0f9a143708b /drivers/thunderbolt/tb.c
parentf1d5ec3e0eabaf961ed16516bf35e24b48cda483 (diff)
downloadlinux-30a4eca69b76c0ed5a2f34dd2a3e195c9bf6bed1.tar.xz
thunderbolt: Add internal xHCI connect flows for Thunderbolt 3 devices
Both Alpine Ridge and Titan Ridge require special flows in order to activate the internal xHCI controller when there is USB device connected to the downstream type-C port. This implements the missing flows for both. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/thunderbolt/tb.c')
-rw-r--r--drivers/thunderbolt/tb.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index cbd0ad85ffb1..9beb47b31c75 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -1054,6 +1054,8 @@ static int tb_disconnect_pci(struct tb *tb, struct tb_switch *sw)
if (WARN_ON(!tunnel))
return -ENODEV;
+ tb_switch_xhci_disconnect(sw);
+
tb_tunnel_deactivate(tunnel);
list_del(&tunnel->list);
tb_tunnel_free(tunnel);
@@ -1099,6 +1101,9 @@ static int tb_tunnel_pci(struct tb *tb, struct tb_switch *sw)
if (tb_switch_pcie_l1_enable(sw))
tb_sw_warn(sw, "failed to enable PCIe L1 for Titan Ridge\n");
+ if (tb_switch_xhci_connect(sw))
+ tb_sw_warn(sw, "failed to connect xHCI\n");
+
list_add_tail(&tunnel->list, &tcm->tunnel_list);
return 0;
}
@@ -1256,12 +1261,18 @@ static void tb_handle_hotplug(struct work_struct *work)
tb_port_unconfigure_xdomain(port);
} else if (tb_port_is_dpout(port) || tb_port_is_dpin(port)) {
tb_dp_resource_unavailable(tb, port);
+ } else if (!port->port) {
+ tb_sw_dbg(sw, "xHCI disconnect request\n");
+ tb_switch_xhci_disconnect(sw);
} else {
tb_port_dbg(port,
"got unplug event for disconnected port, ignoring\n");
}
} else if (port->remote) {
tb_port_dbg(port, "got plug event for connected port, ignoring\n");
+ } else if (!port->port && sw->authorized) {
+ tb_sw_dbg(sw, "xHCI connect request\n");
+ tb_switch_xhci_connect(sw);
} else {
if (tb_port_is_null(port)) {
tb_port_dbg(port, "hotplug: scanning\n");