summaryrefslogtreecommitdiff
path: root/drivers/thunderbolt/switch.c
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2018-09-28 16:41:01 +0300
committerMika Westerberg <mika.westerberg@linux.intel.com>2019-04-18 11:18:53 +0300
commit7ea4cd6b2010eecccf37ac3953ac8ecd3688300f (patch)
tree2ad9923d6af59ba375a936cd46928052ead16c6d /drivers/thunderbolt/switch.c
parent444ac3844895c34ab71ffcec1b3199449d3434a4 (diff)
thunderbolt: Add support for XDomain connections
Two domains (hosts) can be connected through a Thunderbolt cable and in that case they can start software services such as networking over the high-speed DMA paths. Now that we have all the basic building blocks in place to create DMA tunnels over the Thunderbolt fabric we can add this support to the software connection manager as well. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/thunderbolt/switch.c')
-rw-r--r--drivers/thunderbolt/switch.c29
1 files changed, 25 insertions, 4 deletions
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index 460f2bcad40a..a5345a6225bd 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -1845,6 +1845,8 @@ void tb_sw_set_unplugged(struct tb_switch *sw)
for (i = 0; i <= sw->config.max_port_number; i++) {
if (tb_port_has_remote(&sw->ports[i]))
tb_sw_set_unplugged(sw->ports[i].remote->sw);
+ else if (sw->ports[i].xdomain)
+ sw->ports[i].xdomain->is_unplugged = true;
}
}
@@ -1860,6 +1862,17 @@ int tb_switch_resume(struct tb_switch *sw)
if (tb_route(sw)) {
u64 uid;
+ /*
+ * Check first that we can still read the switch config
+ * space. It may be that there is now another domain
+ * connected.
+ */
+ err = tb_cfg_get_upstream_port(sw->tb->ctl, tb_route(sw));
+ if (err < 0) {
+ tb_sw_info(sw, "switch not present anymore\n");
+ return err;
+ }
+
err = tb_drom_read_uid_only(sw, &uid);
if (err) {
tb_sw_warn(sw, "uid read failed\n");
@@ -1890,14 +1903,22 @@ int tb_switch_resume(struct tb_switch *sw)
for (i = 1; i <= sw->config.max_port_number; i++) {
struct tb_port *port = &sw->ports[i];
- if (!tb_port_has_remote(port))
+ if (!tb_port_has_remote(port) && !port->xdomain)
continue;
- if (tb_wait_for_port(port, true) <= 0
- || tb_switch_resume(port->remote->sw)) {
+ if (tb_wait_for_port(port, true) <= 0) {
tb_port_warn(port,
"lost during suspend, disconnecting\n");
- tb_sw_set_unplugged(port->remote->sw);
+ if (tb_port_has_remote(port))
+ tb_sw_set_unplugged(port->remote->sw);
+ else if (port->xdomain)
+ port->xdomain->is_unplugged = true;
+ } else if (tb_port_has_remote(port)) {
+ if (tb_switch_resume(port->remote->sw)) {
+ tb_port_warn(port,
+ "lost during suspend, disconnecting\n");
+ tb_sw_set_unplugged(port->remote->sw);
+ }
}
}
return 0;