thunderbolt: Change bandwidth reservations to comply USB4 v2

USB4 v2 Connection Manager guide (section 6.1.2.3) suggests to reserve
bandwidth in a sligthly different manner. It suggests to keep minimum of
1500 Mb/s for each path that carry a bulk traffic. Here we change the
bandwidth reservations to comply to the above for USB 3.x and PCIe
protocols over Gen 4 link, taking weights into account (that's 1500 Mb/s
for PCIe and 3000 Mb/s for USB 3.x).

For Gen 3 and below we use the existing reservation.

Signed-off-by: Gil Fine <gil.fine@linux.intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
This commit is contained in:
Gil Fine 2023-07-31 05:25:40 +03:00 committed by Mika Westerberg
parent aa673d6060
commit 582e70b0d3
3 changed files with 76 additions and 3 deletions

View file

@ -602,6 +602,7 @@ static int tb_available_bandwidth(struct tb *tb, struct tb_port *src_port,
/* Find the minimum available bandwidth over all links */
tb_for_each_port_on_path(src_port, dst_port, port) {
int link_speed, link_width, up_bw, down_bw;
int pci_reserved_up, pci_reserved_down;
if (!tb_port_is_null(port))
continue;
@ -695,6 +696,16 @@ static int tb_available_bandwidth(struct tb *tb, struct tb_port *src_port,
up_bw -= usb3_consumed_up;
down_bw -= usb3_consumed_down;
/*
* If there is anything reserved for PCIe bulk traffic
* take it into account here too.
*/
if (tb_tunnel_reserved_pci(port, &pci_reserved_up,
&pci_reserved_down)) {
up_bw -= pci_reserved_up;
down_bw -= pci_reserved_down;
}
if (up_bw < *available_up)
*available_up = up_bw;
if (down_bw < *available_down)

View file

@ -31,7 +31,7 @@
#define TB_USB3_PATH_UP 1
#define TB_USB3_PRIORITY 3
#define TB_USB3_WEIGHT 3
#define TB_USB3_WEIGHT 2
/* DP adapters use HopID 8 for AUX and 9 for Video */
#define TB_DP_AUX_TX_HOPID 8
@ -61,6 +61,15 @@
#define TB_DMA_PRIORITY 5
#define TB_DMA_WEIGHT 1
/*
* Reserve additional bandwidth for USB 3.x and PCIe bulk traffic
* according to USB4 v2 Connection Manager guide. This ends up reserving
* 1500 Mb/s for PCIe and 3000 Mb/s for USB 3.x taking weights into
* account.
*/
#define USB4_V2_PCI_MIN_BANDWIDTH (1500 * TB_PCI_WEIGHT)
#define USB4_V2_USB3_MIN_BANDWIDTH (1500 * TB_USB3_WEIGHT)
static unsigned int dma_credits = TB_DMA_CREDITS;
module_param(dma_credits, uint, 0444);
MODULE_PARM_DESC(dma_credits, "specify custom credits for DMA tunnels (default: "
@ -150,11 +159,11 @@ static struct tb_tunnel *tb_tunnel_alloc(struct tb *tb, size_t npaths,
static int tb_pci_set_ext_encapsulation(struct tb_tunnel *tunnel, bool enable)
{
struct tb_port *port = tb_upstream_port(tunnel->dst_port->sw);
int ret;
/* Only supported of both routers are at least USB4 v2 */
if (usb4_switch_version(tunnel->src_port->sw) < 2 ||
usb4_switch_version(tunnel->dst_port->sw) < 2)
if (tb_port_get_link_generation(port) < 4)
return 0;
ret = usb4_pci_port_set_ext_encapsulation(tunnel->src_port, enable);
@ -370,6 +379,51 @@ struct tb_tunnel *tb_tunnel_alloc_pci(struct tb *tb, struct tb_port *up,
return NULL;
}
/**
* tb_tunnel_reserved_pci() - Amount of bandwidth to reserve for PCIe
* @port: Lane 0 adapter
* @reserved_up: Upstream bandwidth in Mb/s to reserve
* @reserved_down: Downstream bandwidth in Mb/s to reserve
*
* Can be called to any connected lane 0 adapter to find out how much
* bandwidth needs to be left in reserve for possible PCIe bulk traffic.
* Returns true if there is something to be reserved and writes the
* amount to @reserved_down/@reserved_up. Otherwise returns false and
* does not touch the parameters.
*/
bool tb_tunnel_reserved_pci(struct tb_port *port, int *reserved_up,
int *reserved_down)
{
if (WARN_ON_ONCE(!port->remote))
return false;
if (!tb_acpi_may_tunnel_pcie())
return false;
if (tb_port_get_link_generation(port) < 4)
return false;
/* Must have PCIe adapters */
if (tb_is_upstream_port(port)) {
if (!tb_switch_find_port(port->sw, TB_TYPE_PCIE_UP))
return false;
if (!tb_switch_find_port(port->remote->sw, TB_TYPE_PCIE_DOWN))
return false;
} else {
if (!tb_switch_find_port(port->sw, TB_TYPE_PCIE_DOWN))
return false;
if (!tb_switch_find_port(port->remote->sw, TB_TYPE_PCIE_UP))
return false;
}
*reserved_up = USB4_V2_PCI_MIN_BANDWIDTH;
*reserved_down = USB4_V2_PCI_MIN_BANDWIDTH;
tb_port_dbg(port, "reserving %u/%u Mb/s for PCIe\n", *reserved_up,
*reserved_down);
return true;
}
static bool tb_dp_is_usb4(const struct tb_switch *sw)
{
/* Titan Ridge DP adapters need the same treatment as USB4 */
@ -1747,6 +1801,7 @@ static int tb_usb3_activate(struct tb_tunnel *tunnel, bool activate)
static int tb_usb3_consumed_bandwidth(struct tb_tunnel *tunnel,
int *consumed_up, int *consumed_down)
{
struct tb_port *port = tb_upstream_port(tunnel->dst_port->sw);
int pcie_weight = tb_acpi_may_tunnel_pcie() ? TB_PCI_WEIGHT : 0;
/*
@ -1758,6 +1813,11 @@ static int tb_usb3_consumed_bandwidth(struct tb_tunnel *tunnel,
*consumed_down = tunnel->allocated_down *
(TB_USB3_WEIGHT + pcie_weight) / TB_USB3_WEIGHT;
if (tb_port_get_link_generation(port) >= 4) {
*consumed_up = max(*consumed_up, USB4_V2_USB3_MIN_BANDWIDTH);
*consumed_down = max(*consumed_down, USB4_V2_USB3_MIN_BANDWIDTH);
}
return 0;
}

View file

@ -80,6 +80,8 @@ struct tb_tunnel *tb_tunnel_discover_pci(struct tb *tb, struct tb_port *down,
bool alloc_hopid);
struct tb_tunnel *tb_tunnel_alloc_pci(struct tb *tb, struct tb_port *up,
struct tb_port *down);
bool tb_tunnel_reserved_pci(struct tb_port *port, int *reserved_up,
int *reserved_down);
struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb, struct tb_port *in,
bool alloc_hopid);
struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, struct tb_port *in,