Commit c82510b1 authored by Mika Westerberg's avatar Mika Westerberg
Browse files

thunderbolt: Use scale field when allocating USB3 bandwidth



When tunneling aggregated USB3 (20 Gb/s) the bandwidth values that are
programmed to the ADP_USB3_CS_2 go higher than 4096 and that does not
fit anymore to the 12-bit field. Fix this by scaling the value using
the scale field accordingly.

Fixes: 3b1d8d57 ("thunderbolt: Implement USB3 bandwidth negotiation routines")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
parent f0a57dd3
Loading
Loading
Loading
Loading
+17 −5
Original line number Diff line number Diff line
@@ -2094,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,
	/* 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)