summaryrefslogtreecommitdiff
path: root/drivers/thunderbolt/switch.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/thunderbolt/switch.c')
-rw-r--r--drivers/thunderbolt/switch.c77
1 files changed, 37 insertions, 40 deletions
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index c2ad58b19e7b..a830c82bb905 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -209,30 +209,6 @@ static int nvm_authenticate_device_dma_port(struct tb_switch *sw)
return -ETIMEDOUT;
}
-static void nvm_authenticate_start_dma_port(struct tb_switch *sw)
-{
- struct pci_dev *root_port;
-
- /*
- * During host router NVM upgrade we should not allow root port to
- * go into D3cold because some root ports cannot trigger PME
- * itself. To be on the safe side keep the root port in D0 during
- * the whole upgrade process.
- */
- root_port = pcie_find_root_port(sw->tb->nhi->pdev);
- if (root_port)
- pm_runtime_get_noresume(&root_port->dev);
-}
-
-static void nvm_authenticate_complete_dma_port(struct tb_switch *sw)
-{
- struct pci_dev *root_port;
-
- root_port = pcie_find_root_port(sw->tb->nhi->pdev);
- if (root_port)
- pm_runtime_put(&root_port->dev);
-}
-
static inline bool nvm_readable(struct tb_switch *sw)
{
if (tb_switch_is_usb4(sw)) {
@@ -258,6 +234,7 @@ static inline bool nvm_upgradeable(struct tb_switch *sw)
static int nvm_authenticate(struct tb_switch *sw, bool auth_only)
{
+ struct tb_nhi *nhi = sw->tb->nhi;
int ret;
if (tb_switch_is_usb4(sw)) {
@@ -274,7 +251,8 @@ static int nvm_authenticate(struct tb_switch *sw, bool auth_only)
sw->nvm->authenticating = true;
if (!tb_route(sw)) {
- nvm_authenticate_start_dma_port(sw);
+ if (nhi->ops->pre_nvm_auth)
+ nhi->ops->pre_nvm_auth(nhi);
ret = nvm_authenticate_host_dma_port(sw);
} else {
ret = nvm_authenticate_device_dma_port(sw);
@@ -1620,6 +1598,12 @@ static int tb_switch_reset_host(struct tb_switch *sw)
ret = tb_port_reset(port);
if (ret)
return ret;
+ /*
+ * USB4 Lane 1 adapters do not have accessible
+ * path config space.
+ */
+ if (tb_switch_is_usb4(sw) && !port->usb4)
+ continue;
} else if (tb_port_is_usb3_down(port) ||
tb_port_is_usb3_up(port)) {
tb_usb3_port_enable(port, false);
@@ -1761,8 +1745,6 @@ int tb_switch_wait_for_bit(struct tb_switch *sw, u32 offset, u32 bit,
/*
* tb_plug_events_active() - enable/disable plug events on a switch
*
- * Also configures a sane plug_events_delay of 255ms.
- *
* Return: %0 on success, negative errno otherwise.
*/
static int tb_plug_events_active(struct tb_switch *sw, bool active)
@@ -1773,11 +1755,6 @@ static int tb_plug_events_active(struct tb_switch *sw, bool active)
if (tb_switch_is_icm(sw) || tb_switch_is_usb4(sw))
return 0;
- sw->config.plug_events_delay = 0xff;
- res = tb_sw_write(sw, ((u32 *) &sw->config) + 4, TB_CFG_SWITCH, 4, 1);
- if (res)
- return res;
-
res = tb_sw_read(sw, &data, TB_CFG_SWITCH, sw->cap_plug_events + 1, 1);
if (res)
return res;
@@ -2639,6 +2616,8 @@ int tb_switch_configure(struct tb_switch *sw)
sw->config.enabled = 1;
+ /* Set Notification Timeout to 255 ms for all routers */
+ sw->config.plug_events_delay = 0xff;
if (tb_switch_is_usb4(sw)) {
/*
* For USB4 devices, we need to program the CM version
@@ -2650,7 +2629,6 @@ int tb_switch_configure(struct tb_switch *sw)
sw->config.cmuv = ROUTER_CS_4_CMUV_V1;
else
sw->config.cmuv = ROUTER_CS_4_CMUV_V2;
- sw->config.plug_events_delay = 0xa;
/* Enumerate the switch */
ret = tb_sw_write(sw, (u32 *)&sw->config + 1, TB_CFG_SWITCH,
@@ -2671,7 +2649,7 @@ int tb_switch_configure(struct tb_switch *sw)
/* Enumerate the switch */
ret = tb_sw_write(sw, (u32 *)&sw->config + 1, TB_CFG_SWITCH,
- ROUTER_CS_1, 3);
+ ROUTER_CS_1, 4);
}
if (ret)
return ret;
@@ -2743,6 +2721,7 @@ static int tb_switch_set_uuid(struct tb_switch *sw)
static int tb_switch_add_dma_port(struct tb_switch *sw)
{
+ struct tb_nhi *nhi = sw->tb->nhi;
u32 status;
int ret;
@@ -2802,8 +2781,10 @@ static int tb_switch_add_dma_port(struct tb_switch *sw)
*/
nvm_get_auth_status(sw, &status);
if (status) {
- if (!tb_route(sw))
- nvm_authenticate_complete_dma_port(sw);
+ if (!tb_route(sw)) {
+ if (nhi->ops->post_nvm_auth)
+ nhi->ops->post_nvm_auth(nhi);
+ }
return 0;
}
@@ -2817,8 +2798,10 @@ static int tb_switch_add_dma_port(struct tb_switch *sw)
return ret;
/* Now we can allow root port to suspend again */
- if (!tb_route(sw))
- nvm_authenticate_complete_dma_port(sw);
+ if (!tb_route(sw)) {
+ if (nhi->ops->post_nvm_auth)
+ nhi->ops->post_nvm_auth(nhi);
+ }
if (status) {
tb_sw_info(sw, "switch flash authentication failed\n");
@@ -2971,14 +2954,14 @@ static int tb_switch_lane_bonding_enable(struct tb_switch *sw)
int ret;
if (!tb_switch_lane_bonding_possible(sw))
- return 0;
+ return -EOPNOTSUPP;
up = tb_upstream_port(sw);
down = tb_switch_downstream_port(sw);
if (!tb_port_width_supported(up, TB_LINK_WIDTH_DUAL) ||
!tb_port_width_supported(down, TB_LINK_WIDTH_DUAL))
- return 0;
+ return -EOPNOTSUPP;
/*
* Both lanes need to be in CL0. Here we assume lane 0 already be in
@@ -3625,6 +3608,20 @@ int tb_switch_resume(struct tb_switch *sw, bool runtime)
tb_port_warn(port,
"lost during suspend, disconnecting\n");
tb_sw_set_unplugged(port->remote->sw);
+ } else if (port->xdomain) {
+ /*
+ * If the user replaced the XDomain with
+ * another router, this will succeed in
+ * which case we must remove the XDomain
+ * before adding the new router.
+ */
+ err = tb_cfg_get_upstream_port(sw->tb->ctl,
+ port->xdomain->route);
+ if (err > 0) {
+ tb_port_warn(port,
+ "XDomain was disconnected\n");
+ port->xdomain->is_unplugged = true;
+ }
}
}
}