thunderbolt: Add support for retimer NVM upgrade when there is no link
With help from platform firmware (ACPI) it is possible to power on retimers even when there is no USB4 link (e.g nothing is connected to the USB4 ports). This allows us to bring the USB4 sideband up so that we can access retimers and upgrade their NVM firmware. If the platform has support for this, we expose two additional attributes under USB4 ports: offline and rescan. These can be used to bring the port offline, rescan for the retimers and put the port online again. The retimer NVM upgrade itself works the same way than with cable connected. Signed-off-by: Rajmohan Mani <rajmohan.mani@intel.com> Co-developed-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Mika Westerberg
parent
3406de7cc2
commit
3fb10ea4ce
@@ -1153,6 +1153,33 @@ static int tb_port_start_lane_initialization(struct tb_port *port)
|
||||
return ret == -EINVAL ? 0 : ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the port had something (router, XDomain) connected
|
||||
* before suspend.
|
||||
*/
|
||||
static bool tb_port_resume(struct tb_port *port)
|
||||
{
|
||||
bool has_remote = tb_port_has_remote(port);
|
||||
|
||||
if (port->usb4) {
|
||||
usb4_port_device_resume(port->usb4);
|
||||
} else if (!has_remote) {
|
||||
/*
|
||||
* For disconnected downstream lane adapters start lane
|
||||
* initialization now so we detect future connects.
|
||||
*
|
||||
* For XDomain start the lane initialzation now so the
|
||||
* link gets re-established.
|
||||
*
|
||||
* This is only needed for non-USB4 ports.
|
||||
*/
|
||||
if (!tb_is_upstream_port(port) || port->xdomain)
|
||||
tb_port_start_lane_initialization(port);
|
||||
}
|
||||
|
||||
return has_remote || port->xdomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* tb_port_is_enabled() - Is the adapter port enabled
|
||||
* @port: Port to check
|
||||
@@ -2915,22 +2942,11 @@ int tb_switch_resume(struct tb_switch *sw)
|
||||
|
||||
/* check for surviving downstream switches */
|
||||
tb_switch_for_each_port(sw, port) {
|
||||
if (!tb_port_has_remote(port) && !port->xdomain) {
|
||||
/*
|
||||
* For disconnected downstream lane adapters
|
||||
* start lane initialization now so we detect
|
||||
* future connects.
|
||||
*/
|
||||
if (!tb_is_upstream_port(port) && tb_port_is_null(port))
|
||||
tb_port_start_lane_initialization(port);
|
||||
if (!tb_port_is_null(port))
|
||||
continue;
|
||||
|
||||
if (!tb_port_resume(port))
|
||||
continue;
|
||||
} else if (port->xdomain) {
|
||||
/*
|
||||
* Start lane initialization for XDomain so the
|
||||
* link gets re-established.
|
||||
*/
|
||||
tb_port_start_lane_initialization(port);
|
||||
}
|
||||
|
||||
if (tb_wait_for_port(port, true) <= 0) {
|
||||
tb_port_warn(port,
|
||||
@@ -2939,7 +2955,7 @@ int tb_switch_resume(struct tb_switch *sw)
|
||||
tb_sw_set_unplugged(port->remote->sw);
|
||||
else if (port->xdomain)
|
||||
port->xdomain->is_unplugged = true;
|
||||
} else if (tb_port_has_remote(port) || port->xdomain) {
|
||||
} else {
|
||||
/*
|
||||
* Always unlock the port so the downstream
|
||||
* switch/domain is accessible.
|
||||
|
||||
Reference in New Issue
Block a user