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:
parent
aa673d6060
commit
582e70b0d3
@ -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)
|
||||
|
@ -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 @@ err_free:
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user