diff options
Diffstat (limited to 'drivers/thunderbolt/tunnel.c')
-rw-r--r-- | drivers/thunderbolt/tunnel.c | 263 |
1 files changed, 165 insertions, 98 deletions
diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index a6810fb36860..7534cd3a81f4 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -21,12 +21,18 @@ #define TB_PCI_PATH_DOWN 0 #define TB_PCI_PATH_UP 1 +#define TB_PCI_PRIORITY 3 +#define TB_PCI_WEIGHT 1 + /* USB3 adapters use always HopID of 8 for both directions */ #define TB_USB3_HOPID 8 #define TB_USB3_PATH_DOWN 0 #define TB_USB3_PATH_UP 1 +#define TB_USB3_PRIORITY 3 +#define TB_USB3_WEIGHT 2 + /* DP adapters use HopID 8 for AUX and 9 for Video */ #define TB_DP_AUX_TX_HOPID 8 #define TB_DP_AUX_RX_HOPID 8 @@ -36,6 +42,12 @@ #define TB_DP_AUX_PATH_OUT 1 #define TB_DP_AUX_PATH_IN 2 +#define TB_DP_VIDEO_PRIORITY 1 +#define TB_DP_VIDEO_WEIGHT 1 + +#define TB_DP_AUX_PRIORITY 2 +#define TB_DP_AUX_WEIGHT 1 + /* Minimum number of credits needed for PCIe path */ #define TB_MIN_PCIE_CREDITS 6U /* @@ -46,6 +58,18 @@ /* Minimum number of credits for DMA path */ #define TB_MIN_DMA_CREDITS 1 +#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: " @@ -58,27 +82,6 @@ MODULE_PARM_DESC(bw_alloc_mode, static const char * const tb_tunnel_names[] = { "PCI", "DP", "DMA", "USB3" }; -#define __TB_TUNNEL_PRINT(level, tunnel, fmt, arg...) \ - do { \ - struct tb_tunnel *__tunnel = (tunnel); \ - level(__tunnel->tb, "%llx:%u <-> %llx:%u (%s): " fmt, \ - tb_route(__tunnel->src_port->sw), \ - __tunnel->src_port->port, \ - tb_route(__tunnel->dst_port->sw), \ - __tunnel->dst_port->port, \ - tb_tunnel_names[__tunnel->type], \ - ## arg); \ - } while (0) - -#define tb_tunnel_WARN(tunnel, fmt, arg...) \ - __TB_TUNNEL_PRINT(tb_WARN, tunnel, fmt, ##arg) -#define tb_tunnel_warn(tunnel, fmt, arg...) \ - __TB_TUNNEL_PRINT(tb_warn, tunnel, fmt, ##arg) -#define tb_tunnel_info(tunnel, fmt, arg...) \ - __TB_TUNNEL_PRINT(tb_info, tunnel, fmt, ##arg) -#define tb_tunnel_dbg(tunnel, fmt, arg...) \ - __TB_TUNNEL_PRINT(tb_dbg, tunnel, fmt, ##arg) - static inline unsigned int tb_usable_credits(const struct tb_port *port) { return port->total_credits - port->ctl_credits; @@ -131,6 +134,16 @@ static unsigned int tb_available_credits(const struct tb_port *port, return credits > 0 ? credits : 0; } +static void tb_init_pm_support(struct tb_path_hop *hop) +{ + struct tb_port *out_port = hop->out_port; + struct tb_port *in_port = hop->in_port; + + if (tb_port_is_null(in_port) && tb_port_is_null(out_port) && + usb4_switch_version(in_port->sw) >= 2) + hop->pm_support = true; +} + static struct tb_tunnel *tb_tunnel_alloc(struct tb *tb, size_t npaths, enum tb_tunnel_type type) { @@ -156,11 +169,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); @@ -234,8 +247,8 @@ static int tb_pci_init_path(struct tb_path *path) path->egress_shared_buffer = TB_PATH_NONE; path->ingress_fc_enable = TB_PATH_ALL; path->ingress_shared_buffer = TB_PATH_NONE; - path->priority = 3; - path->weight = 1; + path->priority = TB_PCI_PRIORITY; + path->weight = TB_PCI_WEIGHT; path->drop_packages = 0; tb_path_for_each_hop(path, hop) { @@ -376,6 +389,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 */ @@ -614,8 +672,9 @@ static int tb_dp_xchg_caps(struct tb_tunnel *tunnel) in_rate = tb_dp_cap_get_rate(in_dp_cap); in_lanes = tb_dp_cap_get_lanes(in_dp_cap); - tb_port_dbg(in, "maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", - in_rate, in_lanes, tb_dp_bandwidth(in_rate, in_lanes)); + tb_tunnel_dbg(tunnel, + "DP IN maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", + in_rate, in_lanes, tb_dp_bandwidth(in_rate, in_lanes)); /* * If the tunnel bandwidth is limited (max_bw is set) then see @@ -624,10 +683,11 @@ static int tb_dp_xchg_caps(struct tb_tunnel *tunnel) out_rate = tb_dp_cap_get_rate(out_dp_cap); out_lanes = tb_dp_cap_get_lanes(out_dp_cap); bw = tb_dp_bandwidth(out_rate, out_lanes); - tb_port_dbg(out, "maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", - out_rate, out_lanes, bw); + tb_tunnel_dbg(tunnel, + "DP OUT maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", + out_rate, out_lanes, bw); - if (in->sw->config.depth < out->sw->config.depth) + if (tb_port_path_direction_downstream(in, out)) max_bw = tunnel->max_down; else max_bw = tunnel->max_up; @@ -639,13 +699,14 @@ static int tb_dp_xchg_caps(struct tb_tunnel *tunnel) out_rate, out_lanes, &new_rate, &new_lanes); if (ret) { - tb_port_info(out, "not enough bandwidth for DP tunnel\n"); + tb_tunnel_info(tunnel, "not enough bandwidth\n"); return ret; } new_bw = tb_dp_bandwidth(new_rate, new_lanes); - tb_port_dbg(out, "bandwidth reduced to %u Mb/s x%u = %u Mb/s\n", - new_rate, new_lanes, new_bw); + tb_tunnel_dbg(tunnel, + "bandwidth reduced to %u Mb/s x%u = %u Mb/s\n", + new_rate, new_lanes, new_bw); /* * Set new rate and number of lanes before writing it to @@ -662,7 +723,7 @@ static int tb_dp_xchg_caps(struct tb_tunnel *tunnel) */ if (tb_route(out->sw) && tb_switch_is_titan_ridge(out->sw)) { out_dp_cap |= DP_COMMON_CAP_LTTPR_NS; - tb_port_dbg(out, "disabling LTTPR\n"); + tb_tunnel_dbg(tunnel, "disabling LTTPR\n"); } return tb_port_write(in, &out_dp_cap, TB_CFG_PORT, @@ -712,8 +773,8 @@ static int tb_dp_bandwidth_alloc_mode_enable(struct tb_tunnel *tunnel) lanes = min(in_lanes, out_lanes); tmp = tb_dp_bandwidth(rate, lanes); - tb_port_dbg(in, "non-reduced bandwidth %u Mb/s x%u = %u Mb/s\n", rate, - lanes, tmp); + tb_tunnel_dbg(tunnel, "non-reduced bandwidth %u Mb/s x%u = %u Mb/s\n", + rate, lanes, tmp); ret = usb4_dp_port_set_nrd(in, rate, lanes); if (ret) @@ -728,15 +789,15 @@ static int tb_dp_bandwidth_alloc_mode_enable(struct tb_tunnel *tunnel) rate = min(in_rate, out_rate); tmp = tb_dp_bandwidth(rate, lanes); - tb_port_dbg(in, - "maximum bandwidth through allocation mode %u Mb/s x%u = %u Mb/s\n", - rate, lanes, tmp); + tb_tunnel_dbg(tunnel, + "maximum bandwidth through allocation mode %u Mb/s x%u = %u Mb/s\n", + rate, lanes, tmp); for (granularity = 250; tmp / granularity > 255 && granularity <= 1000; granularity *= 2) ; - tb_port_dbg(in, "granularity %d Mb/s\n", granularity); + tb_tunnel_dbg(tunnel, "granularity %d Mb/s\n", granularity); /* * Returns -EINVAL if granularity above is outside of the @@ -751,12 +812,12 @@ static int tb_dp_bandwidth_alloc_mode_enable(struct tb_tunnel *tunnel) * max_up/down fields. For discovery we just read what the * estimation was set to. */ - if (in->sw->config.depth < out->sw->config.depth) + if (tb_port_path_direction_downstream(in, out)) estimated_bw = tunnel->max_down; else estimated_bw = tunnel->max_up; - tb_port_dbg(in, "estimated bandwidth %d Mb/s\n", estimated_bw); + tb_tunnel_dbg(tunnel, "estimated bandwidth %d Mb/s\n", estimated_bw); ret = usb4_dp_port_set_estimated_bandwidth(in, estimated_bw); if (ret) @@ -767,7 +828,7 @@ static int tb_dp_bandwidth_alloc_mode_enable(struct tb_tunnel *tunnel) if (ret) return ret; - tb_port_dbg(in, "bandwidth allocation mode enabled\n"); + tb_tunnel_dbg(tunnel, "bandwidth allocation mode enabled\n"); return 0; } @@ -788,7 +849,7 @@ static int tb_dp_init(struct tb_tunnel *tunnel) if (!usb4_dp_port_bandwidth_mode_supported(in)) return 0; - tb_port_dbg(in, "bandwidth allocation mode supported\n"); + tb_tunnel_dbg(tunnel, "bandwidth allocation mode supported\n"); ret = usb4_dp_port_set_cm_id(in, tb->index); if (ret) @@ -805,7 +866,7 @@ static void tb_dp_deinit(struct tb_tunnel *tunnel) return; if (usb4_dp_port_bandwidth_mode_enabled(in)) { usb4_dp_port_set_cm_bandwidth_mode_supported(in, false); - tb_port_dbg(in, "bandwidth allocation mode disabled\n"); + tb_tunnel_dbg(tunnel, "bandwidth allocation mode disabled\n"); } } @@ -921,10 +982,7 @@ static int tb_dp_bandwidth_mode_consumed_bandwidth(struct tb_tunnel *tunnel, if (allocated_bw == max_bw) allocated_bw = ret; - tb_port_dbg(in, "consumed bandwidth through allocation mode %d Mb/s\n", - allocated_bw); - - if (in->sw->config.depth < out->sw->config.depth) { + if (tb_port_path_direction_downstream(in, out)) { *consumed_up = 0; *consumed_down = allocated_bw; } else { @@ -959,7 +1017,7 @@ static int tb_dp_allocated_bandwidth(struct tb_tunnel *tunnel, int *allocated_up if (allocated_bw == max_bw) allocated_bw = ret; - if (in->sw->config.depth < out->sw->config.depth) { + if (tb_port_path_direction_downstream(in, out)) { *allocated_up = 0; *allocated_down = allocated_bw; } else { @@ -987,7 +1045,7 @@ static int tb_dp_alloc_bandwidth(struct tb_tunnel *tunnel, int *alloc_up, if (ret < 0) return ret; - if (in->sw->config.depth < out->sw->config.depth) { + if (tb_port_path_direction_downstream(in, out)) { tmp = min(*alloc_down, max_bw); ret = usb4_dp_port_allocate_bandwidth(in, tmp); if (ret) @@ -1006,9 +1064,6 @@ static int tb_dp_alloc_bandwidth(struct tb_tunnel *tunnel, int *alloc_up, /* Now we can use BW mode registers to figure out the bandwidth */ /* TODO: need to handle discovery too */ tunnel->bw_mode = true; - - tb_port_dbg(in, "allocated bandwidth through allocation mode %d Mb/s\n", - tmp); return 0; } @@ -1035,8 +1090,7 @@ static int tb_dp_read_dprx(struct tb_tunnel *tunnel, u32 *rate, u32 *lanes, *rate = tb_dp_cap_get_rate(val); *lanes = tb_dp_cap_get_lanes(val); - tb_port_dbg(in, "consumed bandwidth through DPRX %d Mb/s\n", - tb_dp_bandwidth(*rate, *lanes)); + tb_tunnel_dbg(tunnel, "DPRX read done\n"); return 0; } usleep_range(100, 150); @@ -1073,9 +1127,6 @@ static int tb_dp_read_cap(struct tb_tunnel *tunnel, unsigned int cap, u32 *rate, *rate = tb_dp_cap_get_rate(val); *lanes = tb_dp_cap_get_lanes(val); - - tb_port_dbg(in, "bandwidth from %#x capability %d Mb/s\n", cap, - tb_dp_bandwidth(*rate, *lanes)); return 0; } @@ -1092,7 +1143,7 @@ static int tb_dp_maximum_bandwidth(struct tb_tunnel *tunnel, int *max_up, if (ret < 0) return ret; - if (in->sw->config.depth < tunnel->dst_port->sw->config.depth) { + if (tb_port_path_direction_downstream(in, tunnel->dst_port)) { *max_up = 0; *max_down = ret; } else { @@ -1150,7 +1201,7 @@ static int tb_dp_consumed_bandwidth(struct tb_tunnel *tunnel, int *consumed_up, return 0; } - if (in->sw->config.depth < tunnel->dst_port->sw->config.depth) { + if (tb_port_path_direction_downstream(in, tunnel->dst_port)) { *consumed_up = 0; *consumed_down = tb_dp_bandwidth(rate, lanes); } else { @@ -1172,7 +1223,7 @@ static void tb_dp_init_aux_credits(struct tb_path_hop *hop) hop->initial_credits = 1; } -static void tb_dp_init_aux_path(struct tb_path *path) +static void tb_dp_init_aux_path(struct tb_path *path, bool pm_support) { struct tb_path_hop *hop; @@ -1180,11 +1231,14 @@ static void tb_dp_init_aux_path(struct tb_path *path) path->egress_shared_buffer = TB_PATH_NONE; path->ingress_fc_enable = TB_PATH_ALL; path->ingress_shared_buffer = TB_PATH_NONE; - path->priority = 2; - path->weight = 1; + path->priority = TB_DP_AUX_PRIORITY; + path->weight = TB_DP_AUX_WEIGHT; - tb_path_for_each_hop(path, hop) + tb_path_for_each_hop(path, hop) { tb_dp_init_aux_credits(hop); + if (pm_support) + tb_init_pm_support(hop); + } } static int tb_dp_init_video_credits(struct tb_path_hop *hop) @@ -1216,7 +1270,7 @@ static int tb_dp_init_video_credits(struct tb_path_hop *hop) return 0; } -static int tb_dp_init_video_path(struct tb_path *path) +static int tb_dp_init_video_path(struct tb_path *path, bool pm_support) { struct tb_path_hop *hop; @@ -1224,8 +1278,8 @@ static int tb_dp_init_video_path(struct tb_path *path) path->egress_shared_buffer = TB_PATH_NONE; path->ingress_fc_enable = TB_PATH_NONE; path->ingress_shared_buffer = TB_PATH_NONE; - path->priority = 1; - path->weight = 1; + path->priority = TB_DP_VIDEO_PRIORITY; + path->weight = TB_DP_VIDEO_WEIGHT; tb_path_for_each_hop(path, hop) { int ret; @@ -1233,6 +1287,8 @@ static int tb_dp_init_video_path(struct tb_path *path) ret = tb_dp_init_video_credits(hop); if (ret) return ret; + if (pm_support) + tb_init_pm_support(hop); } return 0; @@ -1253,8 +1309,9 @@ static void tb_dp_dump(struct tb_tunnel *tunnel) rate = tb_dp_cap_get_rate(dp_cap); lanes = tb_dp_cap_get_lanes(dp_cap); - tb_port_dbg(in, "maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", - rate, lanes, tb_dp_bandwidth(rate, lanes)); + tb_tunnel_dbg(tunnel, + "DP IN maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", + rate, lanes, tb_dp_bandwidth(rate, lanes)); out = tunnel->dst_port; @@ -1265,8 +1322,9 @@ static void tb_dp_dump(struct tb_tunnel *tunnel) rate = tb_dp_cap_get_rate(dp_cap); lanes = tb_dp_cap_get_lanes(dp_cap); - tb_port_dbg(out, "maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", - rate, lanes, tb_dp_bandwidth(rate, lanes)); + tb_tunnel_dbg(tunnel, + "DP OUT maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", + rate, lanes, tb_dp_bandwidth(rate, lanes)); if (tb_port_read(in, &dp_cap, TB_CFG_PORT, in->cap_adap + DP_REMOTE_CAP, 1)) @@ -1275,8 +1333,8 @@ static void tb_dp_dump(struct tb_tunnel *tunnel) rate = tb_dp_cap_get_rate(dp_cap); lanes = tb_dp_cap_get_lanes(dp_cap); - tb_port_dbg(in, "reduced bandwidth %u Mb/s x%u = %u Mb/s\n", - rate, lanes, tb_dp_bandwidth(rate, lanes)); + tb_tunnel_dbg(tunnel, "reduced bandwidth %u Mb/s x%u = %u Mb/s\n", + rate, lanes, tb_dp_bandwidth(rate, lanes)); } /** @@ -1322,7 +1380,7 @@ struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb, struct tb_port *in, goto err_free; } tunnel->paths[TB_DP_VIDEO_PATH_OUT] = path; - if (tb_dp_init_video_path(tunnel->paths[TB_DP_VIDEO_PATH_OUT])) + if (tb_dp_init_video_path(tunnel->paths[TB_DP_VIDEO_PATH_OUT], false)) goto err_free; path = tb_path_discover(in, TB_DP_AUX_TX_HOPID, NULL, -1, NULL, "AUX TX", @@ -1330,14 +1388,14 @@ struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb, struct tb_port *in, if (!path) goto err_deactivate; tunnel->paths[TB_DP_AUX_PATH_OUT] = path; - tb_dp_init_aux_path(tunnel->paths[TB_DP_AUX_PATH_OUT]); + tb_dp_init_aux_path(tunnel->paths[TB_DP_AUX_PATH_OUT], false); path = tb_path_discover(tunnel->dst_port, -1, in, TB_DP_AUX_RX_HOPID, &port, "AUX RX", alloc_hopid); if (!path) goto err_deactivate; tunnel->paths[TB_DP_AUX_PATH_IN] = path; - tb_dp_init_aux_path(tunnel->paths[TB_DP_AUX_PATH_IN]); + tb_dp_init_aux_path(tunnel->paths[TB_DP_AUX_PATH_IN], false); /* Validate that the tunnel is complete */ if (!tb_port_is_dpout(tunnel->dst_port)) { @@ -1392,6 +1450,7 @@ struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, struct tb_port *in, struct tb_tunnel *tunnel; struct tb_path **paths; struct tb_path *path; + bool pm_support; if (WARN_ON(!in->cap_adap || !out->cap_adap)) return NULL; @@ -1413,26 +1472,27 @@ struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, struct tb_port *in, tunnel->max_down = max_down; paths = tunnel->paths; + pm_support = usb4_switch_version(in->sw) >= 2; path = tb_path_alloc(tb, in, TB_DP_VIDEO_HOPID, out, TB_DP_VIDEO_HOPID, link_nr, "Video"); if (!path) goto err_free; - tb_dp_init_video_path(path); + tb_dp_init_video_path(path, pm_support); paths[TB_DP_VIDEO_PATH_OUT] = path; path = tb_path_alloc(tb, in, TB_DP_AUX_TX_HOPID, out, TB_DP_AUX_TX_HOPID, link_nr, "AUX TX"); if (!path) goto err_free; - tb_dp_init_aux_path(path); + tb_dp_init_aux_path(path, pm_support); paths[TB_DP_AUX_PATH_OUT] = path; path = tb_path_alloc(tb, out, TB_DP_AUX_RX_HOPID, in, TB_DP_AUX_RX_HOPID, link_nr, "AUX RX"); if (!path) goto err_free; - tb_dp_init_aux_path(path); + tb_dp_init_aux_path(path, pm_support); paths[TB_DP_AUX_PATH_IN] = path; return tunnel; @@ -1497,8 +1557,8 @@ static int tb_dma_init_rx_path(struct tb_path *path, unsigned int credits) path->ingress_fc_enable = TB_PATH_ALL; path->egress_shared_buffer = TB_PATH_NONE; path->ingress_shared_buffer = TB_PATH_NONE; - path->priority = 5; - path->weight = 1; + path->priority = TB_DMA_PRIORITY; + path->weight = TB_DMA_WEIGHT; path->clear_fc = true; /* @@ -1531,8 +1591,8 @@ static int tb_dma_init_tx_path(struct tb_path *path, unsigned int credits) path->ingress_fc_enable = TB_PATH_ALL; path->egress_shared_buffer = TB_PATH_NONE; path->ingress_shared_buffer = TB_PATH_NONE; - path->priority = 5; - path->weight = 1; + path->priority = TB_DMA_PRIORITY; + path->weight = TB_DMA_WEIGHT; path->clear_fc = true; tb_path_for_each_hop(path, hop) { @@ -1758,14 +1818,23 @@ 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) { - int pcie_enabled = tb_acpi_may_tunnel_pcie(); + struct tb_port *port = tb_upstream_port(tunnel->dst_port->sw); + int pcie_weight = tb_acpi_may_tunnel_pcie() ? TB_PCI_WEIGHT : 0; /* * PCIe tunneling, if enabled, affects the USB3 bandwidth so * take that it into account here. */ - *consumed_up = tunnel->allocated_up * (3 + pcie_enabled) / 3; - *consumed_down = tunnel->allocated_down * (3 + pcie_enabled) / 3; + *consumed_up = tunnel->allocated_up * + (TB_USB3_WEIGHT + pcie_weight) / TB_USB3_WEIGHT; + *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; } @@ -1790,17 +1859,10 @@ static void tb_usb3_reclaim_available_bandwidth(struct tb_tunnel *tunnel, { int ret, max_rate, allocate_up, allocate_down; - ret = usb4_usb3_port_actual_link_rate(tunnel->src_port); + ret = tb_usb3_max_link_rate(tunnel->dst_port, tunnel->src_port); if (ret < 0) { - tb_tunnel_warn(tunnel, "failed to read actual link rate\n"); + tb_tunnel_warn(tunnel, "failed to read maximum link rate\n"); return; - } else if (!ret) { - /* Use maximum link rate if the link valid is not set */ - ret = tb_usb3_max_link_rate(tunnel->dst_port, tunnel->src_port); - if (ret < 0) { - tb_tunnel_warn(tunnel, "failed to read maximum link rate\n"); - return; - } } /* @@ -1871,8 +1933,8 @@ static void tb_usb3_init_path(struct tb_path *path) path->egress_shared_buffer = TB_PATH_NONE; path->ingress_fc_enable = TB_PATH_ALL; path->ingress_shared_buffer = TB_PATH_NONE; - path->priority = 3; - path->weight = 3; + path->priority = TB_USB3_PRIORITY; + path->weight = TB_USB3_WEIGHT; path->drop_packages = 0; tb_path_for_each_hop(path, hop) @@ -2387,3 +2449,8 @@ void tb_tunnel_reclaim_available_bandwidth(struct tb_tunnel *tunnel, tunnel->reclaim_available_bandwidth(tunnel, available_up, available_down); } + +const char *tb_tunnel_type_name(const struct tb_tunnel *tunnel) +{ + return tb_tunnel_names[tunnel->type]; +} |