diff options
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; | 
