Commit f0a57dd3 authored by Gil Fine's avatar Gil Fine Committed by Mika Westerberg
Browse files

thunderbolt: Limit USB3 bandwidth of certain Intel USB4 host routers



Current Intel USB4 host routers have hardware limitation that the USB3
bandwidth cannot go higher than 16376 Mb/s. Work this around by adding a
new quirk that limits the bandwidth for the affected host routers.

Cc: stable@vger.kernel.org
Signed-off-by: default avatarGil Fine <gil.fine@linux.intel.com>
Signed-off-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
parent d2d6ddf1
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -26,6 +26,19 @@ static void quirk_clx_disable(struct tb_switch *sw)
	tb_sw_dbg(sw, "disabling CL states\n");
}

static void quirk_usb3_maximum_bandwidth(struct tb_switch *sw)
{
	struct tb_port *port;

	tb_switch_for_each_port(sw, port) {
		if (!tb_port_is_usb3_down(port))
			continue;
		port->max_bw = 16376;
		tb_port_dbg(port, "USB3 maximum bandwidth limited to %u Mb/s\n",
			    port->max_bw);
	}
}

struct tb_quirk {
	u16 hw_vendor_id;
	u16 hw_device_id;
@@ -43,6 +56,24 @@ static const struct tb_quirk tb_quirks[] = {
	 * DP buffers.
	 */
	{ 0x8087, 0x0b26, 0x0000, 0x0000, quirk_dp_credit_allocation },
	/*
	 * Limit the maximum USB3 bandwidth for the following Intel USB4
	 * host routers due to a hardware issue.
	 */
	{ 0x8087, PCI_DEVICE_ID_INTEL_ADL_NHI0, 0x0000, 0x0000,
		  quirk_usb3_maximum_bandwidth },
	{ 0x8087, PCI_DEVICE_ID_INTEL_ADL_NHI1, 0x0000, 0x0000,
		  quirk_usb3_maximum_bandwidth },
	{ 0x8087, PCI_DEVICE_ID_INTEL_RPL_NHI0, 0x0000, 0x0000,
		  quirk_usb3_maximum_bandwidth },
	{ 0x8087, PCI_DEVICE_ID_INTEL_RPL_NHI1, 0x0000, 0x0000,
		  quirk_usb3_maximum_bandwidth },
	{ 0x8087, PCI_DEVICE_ID_INTEL_MTL_M_NHI0, 0x0000, 0x0000,
		  quirk_usb3_maximum_bandwidth },
	{ 0x8087, PCI_DEVICE_ID_INTEL_MTL_P_NHI0, 0x0000, 0x0000,
		  quirk_usb3_maximum_bandwidth },
	{ 0x8087, PCI_DEVICE_ID_INTEL_MTL_P_NHI1, 0x0000, 0x0000,
		  quirk_usb3_maximum_bandwidth },
	/*
	 * CLx is not supported on AMD USB4 Yellow Carp and Pink Sardine platforms.
	 */
+3 −0
Original line number Diff line number Diff line
@@ -272,6 +272,8 @@ struct tb_bandwidth_group {
 * @group: Bandwidth allocation group the adapter is assigned to. Only
 *	   used for DP IN adapters for now.
 * @group_list: The adapter is linked to the group's list of ports through this
 * @max_bw: Maximum possible bandwidth through this adapter if set to
 *	    non-zero.
 *
 * In USB4 terminology this structure represents an adapter (protocol or
 * lane adapter).
@@ -299,6 +301,7 @@ struct tb_port {
	unsigned int dma_credits;
	struct tb_bandwidth_group *group;
	struct list_head group_list;
	unsigned int max_bw;
};

/**
+15 −2
Original line number Diff line number Diff line
@@ -1882,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
@@ -1903,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);
}

/**
@@ -1930,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)