diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-04-13 12:17:14 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-04-13 12:17:14 +0200 |
commit | 5367f82a212305c35b35303a8a21ca348f653ca3 (patch) | |
tree | 98e88cbd6f40762b11802624022eaccf08051c39 /drivers/thunderbolt/tunnel.c | |
parent | 9bc46a12c53d8268392774172742aa9e5dd6953d (diff) | |
parent | 6f3badead6a078cf3c71f381f9d84ac922984a00 (diff) |
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/tunnel.c')
-rw-r--r-- | drivers/thunderbolt/tunnel.c | 102 |
1 files changed, 75 insertions, 27 deletions
diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index 6557b6e07009..e1979bed7146 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -794,24 +794,14 @@ static u32 tb_dma_credits(struct tb_port *nhi) return min(max_credits, 13U); } -static int tb_dma_activate(struct tb_tunnel *tunnel, bool active) -{ - struct tb_port *nhi = tunnel->src_port; - u32 credits; - - credits = active ? tb_dma_credits(nhi) : 0; - return tb_port_set_initial_credits(nhi, credits); -} - -static void tb_dma_init_path(struct tb_path *path, unsigned int isb, - unsigned int efc, u32 credits) +static void tb_dma_init_path(struct tb_path *path, unsigned int efc, u32 credits) { int i; path->egress_fc_enable = efc; path->ingress_fc_enable = TB_PATH_ALL; path->egress_shared_buffer = TB_PATH_NONE; - path->ingress_shared_buffer = isb; + path->ingress_shared_buffer = TB_PATH_NONE; path->priority = 5; path->weight = 1; path->clear_fc = true; @@ -825,28 +815,28 @@ static void tb_dma_init_path(struct tb_path *path, unsigned int isb, * @tb: Pointer to the domain structure * @nhi: Host controller port * @dst: Destination null port which the other domain is connected to - * @transmit_ring: NHI ring number used to send packets towards the - * other domain. Set to %0 if TX path is not needed. * @transmit_path: HopID used for transmitting packets - * @receive_ring: NHI ring number used to receive packets from the - * other domain. Set to %0 if RX path is not needed. + * @transmit_ring: NHI ring number used to send packets towards the + * other domain. Set to %-1 if TX path is not needed. * @receive_path: HopID used for receiving packets + * @receive_ring: NHI ring number used to receive packets from the + * other domain. Set to %-1 if RX path is not needed. * * Return: Returns a tb_tunnel on success or NULL on failure. */ struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi, - struct tb_port *dst, int transmit_ring, - int transmit_path, int receive_ring, - int receive_path) + struct tb_port *dst, int transmit_path, + int transmit_ring, int receive_path, + int receive_ring) { struct tb_tunnel *tunnel; size_t npaths = 0, i = 0; struct tb_path *path; u32 credits; - if (receive_ring) + if (receive_ring > 0) npaths++; - if (transmit_ring) + if (transmit_ring > 0) npaths++; if (WARN_ON(!npaths)) @@ -856,38 +846,96 @@ struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi, if (!tunnel) return NULL; - tunnel->activate = tb_dma_activate; tunnel->src_port = nhi; tunnel->dst_port = dst; credits = tb_dma_credits(nhi); - if (receive_ring) { + if (receive_ring > 0) { path = tb_path_alloc(tb, dst, receive_path, nhi, receive_ring, 0, "DMA RX"); if (!path) { tb_tunnel_free(tunnel); return NULL; } - tb_dma_init_path(path, TB_PATH_NONE, TB_PATH_SOURCE | TB_PATH_INTERNAL, - credits); + tb_dma_init_path(path, TB_PATH_SOURCE | TB_PATH_INTERNAL, credits); tunnel->paths[i++] = path; } - if (transmit_ring) { + if (transmit_ring > 0) { path = tb_path_alloc(tb, nhi, transmit_ring, dst, transmit_path, 0, "DMA TX"); if (!path) { tb_tunnel_free(tunnel); return NULL; } - tb_dma_init_path(path, TB_PATH_SOURCE, TB_PATH_ALL, credits); + tb_dma_init_path(path, TB_PATH_ALL, credits); tunnel->paths[i++] = path; } return tunnel; } +/** + * tb_tunnel_match_dma() - Match DMA tunnel + * @tunnel: Tunnel to match + * @transmit_path: HopID used for transmitting packets. Pass %-1 to ignore. + * @transmit_ring: NHI ring number used to send packets towards the + * other domain. Pass %-1 to ignore. + * @receive_path: HopID used for receiving packets. Pass %-1 to ignore. + * @receive_ring: NHI ring number used to receive packets from the + * other domain. Pass %-1 to ignore. + * + * This function can be used to match specific DMA tunnel, if there are + * multiple DMA tunnels going through the same XDomain connection. + * Returns true if there is match and false otherwise. + */ +bool tb_tunnel_match_dma(const struct tb_tunnel *tunnel, int transmit_path, + int transmit_ring, int receive_path, int receive_ring) +{ + const struct tb_path *tx_path = NULL, *rx_path = NULL; + int i; + + if (!receive_ring || !transmit_ring) + return false; + + for (i = 0; i < tunnel->npaths; i++) { + const struct tb_path *path = tunnel->paths[i]; + + if (!path) + continue; + + if (tb_port_is_nhi(path->hops[0].in_port)) + tx_path = path; + else if (tb_port_is_nhi(path->hops[path->path_length - 1].out_port)) + rx_path = path; + } + + if (transmit_ring > 0 || transmit_path > 0) { + if (!tx_path) + return false; + if (transmit_ring > 0 && + (tx_path->hops[0].in_hop_index != transmit_ring)) + return false; + if (transmit_path > 0 && + (tx_path->hops[tx_path->path_length - 1].next_hop_index != transmit_path)) + return false; + } + + if (receive_ring > 0 || receive_path > 0) { + if (!rx_path) + return false; + if (receive_path > 0 && + (rx_path->hops[0].in_hop_index != receive_path)) + return false; + if (receive_ring > 0 && + (rx_path->hops[rx_path->path_length - 1].next_hop_index != receive_ring)) + return false; + } + + return true; +} + static int tb_usb3_max_link_rate(struct tb_port *up, struct tb_port *down) { int ret, up_max_rate, down_max_rate; |