in tb.c [579:695]
static void tb_scan_port(struct tb_port *port)
{
struct tb_cm *tcm = tb_priv(port->sw->tb);
struct tb_port *upstream_port;
struct tb_switch *sw;
if (tb_is_upstream_port(port))
return;
if (tb_port_is_dpout(port) && tb_dp_port_hpd_is_active(port) == 1 &&
!tb_dp_port_is_enabled(port)) {
tb_port_dbg(port, "DP adapter HPD set, queuing hotplug\n");
tb_queue_hotplug(port->sw->tb, tb_route(port->sw), port->port,
false);
return;
}
if (port->config.type != TB_TYPE_PORT)
return;
if (port->dual_link_port && port->link_nr)
return; /*
* Downstream switch is reachable through two ports.
* Only scan on the primary port (link_nr == 0).
*/
if (tb_wait_for_port(port, false) <= 0)
return;
if (port->remote) {
tb_port_dbg(port, "port already has a remote\n");
return;
}
tb_retimer_scan(port, true);
sw = tb_switch_alloc(port->sw->tb, &port->sw->dev,
tb_downstream_route(port));
if (IS_ERR(sw)) {
/*
* If there is an error accessing the connected switch
* it may be connected to another domain. Also we allow
* the other domain to be connected to a max depth switch.
*/
if (PTR_ERR(sw) == -EIO || PTR_ERR(sw) == -EADDRNOTAVAIL)
tb_scan_xdomain(port);
return;
}
if (tb_switch_configure(sw)) {
tb_switch_put(sw);
return;
}
/*
* If there was previously another domain connected remove it
* first.
*/
if (port->xdomain) {
tb_xdomain_remove(port->xdomain);
tb_port_unconfigure_xdomain(port);
port->xdomain = NULL;
}
/*
* Do not send uevents until we have discovered all existing
* tunnels and know which switches were authorized already by
* the boot firmware.
*/
if (!tcm->hotplug_active)
dev_set_uevent_suppress(&sw->dev, true);
/*
* At the moment Thunderbolt 2 and beyond (devices with LC) we
* can support runtime PM.
*/
sw->rpm = sw->generation > 1;
if (tb_switch_add(sw)) {
tb_switch_put(sw);
return;
}
/* Link the switches using both links if available */
upstream_port = tb_upstream_port(sw);
port->remote = upstream_port;
upstream_port->remote = port;
if (port->dual_link_port && upstream_port->dual_link_port) {
port->dual_link_port->remote = upstream_port->dual_link_port;
upstream_port->dual_link_port->remote = port->dual_link_port;
}
/* Enable lane bonding if supported */
tb_switch_lane_bonding_enable(sw);
/* Set the link configured */
tb_switch_configure_link(sw);
if (tb_switch_enable_clx(sw, TB_CL0S))
tb_sw_warn(sw, "failed to enable CLx on upstream port\n");
tb_switch_tmu_configure(sw, TB_SWITCH_TMU_RATE_HIFI,
tb_switch_is_clx_enabled(sw));
if (tb_enable_tmu(sw))
tb_sw_warn(sw, "failed to enable TMU\n");
/* Scan upstream retimers */
tb_retimer_scan(upstream_port, true);
/*
* Create USB 3.x tunnels only when the switch is plugged to the
* domain. This is because we scan the domain also during discovery
* and want to discover existing USB 3.x tunnels before we create
* any new.
*/
if (tcm->hotplug_active && tb_tunnel_usb3(sw->tb, sw))
tb_sw_warn(sw, "USB3 tunnel creation failed\n");
tb_add_dp_resources(sw);
tb_scan_switch(sw);
}