summaryrefslogtreecommitdiff
path: root/drivers/thunderbolt/tb.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-04-13 13:17:14 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-04-13 13:17:14 +0300
commit5367f82a212305c35b35303a8a21ca348f653ca3 (patch)
tree98e88cbd6f40762b11802624022eaccf08051c39 /drivers/thunderbolt/tb.c
parent9bc46a12c53d8268392774172742aa9e5dd6953d (diff)
parent6f3badead6a078cf3c71f381f9d84ac922984a00 (diff)
downloadlinux-5367f82a212305c35b35303a8a21ca348f653ca3.tar.xz
Merge tag 'thunderbolt-for-v5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt into usb-next
Mika writes: thunderbolt: Changes for v5.13 merge window This includes following Thunderbolt/USB4 changes for v5.13 merge window: * Debugfs improvements * Align the inter-domain (peer-to-peer) support with the USB4 inter-domain spec for better interoperability * Add support for USB4 DROM and the new product descriptor * More KUnit tests * Detailed uevent for routers * Few miscellaneous improvements All these have been in linux-next without reported issues. * tag 'thunderbolt-for-v5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt: (24 commits) thunderbolt: Hide authorized attribute if router does not support PCIe tunnels thunderbolt: Add details to router uevent thunderbolt: Unlock on error path in tb_domain_add() thunderbolt: Add support for USB4 DROM thunderbolt: Check quirks in tb_switch_add() thunderbolt: Add KUnit tests for DMA tunnels thunderbolt: Add KUnit tests for XDomain properties net: thunderbolt: Align the driver to the USB4 networking spec thunderbolt: Allow multiple DMA tunnels over a single XDomain connection thunderbolt: Drop unused tb_port_set_initial_credits() thunderbolt: Use dedicated flow control for DMA tunnels thunderbolt: Add support for maxhopid XDomain property thunderbolt: Add tb_property_copy_dir() thunderbolt: Align XDomain protocol timeouts with the spec thunderbolt: Use pseudo-random number as initial property block generation thunderbolt: Do not re-establish XDomain DMA paths automatically thunderbolt: Add more logging to XDomain connections Documentation / thunderbolt: Drop speed/lanes entries for XDomain thunderbolt: Decrease control channel timeout for software connection manager thunderbolt: Do not pass timeout for tb_cfg_reset() ...
Diffstat (limited to 'drivers/thunderbolt/tb.c')
-rw-r--r--drivers/thunderbolt/tb.c52
1 files changed, 33 insertions, 19 deletions
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index c348b1fc0efc..7e6dc2b03bed 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -15,6 +15,8 @@
#include "tb_regs.h"
#include "tunnel.h"
+#define TB_TIMEOUT 100 /* ms */
+
/**
* struct tb_cm - Simple Thunderbolt connection manager
* @tunnel_list: List of active tunnels
@@ -1077,7 +1079,9 @@ static int tb_tunnel_pci(struct tb *tb, struct tb_switch *sw)
return 0;
}
-static int tb_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd)
+static int tb_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd,
+ int transmit_path, int transmit_ring,
+ int receive_path, int receive_ring)
{
struct tb_cm *tcm = tb_priv(tb);
struct tb_port *nhi_port, *dst_port;
@@ -1089,9 +1093,8 @@ static int tb_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd)
nhi_port = tb_switch_find_port(tb->root_switch, TB_TYPE_NHI);
mutex_lock(&tb->lock);
- tunnel = tb_tunnel_alloc_dma(tb, nhi_port, dst_port, xd->transmit_ring,
- xd->transmit_path, xd->receive_ring,
- xd->receive_path);
+ tunnel = tb_tunnel_alloc_dma(tb, nhi_port, dst_port, transmit_path,
+ transmit_ring, receive_path, receive_ring);
if (!tunnel) {
mutex_unlock(&tb->lock);
return -ENOMEM;
@@ -1110,29 +1113,40 @@ static int tb_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd)
return 0;
}
-static void __tb_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd)
+static void __tb_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd,
+ int transmit_path, int transmit_ring,
+ int receive_path, int receive_ring)
{
- struct tb_port *dst_port;
- struct tb_tunnel *tunnel;
+ struct tb_cm *tcm = tb_priv(tb);
+ struct tb_port *nhi_port, *dst_port;
+ struct tb_tunnel *tunnel, *n;
struct tb_switch *sw;
sw = tb_to_switch(xd->dev.parent);
dst_port = tb_port_at(xd->route, sw);
+ nhi_port = tb_switch_find_port(tb->root_switch, TB_TYPE_NHI);
- /*
- * It is possible that the tunnel was already teared down (in
- * case of cable disconnect) so it is fine if we cannot find it
- * here anymore.
- */
- tunnel = tb_find_tunnel(tb, TB_TUNNEL_DMA, NULL, dst_port);
- tb_deactivate_and_free_tunnel(tunnel);
+ list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list) {
+ if (!tb_tunnel_is_dma(tunnel))
+ continue;
+ if (tunnel->src_port != nhi_port || tunnel->dst_port != dst_port)
+ continue;
+
+ if (tb_tunnel_match_dma(tunnel, transmit_path, transmit_ring,
+ receive_path, receive_ring))
+ tb_deactivate_and_free_tunnel(tunnel);
+ }
}
-static int tb_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd)
+static int tb_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd,
+ int transmit_path, int transmit_ring,
+ int receive_path, int receive_ring)
{
if (!xd->is_unplugged) {
mutex_lock(&tb->lock);
- __tb_disconnect_xdomain_paths(tb, xd);
+ __tb_disconnect_xdomain_paths(tb, xd, transmit_path,
+ transmit_ring, receive_path,
+ receive_ring);
mutex_unlock(&tb->lock);
}
return 0;
@@ -1208,12 +1222,12 @@ static void tb_handle_hotplug(struct work_struct *work)
* tb_xdomain_remove() so setting XDomain as
* unplugged here prevents deadlock if they call
* tb_xdomain_disable_paths(). We will tear down
- * the path below.
+ * all the tunnels below.
*/
xd->is_unplugged = true;
tb_xdomain_remove(xd);
port->xdomain = NULL;
- __tb_disconnect_xdomain_paths(tb, xd);
+ __tb_disconnect_xdomain_paths(tb, xd, -1, -1, -1, -1);
tb_xdomain_put(xd);
tb_port_unconfigure_xdomain(port);
} else if (tb_port_is_dpout(port) || tb_port_is_dpin(port)) {
@@ -1562,7 +1576,7 @@ struct tb *tb_probe(struct tb_nhi *nhi)
struct tb_cm *tcm;
struct tb *tb;
- tb = tb_domain_alloc(nhi, sizeof(*tcm));
+ tb = tb_domain_alloc(nhi, TB_TIMEOUT, sizeof(*tcm));
if (!tb)
return NULL;