diff options
Diffstat (limited to 'drivers/thunderbolt/usb4.c')
| -rw-r--r-- | drivers/thunderbolt/usb4.c | 53 | 
1 files changed, 46 insertions, 7 deletions
| diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c index 1e5e9c147a31..a0996cb2893c 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -1579,6 +1579,20 @@ int usb4_port_retimer_set_inbound_sbtx(struct tb_port *port, u8 index)  }  /** + * usb4_port_retimer_unset_inbound_sbtx() - Disable sideband channel transactions + * @port: USB4 port + * @index: Retimer index + * + * Disables sideband channel transations on SBTX. The reverse of + * usb4_port_retimer_set_inbound_sbtx(). + */ +int usb4_port_retimer_unset_inbound_sbtx(struct tb_port *port, u8 index) +{ +	return usb4_port_retimer_op(port, index, +				    USB4_SB_OPCODE_UNSET_INBOUND_SBTX, 500); +} + +/**   * usb4_port_retimer_read() - Read from retimer sideband registers   * @port: USB4 port   * @index: Retimer index @@ -1868,6 +1882,15 @@ int usb4_port_retimer_nvm_read(struct tb_port *port, u8 index,  				usb4_port_retimer_nvm_read_block, &info);  } +static inline unsigned int +usb4_usb3_port_max_bandwidth(const struct tb_port *port, unsigned int bw) +{ +	/* Take the possible bandwidth limitation into account */ +	if (port->max_bw) +		return min(bw, port->max_bw); +	return bw; +} +  /**   * usb4_usb3_port_max_link_rate() - Maximum support USB3 link rate   * @port: USB3 adapter port @@ -1889,7 +1912,9 @@ int usb4_usb3_port_max_link_rate(struct tb_port *port)  		return ret;  	lr = (val & ADP_USB3_CS_4_MSLR_MASK) >> ADP_USB3_CS_4_MSLR_SHIFT; -	return lr == ADP_USB3_CS_4_MSLR_20G ? 20000 : 10000; +	ret = lr == ADP_USB3_CS_4_MSLR_20G ? 20000 : 10000; + +	return usb4_usb3_port_max_bandwidth(port, ret);  }  /** @@ -1916,7 +1941,9 @@ int usb4_usb3_port_actual_link_rate(struct tb_port *port)  		return 0;  	lr = val & ADP_USB3_CS_4_ALR_MASK; -	return lr == ADP_USB3_CS_4_ALR_20G ? 20000 : 10000; +	ret = lr == ADP_USB3_CS_4_ALR_20G ? 20000 : 10000; + +	return usb4_usb3_port_max_bandwidth(port, ret);  }  static int usb4_usb3_port_cm_request(struct tb_port *port, bool request) @@ -2067,18 +2094,30 @@ static int usb4_usb3_port_write_allocated_bandwidth(struct tb_port *port,  						    int downstream_bw)  {  	u32 val, ubw, dbw, scale; -	int ret; +	int ret, max_bw; -	/* Read the used scale, hardware default is 0 */ -	ret = tb_port_read(port, &scale, TB_CFG_PORT, -			   port->cap_adap + ADP_USB3_CS_3, 1); +	/* Figure out suitable scale */ +	scale = 0; +	max_bw = max(upstream_bw, downstream_bw); +	while (scale < 64) { +		if (mbps_to_usb3_bw(max_bw, scale) < 4096) +			break; +		scale++; +	} + +	if (WARN_ON(scale >= 64)) +		return -EINVAL; + +	ret = tb_port_write(port, &scale, TB_CFG_PORT, +			    port->cap_adap + ADP_USB3_CS_3, 1);  	if (ret)  		return ret; -	scale &= ADP_USB3_CS_3_SCALE_MASK;  	ubw = mbps_to_usb3_bw(upstream_bw, scale);  	dbw = mbps_to_usb3_bw(downstream_bw, scale); +	tb_port_dbg(port, "scaled bandwidth %u/%u, scale %u\n", ubw, dbw, scale); +  	ret = tb_port_read(port, &val, TB_CFG_PORT,  			   port->cap_adap + ADP_USB3_CS_2, 1);  	if (ret) |