summaryrefslogtreecommitdiff
path: root/drivers/thunderbolt/tunnel.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/thunderbolt/tunnel.c')
-rw-r--r--drivers/thunderbolt/tunnel.c82
1 files changed, 71 insertions, 11 deletions
diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c
index 2e7ec037a73e..e1979bed7146 100644
--- a/drivers/thunderbolt/tunnel.c
+++ b/drivers/thunderbolt/tunnel.c
@@ -815,28 +815,28 @@ static void tb_dma_init_path(struct tb_path *path, unsigned int efc, u32 credits
* @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))
@@ -851,7 +851,7 @@ struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi,
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) {
@@ -862,7 +862,7 @@ struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi,
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) {
@@ -876,6 +876,66 @@ struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi,
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;