diff options
author | Mika Westerberg <mika.westerberg@linux.intel.com> | 2017-02-19 23:43:26 +0200 |
---|---|---|
committer | Mika Westerberg <mika.westerberg@linux.intel.com> | 2019-04-18 11:18:53 +0300 |
commit | 0414bec5f39a3c73fa56474b1bcd899101c2727d (patch) | |
tree | e1a9715e38db40ea9b783be0129959f09b7f6311 /drivers/thunderbolt/tb.c | |
parent | aae9e27f3b72ed58d6b87c8f511e7812601a93c5 (diff) | |
download | linux-0414bec5f39a3c73fa56474b1bcd899101c2727d.tar.bz2 |
thunderbolt: Discover preboot PCIe paths the boot firmware established
In Apple Macs the boot firmware (EFI) connects all devices automatically
when the system is started, before it hands over to the OS. Instead of
ignoring we discover all those PCIe tunnels and record them using our
internal structures, just like we do when a device is connected after
the OS is already up.
By doing this we can properly tear down tunnels when devices are
disconnected. Also this allows us to resume the existing tunnels after
system suspend/resume cycle.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/thunderbolt/tb.c')
-rw-r--r-- | drivers/thunderbolt/tb.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index 0485f4ef9a62..a62695a99835 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -29,6 +29,43 @@ struct tb_cm { /* enumeration & hot plug handling */ +static void tb_discover_tunnels(struct tb_switch *sw) +{ + struct tb *tb = sw->tb; + struct tb_cm *tcm = tb_priv(tb); + struct tb_port *port; + int i; + + for (i = 1; i <= sw->config.max_port_number; i++) { + struct tb_tunnel *tunnel = NULL; + + port = &sw->ports[i]; + switch (port->config.type) { + case TB_TYPE_PCIE_DOWN: + tunnel = tb_tunnel_discover_pci(tb, port); + break; + + default: + break; + } + + if (tunnel) { + struct tb_switch *parent = tunnel->dst_port->sw; + + while (parent != tunnel->src_port->sw) { + parent->boot = true; + parent = tb_switch_parent(parent); + } + + list_add_tail(&tunnel->list, &tcm->tunnel_list); + } + } + + for (i = 1; i <= sw->config.max_port_number; i++) { + if (tb_port_has_remote(&sw->ports[i])) + tb_discover_tunnels(sw->ports[i].remote->sw); + } +} static void tb_scan_port(struct tb_port *port); @@ -408,6 +445,8 @@ static int tb_start(struct tb *tb) /* Full scan to discover devices added before the driver was loaded. */ tb_scan_switch(tb->root_switch); + /* Find out tunnels created by the boot firmware */ + tb_discover_tunnels(tb->root_switch); tb_activate_pcie_devices(tb); /* Allow tb_handle_hotplug to progress events */ |