Merge tag 'cfi-v5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
[linux-2.6-microblaze.git] / drivers / thunderbolt / tunnel.c
index 6557b6e..e1979be 100644 (file)
@@ -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;