Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'thunderbolt-for-v6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt into usb-next

Mika writes:

thunderbolt: Changes for v6.7 merge window

This includes following USB4/Thunderbolt changes for the v6.7 merge
window:

- Configure asymmetric link if the DisplayPort bandwidth requires so
- Enable path power management packet support for USB4 v2 routers
- Make the bandwidth reservations to follow the USB4 v2 connection
manager guide suggestions
- DisplayPort tunneling improvements
- Small cleanups and improvements around the driver.

All these have been in linux-next with no reported issues.

* tag 'thunderbolt-for-v6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt: (25 commits)
thunderbolt: Fix one kernel-doc comment
thunderbolt: Configure asymmetric link if needed and bandwidth allows
thunderbolt: Add support for asymmetric link
thunderbolt: Introduce tb_switch_depth()
thunderbolt: Introduce tb_for_each_upstream_port_on_path()
thunderbolt: Introduce tb_port_path_direction_downstream()
thunderbolt: Set path power management packet support bit for USB4 v2 routers
thunderbolt: Change bandwidth reservations to comply USB4 v2
thunderbolt: Make is_gen4_link() available to the rest of the driver
thunderbolt: Use weight constants in tb_usb3_consumed_bandwidth()
thunderbolt: Use constants for path weight and priority
thunderbolt: Add DP IN added last in the head of the list of DP resources
thunderbolt: Create multiple DisplayPort tunnels if there are more DP IN/OUT pairs
thunderbolt: Log NVM version of routers and retimers
thunderbolt: Use tb_tunnel_xxx() log macros in tb.c
thunderbolt: Expose tb_tunnel_xxx() log macros to the rest of the driver
thunderbolt: Use tb_tunnel_dbg() where possible to make logging more consistent
thunderbolt: Fix typo of HPD bit for Hot Plug Detect
thunderbolt: Fix typo in enum tb_link_width kernel-doc
thunderbolt: Fix debug log when DisplayPort adapter not available for pairing
...

+1314 -402
+25 -22
drivers/thunderbolt/clx.c
··· 175 175 } 176 176 177 177 /** 178 + * tb_switch_clx_is_supported() - Is CLx supported on this type of router 179 + * @sw: The router to check CLx support for 180 + */ 181 + static bool tb_switch_clx_is_supported(const struct tb_switch *sw) 182 + { 183 + if (!clx_enabled) 184 + return false; 185 + 186 + if (sw->quirks & QUIRK_NO_CLX) 187 + return false; 188 + 189 + /* 190 + * CLx is not enabled and validated on Intel USB4 platforms 191 + * before Alder Lake. 192 + */ 193 + if (tb_switch_is_tiger_lake(sw)) 194 + return false; 195 + 196 + return tb_switch_is_usb4(sw) || tb_switch_is_titan_ridge(sw); 197 + } 198 + 199 + /** 178 200 * tb_switch_clx_init() - Initialize router CL states 179 201 * @sw: Router 180 202 * ··· 293 271 294 272 return tb_sw_write(sw, &val, TB_CFG_SWITCH, 295 273 sw->cap_lp + offset, ARRAY_SIZE(val)); 296 - } 297 - 298 - /** 299 - * tb_switch_clx_is_supported() - Is CLx supported on this type of router 300 - * @sw: The router to check CLx support for 301 - */ 302 - bool tb_switch_clx_is_supported(const struct tb_switch *sw) 303 - { 304 - if (!clx_enabled) 305 - return false; 306 - 307 - if (sw->quirks & QUIRK_NO_CLX) 308 - return false; 309 - 310 - /* 311 - * CLx is not enabled and validated on Intel USB4 platforms 312 - * before Alder Lake. 313 - */ 314 - if (tb_switch_is_tiger_lake(sw)) 315 - return false; 316 - 317 - return tb_switch_is_usb4(sw) || tb_switch_is_titan_ridge(sw); 318 274 } 319 275 320 276 static bool validate_mask(unsigned int clx) ··· 404 404 405 405 if (!clx) 406 406 return 0; 407 + 408 + if (sw->is_unplugged) 409 + return clx; 407 410 408 411 up = tb_upstream_port(sw); 409 412 down = tb_switch_downstream_port(sw);
+5 -9
drivers/thunderbolt/dma_test.c
··· 101 101 unsigned int packets_sent; 102 102 unsigned int packets_received; 103 103 unsigned int link_speed; 104 - unsigned int link_width; 104 + enum tb_link_width link_width; 105 105 unsigned int crc_errors; 106 106 unsigned int buffer_overflow_errors; 107 107 enum dma_test_result result; ··· 465 465 static int dma_test_set_bonding(struct dma_test *dt) 466 466 { 467 467 switch (dt->link_width) { 468 - case 2: 468 + case TB_LINK_WIDTH_DUAL: 469 469 return tb_xdomain_lane_bonding_enable(dt->xd); 470 - case 1: 470 + case TB_LINK_WIDTH_SINGLE: 471 471 tb_xdomain_lane_bonding_disable(dt->xd); 472 472 fallthrough; 473 473 default: ··· 490 490 if (!dt->error_code) { 491 491 if (dt->link_speed && dt->xd->link_speed != dt->link_speed) { 492 492 dt->error_code = DMA_TEST_SPEED_ERROR; 493 - } else if (dt->link_width) { 494 - const struct tb_xdomain *xd = dt->xd; 495 - 496 - if ((dt->link_width == 1 && xd->link_width != TB_LINK_WIDTH_SINGLE) || 497 - (dt->link_width == 2 && xd->link_width < TB_LINK_WIDTH_DUAL)) 498 - dt->error_code = DMA_TEST_WIDTH_ERROR; 493 + } else if (dt->link_width && dt->link_width != dt->xd->link_width) { 494 + dt->error_code = DMA_TEST_WIDTH_ERROR; 499 495 } else if (dt->packets_to_send != dt->packets_sent || 500 496 dt->packets_to_receive != dt->packets_received || 501 497 dt->crc_errors || dt->buffer_overflow_errors) {
+4 -3
drivers/thunderbolt/path.c
··· 19 19 20 20 tb_port_dbg(port, " In HopID: %d => Out port: %d Out HopID: %d\n", 21 21 hop->in_hop_index, regs->out_port, regs->next_hop); 22 - tb_port_dbg(port, " Weight: %d Priority: %d Credits: %d Drop: %d\n", 23 - regs->weight, regs->priority, 24 - regs->initial_credits, regs->drop_packages); 22 + tb_port_dbg(port, " Weight: %d Priority: %d Credits: %d Drop: %d PM: %d\n", 23 + regs->weight, regs->priority, regs->initial_credits, 24 + regs->drop_packages, regs->pmps); 25 25 tb_port_dbg(port, " Counter enabled: %d Counter index: %d\n", 26 26 regs->counter_enable, regs->counter); 27 27 tb_port_dbg(port, " Flow Control (In/Eg): %d/%d Shared Buffer (In/Eg): %d/%d\n", ··· 535 535 hop.next_hop = path->hops[i].next_hop_index; 536 536 hop.out_port = path->hops[i].out_port->port; 537 537 hop.initial_credits = path->hops[i].initial_credits; 538 + hop.pmps = path->hops[i].pm_support; 538 539 hop.unknown1 = 0; 539 540 hop.enable = 1; 540 541
+3
drivers/thunderbolt/quirks.c
··· 31 31 { 32 32 struct tb_port *port; 33 33 34 + if (tb_switch_is_icm(sw)) 35 + return; 36 + 34 37 tb_switch_for_each_port(sw, port) { 35 38 if (!tb_port_is_usb3_down(port)) 36 39 continue;
+1
drivers/thunderbolt/retimer.c
··· 94 94 goto err_nvm; 95 95 96 96 rt->nvm = nvm; 97 + dev_dbg(&rt->dev, "NVM version %x.%x\n", nvm->major, nvm->minor); 97 98 return 0; 98 99 99 100 err_nvm:
+285 -52
drivers/thunderbolt/switch.c
··· 372 372 ret = tb_nvm_add_active(nvm, nvm_read); 373 373 if (ret) 374 374 goto err_nvm; 375 + tb_sw_dbg(sw, "NVM version %x.%x\n", nvm->major, nvm->minor); 375 376 } 376 377 377 378 if (!sw->no_nvm_upgrade) { ··· 916 915 } 917 916 918 917 /** 918 + * tb_port_get_link_generation() - Returns link generation 919 + * @port: Lane adapter 920 + * 921 + * Returns link generation as number or negative errno in case of 922 + * failure. Does not distinguish between Thunderbolt 1 and Thunderbolt 2 923 + * links so for those always returns 2. 924 + */ 925 + int tb_port_get_link_generation(struct tb_port *port) 926 + { 927 + int ret; 928 + 929 + ret = tb_port_get_link_speed(port); 930 + if (ret < 0) 931 + return ret; 932 + 933 + switch (ret) { 934 + case 40: 935 + return 4; 936 + case 20: 937 + return 3; 938 + default: 939 + return 2; 940 + } 941 + } 942 + 943 + static const char *width_name(enum tb_link_width width) 944 + { 945 + switch (width) { 946 + case TB_LINK_WIDTH_SINGLE: 947 + return "symmetric, single lane"; 948 + case TB_LINK_WIDTH_DUAL: 949 + return "symmetric, dual lanes"; 950 + case TB_LINK_WIDTH_ASYM_TX: 951 + return "asymmetric, 3 transmitters, 1 receiver"; 952 + case TB_LINK_WIDTH_ASYM_RX: 953 + return "asymmetric, 3 receivers, 1 transmitter"; 954 + default: 955 + return "unknown"; 956 + } 957 + } 958 + 959 + /** 919 960 * tb_port_get_link_width() - Get current link width 920 961 * @port: Port to check (USB4 or CIO) 921 962 * ··· 982 939 LANE_ADP_CS_1_CURRENT_WIDTH_SHIFT; 983 940 } 984 941 985 - static bool tb_port_is_width_supported(struct tb_port *port, 986 - unsigned int width_mask) 942 + /** 943 + * tb_port_width_supported() - Is the given link width supported 944 + * @port: Port to check 945 + * @width: Widths to check (bitmask) 946 + * 947 + * Can be called to any lane adapter. Checks if given @width is 948 + * supported by the hardware and returns %true if it is. 949 + */ 950 + bool tb_port_width_supported(struct tb_port *port, unsigned int width) 987 951 { 988 952 u32 phy, widths; 989 953 int ret; ··· 998 948 if (!port->cap_phy) 999 949 return false; 1000 950 951 + if (width & (TB_LINK_WIDTH_ASYM_TX | TB_LINK_WIDTH_ASYM_RX)) { 952 + if (tb_port_get_link_generation(port) < 4 || 953 + !usb4_port_asym_supported(port)) 954 + return false; 955 + } 956 + 1001 957 ret = tb_port_read(port, &phy, TB_CFG_PORT, 1002 958 port->cap_phy + LANE_ADP_CS_0, 1); 1003 959 if (ret) 1004 960 return false; 1005 961 1006 - widths = (phy & LANE_ADP_CS_0_SUPPORTED_WIDTH_MASK) >> 1007 - LANE_ADP_CS_0_SUPPORTED_WIDTH_SHIFT; 1008 - 1009 - return widths & width_mask; 1010 - } 1011 - 1012 - static bool is_gen4_link(struct tb_port *port) 1013 - { 1014 - return tb_port_get_link_speed(port) > 20; 962 + /* 963 + * The field encoding is the same as &enum tb_link_width (which is 964 + * passed to @width). 965 + */ 966 + widths = FIELD_GET(LANE_ADP_CS_0_SUPPORTED_WIDTH_MASK, phy); 967 + return widths & width; 1015 968 } 1016 969 1017 970 /** ··· 1044 991 switch (width) { 1045 992 case TB_LINK_WIDTH_SINGLE: 1046 993 /* Gen 4 link cannot be single */ 1047 - if (is_gen4_link(port)) 994 + if (tb_port_get_link_generation(port) >= 4) 1048 995 return -EOPNOTSUPP; 1049 996 val |= LANE_ADP_CS_1_TARGET_WIDTH_SINGLE << 1050 997 LANE_ADP_CS_1_TARGET_WIDTH_SHIFT; 1051 998 break; 999 + 1052 1000 case TB_LINK_WIDTH_DUAL: 1001 + if (tb_port_get_link_generation(port) >= 4) 1002 + return usb4_port_asym_set_link_width(port, width); 1053 1003 val |= LANE_ADP_CS_1_TARGET_WIDTH_DUAL << 1054 1004 LANE_ADP_CS_1_TARGET_WIDTH_SHIFT; 1055 1005 break; 1006 + 1007 + case TB_LINK_WIDTH_ASYM_TX: 1008 + case TB_LINK_WIDTH_ASYM_RX: 1009 + return usb4_port_asym_set_link_width(port, width); 1010 + 1056 1011 default: 1057 1012 return -EINVAL; 1058 1013 } ··· 1185 1124 /** 1186 1125 * tb_port_wait_for_link_width() - Wait until link reaches specific width 1187 1126 * @port: Port to wait for 1188 - * @width_mask: Expected link width mask 1127 + * @width: Expected link width (bitmask) 1189 1128 * @timeout_msec: Timeout in ms how long to wait 1190 1129 * 1191 1130 * Should be used after both ends of the link have been bonded (or ··· 1194 1133 * within the given timeout, %0 if it did. Can be passed a mask of 1195 1134 * expected widths and succeeds if any of the widths is reached. 1196 1135 */ 1197 - int tb_port_wait_for_link_width(struct tb_port *port, unsigned int width_mask, 1136 + int tb_port_wait_for_link_width(struct tb_port *port, unsigned int width, 1198 1137 int timeout_msec) 1199 1138 { 1200 1139 ktime_t timeout = ktime_add_ms(ktime_get(), timeout_msec); 1201 1140 int ret; 1202 1141 1203 1142 /* Gen 4 link does not support single lane */ 1204 - if ((width_mask & TB_LINK_WIDTH_SINGLE) && is_gen4_link(port)) 1143 + if ((width & TB_LINK_WIDTH_SINGLE) && 1144 + tb_port_get_link_generation(port) >= 4) 1205 1145 return -EOPNOTSUPP; 1206 1146 1207 1147 do { ··· 1215 1153 */ 1216 1154 if (ret != -EACCES) 1217 1155 return ret; 1218 - } else if (ret & width_mask) { 1156 + } else if (ret & width) { 1219 1157 return 0; 1220 1158 } 1221 1159 ··· 1394 1332 * tb_dp_port_hpd_is_active() - Is HPD already active 1395 1333 * @port: DP out port to check 1396 1334 * 1397 - * Checks if the DP OUT adapter port has HDP bit already set. 1335 + * Checks if the DP OUT adapter port has HPD bit already set. 1398 1336 */ 1399 1337 int tb_dp_port_hpd_is_active(struct tb_port *port) 1400 1338 { ··· 1406 1344 if (ret) 1407 1345 return ret; 1408 1346 1409 - return !!(data & ADP_DP_CS_2_HDP); 1347 + return !!(data & ADP_DP_CS_2_HPD); 1410 1348 } 1411 1349 1412 1350 /** 1413 1351 * tb_dp_port_hpd_clear() - Clear HPD from DP IN port 1414 1352 * @port: Port to clear HPD 1415 1353 * 1416 - * If the DP IN port has HDP set, this function can be used to clear it. 1354 + * If the DP IN port has HPD set, this function can be used to clear it. 1417 1355 */ 1418 1356 int tb_dp_port_hpd_clear(struct tb_port *port) 1419 1357 { ··· 1425 1363 if (ret) 1426 1364 return ret; 1427 1365 1428 - data |= ADP_DP_CS_3_HDPC; 1366 + data |= ADP_DP_CS_3_HPDC; 1429 1367 return tb_port_write(port, &data, TB_CFG_PORT, 1430 1368 port->cap_adap + ADP_DP_CS_3, 1); 1431 1369 } ··· 2759 2697 return 0; 2760 2698 } 2761 2699 2700 + /* Must be called after tb_switch_update_link_attributes() */ 2701 + static void tb_switch_link_init(struct tb_switch *sw) 2702 + { 2703 + struct tb_port *up, *down; 2704 + bool bonded; 2705 + 2706 + if (!tb_route(sw) || tb_switch_is_icm(sw)) 2707 + return; 2708 + 2709 + tb_sw_dbg(sw, "current link speed %u.0 Gb/s\n", sw->link_speed); 2710 + tb_sw_dbg(sw, "current link width %s\n", width_name(sw->link_width)); 2711 + 2712 + bonded = sw->link_width >= TB_LINK_WIDTH_DUAL; 2713 + 2714 + /* 2715 + * Gen 4 links come up as bonded so update the port structures 2716 + * accordingly. 2717 + */ 2718 + up = tb_upstream_port(sw); 2719 + down = tb_switch_downstream_port(sw); 2720 + 2721 + up->bonded = bonded; 2722 + if (up->dual_link_port) 2723 + up->dual_link_port->bonded = bonded; 2724 + tb_port_update_credits(up); 2725 + 2726 + down->bonded = bonded; 2727 + if (down->dual_link_port) 2728 + down->dual_link_port->bonded = bonded; 2729 + tb_port_update_credits(down); 2730 + } 2731 + 2762 2732 /** 2763 2733 * tb_switch_lane_bonding_enable() - Enable lane bonding 2764 2734 * @sw: Switch to enable lane bonding ··· 2799 2705 * switch. If conditions are correct and both switches support the feature, 2800 2706 * lanes are bonded. It is safe to call this to any switch. 2801 2707 */ 2802 - int tb_switch_lane_bonding_enable(struct tb_switch *sw) 2708 + static int tb_switch_lane_bonding_enable(struct tb_switch *sw) 2803 2709 { 2804 2710 struct tb_port *up, *down; 2805 - u64 route = tb_route(sw); 2806 - unsigned int width_mask; 2711 + unsigned int width; 2807 2712 int ret; 2808 - 2809 - if (!route) 2810 - return 0; 2811 2713 2812 2714 if (!tb_switch_lane_bonding_possible(sw)) 2813 2715 return 0; ··· 2811 2721 up = tb_upstream_port(sw); 2812 2722 down = tb_switch_downstream_port(sw); 2813 2723 2814 - if (!tb_port_is_width_supported(up, TB_LINK_WIDTH_DUAL) || 2815 - !tb_port_is_width_supported(down, TB_LINK_WIDTH_DUAL)) 2724 + if (!tb_port_width_supported(up, TB_LINK_WIDTH_DUAL) || 2725 + !tb_port_width_supported(down, TB_LINK_WIDTH_DUAL)) 2816 2726 return 0; 2817 2727 2818 2728 /* ··· 2836 2746 } 2837 2747 2838 2748 /* Any of the widths are all bonded */ 2839 - width_mask = TB_LINK_WIDTH_DUAL | TB_LINK_WIDTH_ASYM_TX | 2840 - TB_LINK_WIDTH_ASYM_RX; 2749 + width = TB_LINK_WIDTH_DUAL | TB_LINK_WIDTH_ASYM_TX | 2750 + TB_LINK_WIDTH_ASYM_RX; 2841 2751 2842 - ret = tb_port_wait_for_link_width(down, width_mask, 100); 2843 - if (ret) { 2844 - tb_port_warn(down, "timeout enabling lane bonding\n"); 2845 - return ret; 2846 - } 2847 - 2848 - tb_port_update_credits(down); 2849 - tb_port_update_credits(up); 2850 - tb_switch_update_link_attributes(sw); 2851 - 2852 - tb_sw_dbg(sw, "lane bonding enabled\n"); 2853 - return ret; 2752 + return tb_port_wait_for_link_width(down, width, 100); 2854 2753 } 2855 2754 2856 2755 /** ··· 2849 2770 * Disables lane bonding between @sw and parent. This can be called even 2850 2771 * if lanes were not bonded originally. 2851 2772 */ 2852 - void tb_switch_lane_bonding_disable(struct tb_switch *sw) 2773 + static int tb_switch_lane_bonding_disable(struct tb_switch *sw) 2853 2774 { 2854 2775 struct tb_port *up, *down; 2855 2776 int ret; 2856 2777 2857 - if (!tb_route(sw)) 2858 - return; 2859 - 2860 2778 up = tb_upstream_port(sw); 2861 2779 if (!up->bonded) 2862 - return; 2780 + return 0; 2781 + 2782 + /* 2783 + * If the link is Gen 4 there is no way to switch the link to 2784 + * two single lane links so avoid that here. Also don't bother 2785 + * if the link is not up anymore (sw is unplugged). 2786 + */ 2787 + ret = tb_port_get_link_generation(up); 2788 + if (ret < 0) 2789 + return ret; 2790 + if (ret >= 4) 2791 + return -EOPNOTSUPP; 2863 2792 2864 2793 down = tb_switch_downstream_port(sw); 2865 - 2866 2794 tb_port_lane_bonding_disable(up); 2867 2795 tb_port_lane_bonding_disable(down); 2868 2796 ··· 2877 2791 * It is fine if we get other errors as the router might have 2878 2792 * been unplugged. 2879 2793 */ 2880 - ret = tb_port_wait_for_link_width(down, TB_LINK_WIDTH_SINGLE, 100); 2881 - if (ret == -ETIMEDOUT) 2882 - tb_sw_warn(sw, "timeout disabling lane bonding\n"); 2794 + return tb_port_wait_for_link_width(down, TB_LINK_WIDTH_SINGLE, 100); 2795 + } 2796 + 2797 + static int tb_switch_asym_enable(struct tb_switch *sw, enum tb_link_width width) 2798 + { 2799 + struct tb_port *up, *down, *port; 2800 + enum tb_link_width down_width; 2801 + int ret; 2802 + 2803 + up = tb_upstream_port(sw); 2804 + down = tb_switch_downstream_port(sw); 2805 + 2806 + if (width == TB_LINK_WIDTH_ASYM_TX) { 2807 + down_width = TB_LINK_WIDTH_ASYM_RX; 2808 + port = down; 2809 + } else { 2810 + down_width = TB_LINK_WIDTH_ASYM_TX; 2811 + port = up; 2812 + } 2813 + 2814 + ret = tb_port_set_link_width(up, width); 2815 + if (ret) 2816 + return ret; 2817 + 2818 + ret = tb_port_set_link_width(down, down_width); 2819 + if (ret) 2820 + return ret; 2821 + 2822 + /* 2823 + * Initiate the change in the router that one of its TX lanes is 2824 + * changing to RX but do so only if there is an actual change. 2825 + */ 2826 + if (sw->link_width != width) { 2827 + ret = usb4_port_asym_start(port); 2828 + if (ret) 2829 + return ret; 2830 + 2831 + ret = tb_port_wait_for_link_width(up, width, 100); 2832 + if (ret) 2833 + return ret; 2834 + } 2835 + 2836 + sw->link_width = width; 2837 + return 0; 2838 + } 2839 + 2840 + static int tb_switch_asym_disable(struct tb_switch *sw) 2841 + { 2842 + struct tb_port *up, *down; 2843 + int ret; 2844 + 2845 + up = tb_upstream_port(sw); 2846 + down = tb_switch_downstream_port(sw); 2847 + 2848 + ret = tb_port_set_link_width(up, TB_LINK_WIDTH_DUAL); 2849 + if (ret) 2850 + return ret; 2851 + 2852 + ret = tb_port_set_link_width(down, TB_LINK_WIDTH_DUAL); 2853 + if (ret) 2854 + return ret; 2855 + 2856 + /* 2857 + * Initiate the change in the router that has three TX lanes and 2858 + * is changing one of its TX lanes to RX but only if there is a 2859 + * change in the link width. 2860 + */ 2861 + if (sw->link_width > TB_LINK_WIDTH_DUAL) { 2862 + if (sw->link_width == TB_LINK_WIDTH_ASYM_TX) 2863 + ret = usb4_port_asym_start(up); 2864 + else 2865 + ret = usb4_port_asym_start(down); 2866 + if (ret) 2867 + return ret; 2868 + 2869 + ret = tb_port_wait_for_link_width(up, TB_LINK_WIDTH_DUAL, 100); 2870 + if (ret) 2871 + return ret; 2872 + } 2873 + 2874 + sw->link_width = TB_LINK_WIDTH_DUAL; 2875 + return 0; 2876 + } 2877 + 2878 + /** 2879 + * tb_switch_set_link_width() - Configure router link width 2880 + * @sw: Router to configure 2881 + * @width: The new link width 2882 + * 2883 + * Set device router link width to @width from router upstream port 2884 + * perspective. Supports also asymmetric links if the routers boths side 2885 + * of the link supports it. 2886 + * 2887 + * Does nothing for host router. 2888 + * 2889 + * Returns %0 in case of success, negative errno otherwise. 2890 + */ 2891 + int tb_switch_set_link_width(struct tb_switch *sw, enum tb_link_width width) 2892 + { 2893 + struct tb_port *up, *down; 2894 + int ret = 0; 2895 + 2896 + if (!tb_route(sw)) 2897 + return 0; 2898 + 2899 + up = tb_upstream_port(sw); 2900 + down = tb_switch_downstream_port(sw); 2901 + 2902 + switch (width) { 2903 + case TB_LINK_WIDTH_SINGLE: 2904 + ret = tb_switch_lane_bonding_disable(sw); 2905 + break; 2906 + 2907 + case TB_LINK_WIDTH_DUAL: 2908 + if (sw->link_width == TB_LINK_WIDTH_ASYM_TX || 2909 + sw->link_width == TB_LINK_WIDTH_ASYM_RX) { 2910 + ret = tb_switch_asym_disable(sw); 2911 + if (ret) 2912 + break; 2913 + } 2914 + ret = tb_switch_lane_bonding_enable(sw); 2915 + break; 2916 + 2917 + case TB_LINK_WIDTH_ASYM_TX: 2918 + case TB_LINK_WIDTH_ASYM_RX: 2919 + ret = tb_switch_asym_enable(sw, width); 2920 + break; 2921 + } 2922 + 2923 + switch (ret) { 2924 + case 0: 2925 + break; 2926 + 2927 + case -ETIMEDOUT: 2928 + tb_sw_warn(sw, "timeout changing link width\n"); 2929 + return ret; 2930 + 2931 + case -ENOTCONN: 2932 + case -EOPNOTSUPP: 2933 + case -ENODEV: 2934 + return ret; 2935 + 2936 + default: 2937 + tb_sw_dbg(sw, "failed to change link width: %d\n", ret); 2938 + return ret; 2939 + } 2883 2940 2884 2941 tb_port_update_credits(down); 2885 2942 tb_port_update_credits(up); 2943 + 2886 2944 tb_switch_update_link_attributes(sw); 2887 2945 2888 - tb_sw_dbg(sw, "lane bonding disabled\n"); 2946 + tb_sw_dbg(sw, "link width set to %s\n", width_name(width)); 2947 + return ret; 2889 2948 } 2890 2949 2891 2950 /** ··· 3189 2958 ret = tb_switch_update_link_attributes(sw); 3190 2959 if (ret) 3191 2960 return ret; 2961 + 2962 + tb_switch_link_init(sw); 3192 2963 3193 2964 ret = tb_switch_clx_init(sw); 3194 2965 if (ret)
+632 -170
drivers/thunderbolt/tb.c
··· 16 16 #include "tb_regs.h" 17 17 #include "tunnel.h" 18 18 19 - #define TB_TIMEOUT 100 /* ms */ 20 - #define MAX_GROUPS 7 /* max Group_ID is 7 */ 19 + #define TB_TIMEOUT 100 /* ms */ 20 + 21 + /* 22 + * Minimum bandwidth (in Mb/s) that is needed in the single transmitter/receiver 23 + * direction. This is 40G - 10% guard band bandwidth. 24 + */ 25 + #define TB_ASYM_MIN (40000 * 90 / 100) 26 + 27 + /* 28 + * Threshold bandwidth (in Mb/s) that is used to switch the links to 29 + * asymmetric and back. This is selected as 45G which means when the 30 + * request is higher than this, we switch the link to asymmetric, and 31 + * when it is less than this we switch it back. The 45G is selected so 32 + * that we still have 27G (of the total 72G) for bulk PCIe traffic when 33 + * switching back to symmetric. 34 + */ 35 + #define TB_ASYM_THRESHOLD 45000 36 + 37 + #define MAX_GROUPS 7 /* max Group_ID is 7 */ 38 + 39 + static unsigned int asym_threshold = TB_ASYM_THRESHOLD; 40 + module_param_named(asym_threshold, asym_threshold, uint, 0444); 41 + MODULE_PARM_DESC(asym_threshold, 42 + "threshold (Mb/s) when to Gen 4 switch link symmetry. 0 disables. (default: " 43 + __MODULE_STRING(TB_ASYM_THRESHOLD) ")"); 21 44 22 45 /** 23 46 * struct tb_cm - Simple Thunderbolt connection manager ··· 213 190 if (!tb_switch_query_dp_resource(sw, port)) 214 191 continue; 215 192 216 - list_add_tail(&port->list, &tcm->dp_resources); 193 + list_add(&port->list, &tcm->dp_resources); 217 194 tb_port_dbg(port, "DP IN resource available\n"); 218 195 } 219 196 } ··· 278 255 * this in the future to cover the whole topology if it turns 279 256 * out to be beneficial. 280 257 */ 281 - while (sw && sw->config.depth > 1) 258 + while (sw && tb_switch_depth(sw) > 1) 282 259 sw = tb_switch_parent(sw); 283 260 284 261 if (!sw) 285 262 return 0; 286 263 287 - if (sw->config.depth != 1) 264 + if (tb_switch_depth(sw) != 1) 288 265 return 0; 289 266 290 267 /* ··· 308 285 return ret == -EOPNOTSUPP ? 0 : ret; 309 286 } 310 287 311 - /* Disables CL states up to the host router */ 312 - static void tb_disable_clx(struct tb_switch *sw) 288 + /** 289 + * tb_disable_clx() - Disable CL states up to host router 290 + * @sw: Router to start 291 + * 292 + * Disables CL states from @sw up to the host router. Returns true if 293 + * any CL state were disabled. This can be used to figure out whether 294 + * the link was setup by us or the boot firmware so we don't 295 + * accidentally enable them if they were not enabled during discovery. 296 + */ 297 + static bool tb_disable_clx(struct tb_switch *sw) 313 298 { 299 + bool disabled = false; 300 + 314 301 do { 315 - if (tb_switch_clx_disable(sw) < 0) 302 + int ret; 303 + 304 + ret = tb_switch_clx_disable(sw); 305 + if (ret > 0) 306 + disabled = true; 307 + else if (ret < 0) 316 308 tb_sw_warn(sw, "failed to disable CL states\n"); 309 + 317 310 sw = tb_switch_parent(sw); 318 311 } while (sw); 312 + 313 + return disabled; 319 314 } 320 315 321 316 static int tb_increase_switch_tmu_accuracy(struct device *dev, void *data) ··· 594 553 struct tb_switch *sw; 595 554 596 555 /* Pick the router that is deepest in the topology */ 597 - if (dst_port->sw->config.depth > src_port->sw->config.depth) 556 + if (tb_port_path_direction_downstream(src_port, dst_port)) 598 557 sw = dst_port->sw; 599 558 else 600 559 sw = src_port->sw; ··· 613 572 return tb_find_tunnel(tb, TB_TUNNEL_USB3, usb3_down, NULL); 614 573 } 615 574 616 - static int tb_available_bandwidth(struct tb *tb, struct tb_port *src_port, 617 - struct tb_port *dst_port, int *available_up, int *available_down) 575 + /** 576 + * tb_consumed_usb3_pcie_bandwidth() - Consumed USB3/PCIe bandwidth over a single link 577 + * @tb: Domain structure 578 + * @src_port: Source protocol adapter 579 + * @dst_port: Destination protocol adapter 580 + * @port: USB4 port the consumed bandwidth is calculated 581 + * @consumed_up: Consumed upsream bandwidth (Mb/s) 582 + * @consumed_down: Consumed downstream bandwidth (Mb/s) 583 + * 584 + * Calculates consumed USB3 and PCIe bandwidth at @port between path 585 + * from @src_port to @dst_port. Does not take tunnel starting from 586 + * @src_port and ending from @src_port into account. 587 + */ 588 + static int tb_consumed_usb3_pcie_bandwidth(struct tb *tb, 589 + struct tb_port *src_port, 590 + struct tb_port *dst_port, 591 + struct tb_port *port, 592 + int *consumed_up, 593 + int *consumed_down) 618 594 { 619 - int usb3_consumed_up, usb3_consumed_down, ret; 620 - struct tb_cm *tcm = tb_priv(tb); 595 + int pci_consumed_up, pci_consumed_down; 621 596 struct tb_tunnel *tunnel; 622 - struct tb_port *port; 623 597 624 - tb_dbg(tb, "calculating available bandwidth between %llx:%u <-> %llx:%u\n", 625 - tb_route(src_port->sw), src_port->port, tb_route(dst_port->sw), 626 - dst_port->port); 598 + *consumed_up = *consumed_down = 0; 627 599 628 600 tunnel = tb_find_first_usb3_tunnel(tb, src_port, dst_port); 629 601 if (tunnel && tunnel->src_port != src_port && 630 602 tunnel->dst_port != dst_port) { 631 - ret = tb_tunnel_consumed_bandwidth(tunnel, &usb3_consumed_up, 632 - &usb3_consumed_down); 603 + int ret; 604 + 605 + ret = tb_tunnel_consumed_bandwidth(tunnel, consumed_up, 606 + consumed_down); 633 607 if (ret) 634 608 return ret; 635 - } else { 636 - usb3_consumed_up = 0; 637 - usb3_consumed_down = 0; 638 609 } 610 + 611 + /* 612 + * If there is anything reserved for PCIe bulk traffic take it 613 + * into account here too. 614 + */ 615 + if (tb_tunnel_reserved_pci(port, &pci_consumed_up, &pci_consumed_down)) { 616 + *consumed_up += pci_consumed_up; 617 + *consumed_down += pci_consumed_down; 618 + } 619 + 620 + return 0; 621 + } 622 + 623 + /** 624 + * tb_consumed_dp_bandwidth() - Consumed DP bandwidth over a single link 625 + * @tb: Domain structure 626 + * @src_port: Source protocol adapter 627 + * @dst_port: Destination protocol adapter 628 + * @port: USB4 port the consumed bandwidth is calculated 629 + * @consumed_up: Consumed upsream bandwidth (Mb/s) 630 + * @consumed_down: Consumed downstream bandwidth (Mb/s) 631 + * 632 + * Calculates consumed DP bandwidth at @port between path from @src_port 633 + * to @dst_port. Does not take tunnel starting from @src_port and ending 634 + * from @src_port into account. 635 + */ 636 + static int tb_consumed_dp_bandwidth(struct tb *tb, 637 + struct tb_port *src_port, 638 + struct tb_port *dst_port, 639 + struct tb_port *port, 640 + int *consumed_up, 641 + int *consumed_down) 642 + { 643 + struct tb_cm *tcm = tb_priv(tb); 644 + struct tb_tunnel *tunnel; 645 + int ret; 646 + 647 + *consumed_up = *consumed_down = 0; 648 + 649 + /* 650 + * Find all DP tunnels that cross the port and reduce 651 + * their consumed bandwidth from the available. 652 + */ 653 + list_for_each_entry(tunnel, &tcm->tunnel_list, list) { 654 + int dp_consumed_up, dp_consumed_down; 655 + 656 + if (tb_tunnel_is_invalid(tunnel)) 657 + continue; 658 + 659 + if (!tb_tunnel_is_dp(tunnel)) 660 + continue; 661 + 662 + if (!tb_tunnel_port_on_path(tunnel, port)) 663 + continue; 664 + 665 + /* 666 + * Ignore the DP tunnel between src_port and dst_port 667 + * because it is the same tunnel and we may be 668 + * re-calculating estimated bandwidth. 669 + */ 670 + if (tunnel->src_port == src_port && 671 + tunnel->dst_port == dst_port) 672 + continue; 673 + 674 + ret = tb_tunnel_consumed_bandwidth(tunnel, &dp_consumed_up, 675 + &dp_consumed_down); 676 + if (ret) 677 + return ret; 678 + 679 + *consumed_up += dp_consumed_up; 680 + *consumed_down += dp_consumed_down; 681 + } 682 + 683 + return 0; 684 + } 685 + 686 + static bool tb_asym_supported(struct tb_port *src_port, struct tb_port *dst_port, 687 + struct tb_port *port) 688 + { 689 + bool downstream = tb_port_path_direction_downstream(src_port, dst_port); 690 + enum tb_link_width width; 691 + 692 + if (tb_is_upstream_port(port)) 693 + width = downstream ? TB_LINK_WIDTH_ASYM_RX : TB_LINK_WIDTH_ASYM_TX; 694 + else 695 + width = downstream ? TB_LINK_WIDTH_ASYM_TX : TB_LINK_WIDTH_ASYM_RX; 696 + 697 + return tb_port_width_supported(port, width); 698 + } 699 + 700 + /** 701 + * tb_maximum_bandwidth() - Maximum bandwidth over a single link 702 + * @tb: Domain structure 703 + * @src_port: Source protocol adapter 704 + * @dst_port: Destination protocol adapter 705 + * @port: USB4 port the total bandwidth is calculated 706 + * @max_up: Maximum upstream bandwidth (Mb/s) 707 + * @max_down: Maximum downstream bandwidth (Mb/s) 708 + * @include_asym: Include bandwidth if the link is switched from 709 + * symmetric to asymmetric 710 + * 711 + * Returns maximum possible bandwidth in @max_up and @max_down over a 712 + * single link at @port. If @include_asym is set then includes the 713 + * additional banwdith if the links are transitioned into asymmetric to 714 + * direction from @src_port to @dst_port. 715 + */ 716 + static int tb_maximum_bandwidth(struct tb *tb, struct tb_port *src_port, 717 + struct tb_port *dst_port, struct tb_port *port, 718 + int *max_up, int *max_down, bool include_asym) 719 + { 720 + bool downstream = tb_port_path_direction_downstream(src_port, dst_port); 721 + int link_speed, link_width, up_bw, down_bw; 722 + 723 + /* 724 + * Can include asymmetric, only if it is actually supported by 725 + * the lane adapter. 726 + */ 727 + if (!tb_asym_supported(src_port, dst_port, port)) 728 + include_asym = false; 729 + 730 + if (tb_is_upstream_port(port)) { 731 + link_speed = port->sw->link_speed; 732 + /* 733 + * sw->link_width is from upstream perspective so we use 734 + * the opposite for downstream of the host router. 735 + */ 736 + if (port->sw->link_width == TB_LINK_WIDTH_ASYM_TX) { 737 + up_bw = link_speed * 3 * 1000; 738 + down_bw = link_speed * 1 * 1000; 739 + } else if (port->sw->link_width == TB_LINK_WIDTH_ASYM_RX) { 740 + up_bw = link_speed * 1 * 1000; 741 + down_bw = link_speed * 3 * 1000; 742 + } else if (include_asym) { 743 + /* 744 + * The link is symmetric at the moment but we 745 + * can switch it to asymmetric as needed. Report 746 + * this bandwidth as available (even though it 747 + * is not yet enabled). 748 + */ 749 + if (downstream) { 750 + up_bw = link_speed * 1 * 1000; 751 + down_bw = link_speed * 3 * 1000; 752 + } else { 753 + up_bw = link_speed * 3 * 1000; 754 + down_bw = link_speed * 1 * 1000; 755 + } 756 + } else { 757 + up_bw = link_speed * port->sw->link_width * 1000; 758 + down_bw = up_bw; 759 + } 760 + } else { 761 + link_speed = tb_port_get_link_speed(port); 762 + if (link_speed < 0) 763 + return link_speed; 764 + 765 + link_width = tb_port_get_link_width(port); 766 + if (link_width < 0) 767 + return link_width; 768 + 769 + if (link_width == TB_LINK_WIDTH_ASYM_TX) { 770 + up_bw = link_speed * 1 * 1000; 771 + down_bw = link_speed * 3 * 1000; 772 + } else if (link_width == TB_LINK_WIDTH_ASYM_RX) { 773 + up_bw = link_speed * 3 * 1000; 774 + down_bw = link_speed * 1 * 1000; 775 + } else if (include_asym) { 776 + /* 777 + * The link is symmetric at the moment but we 778 + * can switch it to asymmetric as needed. Report 779 + * this bandwidth as available (even though it 780 + * is not yet enabled). 781 + */ 782 + if (downstream) { 783 + up_bw = link_speed * 1 * 1000; 784 + down_bw = link_speed * 3 * 1000; 785 + } else { 786 + up_bw = link_speed * 3 * 1000; 787 + down_bw = link_speed * 1 * 1000; 788 + } 789 + } else { 790 + up_bw = link_speed * link_width * 1000; 791 + down_bw = up_bw; 792 + } 793 + } 794 + 795 + /* Leave 10% guard band */ 796 + *max_up = up_bw - up_bw / 10; 797 + *max_down = down_bw - down_bw / 10; 798 + 799 + tb_port_dbg(port, "link maximum bandwidth %d/%d Mb/s\n", *max_up, *max_down); 800 + return 0; 801 + } 802 + 803 + /** 804 + * tb_available_bandwidth() - Available bandwidth for tunneling 805 + * @tb: Domain structure 806 + * @src_port: Source protocol adapter 807 + * @dst_port: Destination protocol adapter 808 + * @available_up: Available bandwidth upstream (Mb/s) 809 + * @available_down: Available bandwidth downstream (Mb/s) 810 + * @include_asym: Include bandwidth if the link is switched from 811 + * symmetric to asymmetric 812 + * 813 + * Calculates maximum available bandwidth for protocol tunneling between 814 + * @src_port and @dst_port at the moment. This is minimum of maximum 815 + * link bandwidth across all links reduced by currently consumed 816 + * bandwidth on that link. 817 + * 818 + * If @include_asym is true then includes also bandwidth that can be 819 + * added when the links are transitioned into asymmetric (but does not 820 + * transition the links). 821 + */ 822 + static int tb_available_bandwidth(struct tb *tb, struct tb_port *src_port, 823 + struct tb_port *dst_port, int *available_up, 824 + int *available_down, bool include_asym) 825 + { 826 + struct tb_port *port; 827 + int ret; 639 828 640 829 /* Maximum possible bandwidth asymmetric Gen 4 link is 120 Gb/s */ 641 830 *available_up = *available_down = 120000; 642 831 643 832 /* Find the minimum available bandwidth over all links */ 644 833 tb_for_each_port_on_path(src_port, dst_port, port) { 645 - int link_speed, link_width, up_bw, down_bw; 834 + int max_up, max_down, consumed_up, consumed_down; 646 835 647 836 if (!tb_port_is_null(port)) 648 837 continue; 649 838 650 - if (tb_is_upstream_port(port)) { 651 - link_speed = port->sw->link_speed; 652 - /* 653 - * sw->link_width is from upstream perspective 654 - * so we use the opposite for downstream of the 655 - * host router. 656 - */ 657 - if (port->sw->link_width == TB_LINK_WIDTH_ASYM_TX) { 658 - up_bw = link_speed * 3 * 1000; 659 - down_bw = link_speed * 1 * 1000; 660 - } else if (port->sw->link_width == TB_LINK_WIDTH_ASYM_RX) { 661 - up_bw = link_speed * 1 * 1000; 662 - down_bw = link_speed * 3 * 1000; 663 - } else { 664 - up_bw = link_speed * port->sw->link_width * 1000; 665 - down_bw = up_bw; 666 - } 667 - } else { 668 - link_speed = tb_port_get_link_speed(port); 669 - if (link_speed < 0) 670 - return link_speed; 839 + ret = tb_maximum_bandwidth(tb, src_port, dst_port, port, 840 + &max_up, &max_down, include_asym); 841 + if (ret) 842 + return ret; 671 843 672 - link_width = tb_port_get_link_width(port); 673 - if (link_width < 0) 674 - return link_width; 844 + ret = tb_consumed_usb3_pcie_bandwidth(tb, src_port, dst_port, 845 + port, &consumed_up, 846 + &consumed_down); 847 + if (ret) 848 + return ret; 849 + max_up -= consumed_up; 850 + max_down -= consumed_down; 675 851 676 - if (link_width == TB_LINK_WIDTH_ASYM_TX) { 677 - up_bw = link_speed * 1 * 1000; 678 - down_bw = link_speed * 3 * 1000; 679 - } else if (link_width == TB_LINK_WIDTH_ASYM_RX) { 680 - up_bw = link_speed * 3 * 1000; 681 - down_bw = link_speed * 1 * 1000; 682 - } else { 683 - up_bw = link_speed * link_width * 1000; 684 - down_bw = up_bw; 685 - } 686 - } 852 + ret = tb_consumed_dp_bandwidth(tb, src_port, dst_port, port, 853 + &consumed_up, &consumed_down); 854 + if (ret) 855 + return ret; 856 + max_up -= consumed_up; 857 + max_down -= consumed_down; 687 858 688 - /* Leave 10% guard band */ 689 - up_bw -= up_bw / 10; 690 - down_bw -= down_bw / 10; 691 - 692 - tb_port_dbg(port, "link total bandwidth %d/%d Mb/s\n", up_bw, 693 - down_bw); 694 - 695 - /* 696 - * Find all DP tunnels that cross the port and reduce 697 - * their consumed bandwidth from the available. 698 - */ 699 - list_for_each_entry(tunnel, &tcm->tunnel_list, list) { 700 - int dp_consumed_up, dp_consumed_down; 701 - 702 - if (tb_tunnel_is_invalid(tunnel)) 703 - continue; 704 - 705 - if (!tb_tunnel_is_dp(tunnel)) 706 - continue; 707 - 708 - if (!tb_tunnel_port_on_path(tunnel, port)) 709 - continue; 710 - 711 - /* 712 - * Ignore the DP tunnel between src_port and 713 - * dst_port because it is the same tunnel and we 714 - * may be re-calculating estimated bandwidth. 715 - */ 716 - if (tunnel->src_port == src_port && 717 - tunnel->dst_port == dst_port) 718 - continue; 719 - 720 - ret = tb_tunnel_consumed_bandwidth(tunnel, 721 - &dp_consumed_up, 722 - &dp_consumed_down); 723 - if (ret) 724 - return ret; 725 - 726 - up_bw -= dp_consumed_up; 727 - down_bw -= dp_consumed_down; 728 - } 729 - 730 - /* 731 - * If USB3 is tunneled from the host router down to the 732 - * branch leading to port we need to take USB3 consumed 733 - * bandwidth into account regardless whether it actually 734 - * crosses the port. 735 - */ 736 - up_bw -= usb3_consumed_up; 737 - down_bw -= usb3_consumed_down; 738 - 739 - if (up_bw < *available_up) 740 - *available_up = up_bw; 741 - if (down_bw < *available_down) 742 - *available_down = down_bw; 859 + if (max_up < *available_up) 860 + *available_up = max_up; 861 + if (max_down < *available_down) 862 + *available_down = max_down; 743 863 } 744 864 745 865 if (*available_up < 0) ··· 931 729 if (!tunnel) 932 730 return; 933 731 934 - tb_dbg(tb, "reclaiming unused bandwidth for USB3\n"); 732 + tb_tunnel_dbg(tunnel, "reclaiming unused bandwidth\n"); 935 733 936 734 /* 937 735 * Calculate available bandwidth for the first hop USB3 tunnel. 938 736 * That determines the whole USB3 bandwidth for this branch. 939 737 */ 940 738 ret = tb_available_bandwidth(tb, tunnel->src_port, tunnel->dst_port, 941 - &available_up, &available_down); 739 + &available_up, &available_down, false); 942 740 if (ret) { 943 - tb_warn(tb, "failed to calculate available bandwidth\n"); 741 + tb_tunnel_warn(tunnel, "failed to calculate available bandwidth\n"); 944 742 return; 945 743 } 946 744 947 - tb_dbg(tb, "available bandwidth for USB3 %d/%d Mb/s\n", 948 - available_up, available_down); 745 + tb_tunnel_dbg(tunnel, "available bandwidth %d/%d Mb/s\n", available_up, 746 + available_down); 949 747 950 748 tb_tunnel_reclaim_available_bandwidth(tunnel, &available_up, &available_down); 951 749 } ··· 996 794 return ret; 997 795 } 998 796 999 - ret = tb_available_bandwidth(tb, down, up, &available_up, 1000 - &available_down); 797 + ret = tb_available_bandwidth(tb, down, up, &available_up, &available_down, 798 + false); 1001 799 if (ret) 1002 800 goto err_reclaim; 1003 801 ··· 1056 854 } 1057 855 1058 856 return 0; 857 + } 858 + 859 + /** 860 + * tb_configure_asym() - Transition links to asymmetric if needed 861 + * @tb: Domain structure 862 + * @src_port: Source adapter to start the transition 863 + * @dst_port: Destination adapter 864 + * @requested_up: Additional bandwidth (Mb/s) required upstream 865 + * @requested_down: Additional bandwidth (Mb/s) required downstream 866 + * 867 + * Transition links between @src_port and @dst_port into asymmetric, with 868 + * three lanes in the direction from @src_port towards @dst_port and one lane 869 + * in the opposite direction, if the bandwidth requirements 870 + * (requested + currently consumed) on that link exceed @asym_threshold. 871 + * 872 + * Must be called with available >= requested over all links. 873 + */ 874 + static int tb_configure_asym(struct tb *tb, struct tb_port *src_port, 875 + struct tb_port *dst_port, int requested_up, 876 + int requested_down) 877 + { 878 + struct tb_switch *sw; 879 + bool clx, downstream; 880 + struct tb_port *up; 881 + int ret = 0; 882 + 883 + if (!asym_threshold) 884 + return 0; 885 + 886 + /* Disable CL states before doing any transitions */ 887 + downstream = tb_port_path_direction_downstream(src_port, dst_port); 888 + /* Pick up router deepest in the hierarchy */ 889 + if (downstream) 890 + sw = dst_port->sw; 891 + else 892 + sw = src_port->sw; 893 + 894 + clx = tb_disable_clx(sw); 895 + 896 + tb_for_each_upstream_port_on_path(src_port, dst_port, up) { 897 + int consumed_up, consumed_down; 898 + enum tb_link_width width; 899 + 900 + ret = tb_consumed_dp_bandwidth(tb, src_port, dst_port, up, 901 + &consumed_up, &consumed_down); 902 + if (ret) 903 + break; 904 + 905 + if (downstream) { 906 + /* 907 + * Downstream so make sure upstream is within the 36G 908 + * (40G - guard band 10%), and the requested is above 909 + * what the threshold is. 910 + */ 911 + if (consumed_up + requested_up >= TB_ASYM_MIN) { 912 + ret = -ENOBUFS; 913 + break; 914 + } 915 + /* Does consumed + requested exceed the threshold */ 916 + if (consumed_down + requested_down < asym_threshold) 917 + continue; 918 + 919 + width = TB_LINK_WIDTH_ASYM_RX; 920 + } else { 921 + /* Upstream, the opposite of above */ 922 + if (consumed_down + requested_down >= TB_ASYM_MIN) { 923 + ret = -ENOBUFS; 924 + break; 925 + } 926 + if (consumed_up + requested_up < asym_threshold) 927 + continue; 928 + 929 + width = TB_LINK_WIDTH_ASYM_TX; 930 + } 931 + 932 + if (up->sw->link_width == width) 933 + continue; 934 + 935 + if (!tb_port_width_supported(up, width)) 936 + continue; 937 + 938 + tb_sw_dbg(up->sw, "configuring asymmetric link\n"); 939 + 940 + /* 941 + * Here requested + consumed > threshold so we need to 942 + * transtion the link into asymmetric now. 943 + */ 944 + ret = tb_switch_set_link_width(up->sw, width); 945 + if (ret) { 946 + tb_sw_warn(up->sw, "failed to set link width\n"); 947 + break; 948 + } 949 + } 950 + 951 + /* Re-enable CL states if they were previosly enabled */ 952 + if (clx) 953 + tb_enable_clx(sw); 954 + 955 + return ret; 956 + } 957 + 958 + /** 959 + * tb_configure_sym() - Transition links to symmetric if possible 960 + * @tb: Domain structure 961 + * @src_port: Source adapter to start the transition 962 + * @dst_port: Destination adapter 963 + * @requested_up: New lower bandwidth request upstream (Mb/s) 964 + * @requested_down: New lower bandwidth request downstream (Mb/s) 965 + * 966 + * Goes over each link from @src_port to @dst_port and tries to 967 + * transition the link to symmetric if the currently consumed bandwidth 968 + * allows. 969 + */ 970 + static int tb_configure_sym(struct tb *tb, struct tb_port *src_port, 971 + struct tb_port *dst_port, int requested_up, 972 + int requested_down) 973 + { 974 + struct tb_switch *sw; 975 + bool clx, downstream; 976 + struct tb_port *up; 977 + int ret = 0; 978 + 979 + if (!asym_threshold) 980 + return 0; 981 + 982 + /* Disable CL states before doing any transitions */ 983 + downstream = tb_port_path_direction_downstream(src_port, dst_port); 984 + /* Pick up router deepest in the hierarchy */ 985 + if (downstream) 986 + sw = dst_port->sw; 987 + else 988 + sw = src_port->sw; 989 + 990 + clx = tb_disable_clx(sw); 991 + 992 + tb_for_each_upstream_port_on_path(src_port, dst_port, up) { 993 + int consumed_up, consumed_down; 994 + 995 + /* Already symmetric */ 996 + if (up->sw->link_width <= TB_LINK_WIDTH_DUAL) 997 + continue; 998 + /* Unplugged, no need to switch */ 999 + if (up->sw->is_unplugged) 1000 + continue; 1001 + 1002 + ret = tb_consumed_dp_bandwidth(tb, src_port, dst_port, up, 1003 + &consumed_up, &consumed_down); 1004 + if (ret) 1005 + break; 1006 + 1007 + if (downstream) { 1008 + /* 1009 + * Downstream so we want the consumed_down < threshold. 1010 + * Upstream traffic should be less than 36G (40G 1011 + * guard band 10%) as the link was configured asymmetric 1012 + * already. 1013 + */ 1014 + if (consumed_down + requested_down >= asym_threshold) 1015 + continue; 1016 + } else { 1017 + if (consumed_up + requested_up >= asym_threshold) 1018 + continue; 1019 + } 1020 + 1021 + if (up->sw->link_width == TB_LINK_WIDTH_DUAL) 1022 + continue; 1023 + 1024 + tb_sw_dbg(up->sw, "configuring symmetric link\n"); 1025 + 1026 + ret = tb_switch_set_link_width(up->sw, TB_LINK_WIDTH_DUAL); 1027 + if (ret) { 1028 + tb_sw_warn(up->sw, "failed to set link width\n"); 1029 + break; 1030 + } 1031 + } 1032 + 1033 + /* Re-enable CL states if they were previosly enabled */ 1034 + if (clx) 1035 + tb_enable_clx(sw); 1036 + 1037 + return ret; 1038 + } 1039 + 1040 + static void tb_configure_link(struct tb_port *down, struct tb_port *up, 1041 + struct tb_switch *sw) 1042 + { 1043 + struct tb *tb = sw->tb; 1044 + 1045 + /* Link the routers using both links if available */ 1046 + down->remote = up; 1047 + up->remote = down; 1048 + if (down->dual_link_port && up->dual_link_port) { 1049 + down->dual_link_port->remote = up->dual_link_port; 1050 + up->dual_link_port->remote = down->dual_link_port; 1051 + } 1052 + 1053 + /* 1054 + * Enable lane bonding if the link is currently two single lane 1055 + * links. 1056 + */ 1057 + if (sw->link_width < TB_LINK_WIDTH_DUAL) 1058 + tb_switch_set_link_width(sw, TB_LINK_WIDTH_DUAL); 1059 + 1060 + /* 1061 + * Device router that comes up as symmetric link is 1062 + * connected deeper in the hierarchy, we transition the links 1063 + * above into symmetric if bandwidth allows. 1064 + */ 1065 + if (tb_switch_depth(sw) > 1 && 1066 + tb_port_get_link_generation(up) >= 4 && 1067 + up->sw->link_width == TB_LINK_WIDTH_DUAL) { 1068 + struct tb_port *host_port; 1069 + 1070 + host_port = tb_port_at(tb_route(sw), tb->root_switch); 1071 + tb_configure_sym(tb, host_port, up, 0, 0); 1072 + } 1073 + 1074 + /* Set the link configured */ 1075 + tb_switch_configure_link(sw); 1059 1076 } 1060 1077 1061 1078 static void tb_scan_port(struct tb_port *port); ··· 1385 964 goto out_rpm_put; 1386 965 } 1387 966 1388 - /* Link the switches using both links if available */ 1389 967 upstream_port = tb_upstream_port(sw); 1390 - port->remote = upstream_port; 1391 - upstream_port->remote = port; 1392 - if (port->dual_link_port && upstream_port->dual_link_port) { 1393 - port->dual_link_port->remote = upstream_port->dual_link_port; 1394 - upstream_port->dual_link_port->remote = port->dual_link_port; 1395 - } 968 + tb_configure_link(port, upstream_port, sw); 1396 969 1397 - /* Enable lane bonding if supported */ 1398 - tb_switch_lane_bonding_enable(sw); 1399 - /* Set the link configured */ 1400 - tb_switch_configure_link(sw); 1401 970 /* 1402 971 * CL0s and CL1 are enabled and supported together. 1403 972 * Silently ignore CLx enabling in case CLx is not supported. ··· 1451 1040 * deallocated properly. 1452 1041 */ 1453 1042 tb_switch_dealloc_dp_resource(src_port->sw, src_port); 1043 + /* 1044 + * If bandwidth on a link is < asym_threshold 1045 + * transition the link to symmetric. 1046 + */ 1047 + tb_configure_sym(tb, src_port, dst_port, 0, 0); 1454 1048 /* Now we can allow the domain to runtime suspend again */ 1455 1049 pm_runtime_mark_last_busy(&dst_port->sw->dev); 1456 1050 pm_runtime_put_autosuspend(&dst_port->sw->dev); ··· 1508 1092 tb_retimer_remove_all(port); 1509 1093 tb_remove_dp_resources(port->remote->sw); 1510 1094 tb_switch_unconfigure_link(port->remote->sw); 1511 - tb_switch_lane_bonding_disable(port->remote->sw); 1095 + tb_switch_set_link_width(port->remote->sw, 1096 + TB_LINK_WIDTH_SINGLE); 1512 1097 tb_switch_remove(port->remote->sw); 1513 1098 port->remote = NULL; 1514 1099 if (port->dual_link_port) ··· 1605 1188 ret = tb_release_unused_usb3_bandwidth(tb, 1606 1189 first_tunnel->src_port, first_tunnel->dst_port); 1607 1190 if (ret) { 1608 - tb_port_warn(in, 1191 + tb_tunnel_warn(tunnel, 1609 1192 "failed to release unused bandwidth\n"); 1610 1193 break; 1611 1194 } ··· 1613 1196 1614 1197 out = tunnel->dst_port; 1615 1198 ret = tb_available_bandwidth(tb, in, out, &estimated_up, 1616 - &estimated_down); 1199 + &estimated_down, true); 1617 1200 if (ret) { 1618 - tb_port_warn(in, 1201 + tb_tunnel_warn(tunnel, 1619 1202 "failed to re-calculate estimated bandwidth\n"); 1620 1203 break; 1621 1204 } ··· 1626 1209 * - available bandwidth along the path 1627 1210 * - bandwidth allocated for USB 3.x but not used. 1628 1211 */ 1629 - tb_port_dbg(in, "re-calculated estimated bandwidth %u/%u Mb/s\n", 1630 - estimated_up, estimated_down); 1212 + tb_tunnel_dbg(tunnel, 1213 + "re-calculated estimated bandwidth %u/%u Mb/s\n", 1214 + estimated_up, estimated_down); 1631 1215 1632 - if (in->sw->config.depth < out->sw->config.depth) 1216 + if (tb_port_path_direction_downstream(in, out)) 1633 1217 estimated_bw = estimated_down; 1634 1218 else 1635 1219 estimated_bw = estimated_up; 1636 1220 1637 1221 if (usb4_dp_port_set_estimated_bandwidth(in, estimated_bw)) 1638 - tb_port_warn(in, "failed to update estimated bandwidth\n"); 1222 + tb_tunnel_warn(tunnel, 1223 + "failed to update estimated bandwidth\n"); 1639 1224 } 1640 1225 1641 1226 if (first_tunnel) ··· 1701 1282 return NULL; 1702 1283 } 1703 1284 1704 - static void tb_tunnel_dp(struct tb *tb) 1285 + static bool tb_tunnel_one_dp(struct tb *tb) 1705 1286 { 1706 1287 int available_up, available_down, ret, link_nr; 1707 1288 struct tb_cm *tcm = tb_priv(tb); 1708 1289 struct tb_port *port, *in, *out; 1290 + int consumed_up, consumed_down; 1709 1291 struct tb_tunnel *tunnel; 1710 - 1711 - if (!tb_acpi_may_tunnel_dp()) { 1712 - tb_dbg(tb, "DP tunneling disabled, not creating tunnel\n"); 1713 - return; 1714 - } 1715 1292 1716 1293 /* 1717 1294 * Find pair of inactive DP IN and DP OUT adapters and then ··· 1726 1311 continue; 1727 1312 } 1728 1313 1729 - tb_port_dbg(port, "DP IN available\n"); 1314 + in = port; 1315 + tb_port_dbg(in, "DP IN available\n"); 1730 1316 1731 1317 out = tb_find_dp_out(tb, port); 1732 - if (out) { 1733 - in = port; 1318 + if (out) 1734 1319 break; 1735 - } 1736 1320 } 1737 1321 1738 1322 if (!in) { 1739 1323 tb_dbg(tb, "no suitable DP IN adapter available, not tunneling\n"); 1740 - return; 1324 + return false; 1741 1325 } 1742 1326 if (!out) { 1743 1327 tb_dbg(tb, "no suitable DP OUT adapter available, not tunneling\n"); 1744 - return; 1328 + return false; 1745 1329 } 1746 1330 1747 1331 /* ··· 1783 1369 goto err_detach_group; 1784 1370 } 1785 1371 1786 - ret = tb_available_bandwidth(tb, in, out, &available_up, &available_down); 1372 + ret = tb_available_bandwidth(tb, in, out, &available_up, &available_down, 1373 + true); 1787 1374 if (ret) 1788 1375 goto err_reclaim_usb; 1789 1376 ··· 1806 1391 list_add_tail(&tunnel->list, &tcm->tunnel_list); 1807 1392 tb_reclaim_usb3_bandwidth(tb, in, out); 1808 1393 1394 + /* 1395 + * Transition the links to asymmetric if the consumption exceeds 1396 + * the threshold. 1397 + */ 1398 + if (!tb_tunnel_consumed_bandwidth(tunnel, &consumed_up, &consumed_down)) 1399 + tb_configure_asym(tb, in, out, consumed_up, consumed_down); 1400 + 1809 1401 /* Update the domain with the new bandwidth estimation */ 1810 1402 tb_recalc_estimated_bandwidth(tb); 1811 1403 ··· 1821 1399 * TMU mode to HiFi for CL0s to work. 1822 1400 */ 1823 1401 tb_increase_tmu_accuracy(tunnel); 1824 - return; 1402 + return true; 1825 1403 1826 1404 err_free: 1827 1405 tb_tunnel_free(tunnel); ··· 1836 1414 pm_runtime_put_autosuspend(&out->sw->dev); 1837 1415 pm_runtime_mark_last_busy(&in->sw->dev); 1838 1416 pm_runtime_put_autosuspend(&in->sw->dev); 1417 + 1418 + return false; 1419 + } 1420 + 1421 + static void tb_tunnel_dp(struct tb *tb) 1422 + { 1423 + if (!tb_acpi_may_tunnel_dp()) { 1424 + tb_dbg(tb, "DP tunneling disabled, not creating tunnel\n"); 1425 + return; 1426 + } 1427 + 1428 + while (tb_tunnel_one_dp(tb)) 1429 + ; 1839 1430 } 1840 1431 1841 1432 static void tb_dp_resource_unavailable(struct tb *tb, struct tb_port *port) ··· 2136 1701 tb_remove_dp_resources(port->remote->sw); 2137 1702 tb_switch_tmu_disable(port->remote->sw); 2138 1703 tb_switch_unconfigure_link(port->remote->sw); 2139 - tb_switch_lane_bonding_disable(port->remote->sw); 1704 + tb_switch_set_link_width(port->remote->sw, 1705 + TB_LINK_WIDTH_SINGLE); 2140 1706 tb_switch_remove(port->remote->sw); 2141 1707 port->remote = NULL; 2142 1708 if (port->dual_link_port) ··· 2217 1781 in = tunnel->src_port; 2218 1782 out = tunnel->dst_port; 2219 1783 2220 - tb_port_dbg(in, "bandwidth allocated currently %d/%d Mb/s\n", 2221 - allocated_up, allocated_down); 1784 + tb_tunnel_dbg(tunnel, "bandwidth allocated currently %d/%d Mb/s\n", 1785 + allocated_up, allocated_down); 2222 1786 2223 1787 /* 2224 1788 * If we get rounded up request from graphics side, say HBR2 x 4 ··· 2259 1823 else if (requested_down_corrected < 0) 2260 1824 requested_down_corrected = 0; 2261 1825 2262 - tb_port_dbg(in, "corrected bandwidth request %d/%d Mb/s\n", 2263 - requested_up_corrected, requested_down_corrected); 1826 + tb_tunnel_dbg(tunnel, "corrected bandwidth request %d/%d Mb/s\n", 1827 + requested_up_corrected, requested_down_corrected); 2264 1828 2265 1829 if ((*requested_up >= 0 && requested_up_corrected > max_up_rounded) || 2266 1830 (*requested_down >= 0 && requested_down_corrected > max_down_rounded)) { 2267 - tb_port_dbg(in, "bandwidth request too high (%d/%d Mb/s > %d/%d Mb/s)\n", 2268 - requested_up_corrected, requested_down_corrected, 2269 - max_up_rounded, max_down_rounded); 1831 + tb_tunnel_dbg(tunnel, 1832 + "bandwidth request too high (%d/%d Mb/s > %d/%d Mb/s)\n", 1833 + requested_up_corrected, requested_down_corrected, 1834 + max_up_rounded, max_down_rounded); 2270 1835 return -ENOBUFS; 2271 1836 } 2272 1837 2273 1838 if ((*requested_up >= 0 && requested_up_corrected <= allocated_up) || 2274 1839 (*requested_down >= 0 && requested_down_corrected <= allocated_down)) { 1840 + /* 1841 + * If bandwidth on a link is < asym_threshold transition 1842 + * the link to symmetric. 1843 + */ 1844 + tb_configure_sym(tb, in, out, *requested_up, *requested_down); 2275 1845 /* 2276 1846 * If requested bandwidth is less or equal than what is 2277 1847 * currently allocated to that tunnel we simply change ··· 2303 1861 * are also in the same group but we use the same function here 2304 1862 * that we use with the normal bandwidth allocation). 2305 1863 */ 2306 - ret = tb_available_bandwidth(tb, in, out, &available_up, &available_down); 1864 + ret = tb_available_bandwidth(tb, in, out, &available_up, &available_down, 1865 + true); 2307 1866 if (ret) 2308 1867 goto reclaim; 2309 1868 2310 - tb_port_dbg(in, "bandwidth available for allocation %d/%d Mb/s\n", 2311 - available_up, available_down); 1869 + tb_tunnel_dbg(tunnel, "bandwidth available for allocation %d/%d Mb/s\n", 1870 + available_up, available_down); 2312 1871 2313 1872 if ((*requested_up >= 0 && available_up >= requested_up_corrected) || 2314 1873 (*requested_down >= 0 && available_down >= requested_down_corrected)) { 1874 + /* 1875 + * If bandwidth on a link is >= asym_threshold 1876 + * transition the link to asymmetric. 1877 + */ 1878 + ret = tb_configure_asym(tb, in, out, *requested_up, 1879 + *requested_down); 1880 + if (ret) { 1881 + tb_configure_sym(tb, in, out, 0, 0); 1882 + return ret; 1883 + } 1884 + 2315 1885 ret = tb_tunnel_alloc_bandwidth(tunnel, requested_up, 2316 1886 requested_down); 1887 + if (ret) { 1888 + tb_tunnel_warn(tunnel, "failed to allocate bandwidth\n"); 1889 + tb_configure_sym(tb, in, out, 0, 0); 1890 + } 2317 1891 } else { 2318 1892 ret = -ENOBUFS; 2319 1893 } ··· 2395 1937 2396 1938 out = tunnel->dst_port; 2397 1939 2398 - if (in->sw->config.depth < out->sw->config.depth) { 1940 + if (tb_port_path_direction_downstream(in, out)) { 2399 1941 requested_up = -1; 2400 1942 requested_down = requested_bw; 2401 1943 } else { ··· 2406 1948 ret = tb_alloc_dp_bandwidth(tunnel, &requested_up, &requested_down); 2407 1949 if (ret) { 2408 1950 if (ret == -ENOBUFS) 2409 - tb_port_warn(in, "not enough bandwidth available\n"); 1951 + tb_tunnel_warn(tunnel, 1952 + "not enough bandwidth available\n"); 2410 1953 else 2411 - tb_port_warn(in, "failed to change bandwidth allocation\n"); 1954 + tb_tunnel_warn(tunnel, 1955 + "failed to change bandwidth allocation\n"); 2412 1956 } else { 2413 - tb_port_dbg(in, "bandwidth allocation changed to %d/%d Mb/s\n", 2414 - requested_up, requested_down); 1957 + tb_tunnel_dbg(tunnel, 1958 + "bandwidth allocation changed to %d/%d Mb/s\n", 1959 + requested_up, requested_down); 2415 1960 2416 1961 /* Update other clients about the allocation change */ 2417 1962 tb_recalc_estimated_bandwidth(tb); ··· 2640 2179 continue; 2641 2180 2642 2181 if (port->remote) { 2643 - tb_switch_lane_bonding_enable(port->remote->sw); 2182 + tb_switch_set_link_width(port->remote->sw, 2183 + port->remote->sw->link_width); 2644 2184 tb_switch_configure_link(port->remote->sw); 2645 2185 2646 2186 tb_restore_children(port->remote->sw);
+50 -10
drivers/thunderbolt/tb.h
··· 162 162 * switches) you need to have domain lock held. 163 163 * 164 164 * In USB4 terminology this structure represents a router. 165 - * 166 - * Note @link_width is not the same as whether link is bonded or not. 167 - * For Gen 4 links the link is also bonded when it is asymmetric. The 168 - * correct way to find out whether the link is bonded or not is to look 169 - * @bonded field of the upstream port. 170 165 */ 171 166 struct tb_switch { 172 167 struct device dev; ··· 343 348 * the path 344 349 * @nfc_credits: Number of non-flow controlled buffers allocated for the 345 350 * @in_port. 351 + * @pm_support: Set path PM packet support bit to 1 (for USB4 v2 routers) 346 352 * 347 353 * Hop configuration is always done on the IN port of a switch. 348 354 * in_port and out_port have to be on the same switch. Packets arriving on ··· 364 368 int next_hop_index; 365 369 unsigned int initial_credits; 366 370 unsigned int nfc_credits; 371 + bool pm_support; 367 372 }; 368 373 369 374 /** ··· 861 864 return tb_port_at(tb_route(sw), tb_switch_parent(sw)); 862 865 } 863 866 867 + /** 868 + * tb_switch_depth() - Returns depth of the connected router 869 + * @sw: Router 870 + */ 871 + static inline int tb_switch_depth(const struct tb_switch *sw) 872 + { 873 + return sw->config.depth; 874 + } 875 + 864 876 static inline bool tb_switch_is_light_ridge(const struct tb_switch *sw) 865 877 { 866 878 return sw->config.vendor_id == PCI_VENDOR_ID_INTEL && ··· 962 956 return !sw->config.enabled; 963 957 } 964 958 965 - int tb_switch_lane_bonding_enable(struct tb_switch *sw); 966 - void tb_switch_lane_bonding_disable(struct tb_switch *sw); 959 + int tb_switch_set_link_width(struct tb_switch *sw, enum tb_link_width width); 967 960 int tb_switch_configure_link(struct tb_switch *sw); 968 961 void tb_switch_unconfigure_link(struct tb_switch *sw); 969 962 ··· 1006 1001 bool tb_port_clx_is_enabled(struct tb_port *port, unsigned int clx); 1007 1002 1008 1003 int tb_switch_clx_init(struct tb_switch *sw); 1009 - bool tb_switch_clx_is_supported(const struct tb_switch *sw); 1010 1004 int tb_switch_clx_enable(struct tb_switch *sw, unsigned int clx); 1011 1005 int tb_switch_clx_disable(struct tb_switch *sw); 1012 1006 ··· 1044 1040 struct tb_port *tb_next_port_on_path(struct tb_port *start, struct tb_port *end, 1045 1041 struct tb_port *prev); 1046 1042 1043 + /** 1044 + * tb_port_path_direction_downstream() - Checks if path directed downstream 1045 + * @src: Source adapter 1046 + * @dst: Destination adapter 1047 + * 1048 + * Returns %true only if the specified path from source adapter (@src) 1049 + * to destination adapter (@dst) is directed downstream. 1050 + */ 1051 + static inline bool 1052 + tb_port_path_direction_downstream(const struct tb_port *src, 1053 + const struct tb_port *dst) 1054 + { 1055 + return src->sw->config.depth < dst->sw->config.depth; 1056 + } 1057 + 1047 1058 static inline bool tb_port_use_credit_allocation(const struct tb_port *port) 1048 1059 { 1049 1060 return tb_port_is_null(port) && port->sw->credit_allocation; ··· 1076 1057 for ((p) = tb_next_port_on_path((src), (dst), NULL); (p); \ 1077 1058 (p) = tb_next_port_on_path((src), (dst), (p))) 1078 1059 1060 + /** 1061 + * tb_for_each_upstream_port_on_path() - Iterate over each upstreamm port on path 1062 + * @src: Source port 1063 + * @dst: Destination port 1064 + * @p: Port used as iterator 1065 + * 1066 + * Walks over each upstream lane adapter on path from @src to @dst. 1067 + */ 1068 + #define tb_for_each_upstream_port_on_path(src, dst, p) \ 1069 + for ((p) = tb_next_port_on_path((src), (dst), NULL); (p); \ 1070 + (p) = tb_next_port_on_path((src), (dst), (p))) \ 1071 + if (!tb_port_is_null((p)) || !tb_is_upstream_port((p))) {\ 1072 + continue; \ 1073 + } else 1074 + 1079 1075 int tb_port_get_link_speed(struct tb_port *port); 1076 + int tb_port_get_link_generation(struct tb_port *port); 1080 1077 int tb_port_get_link_width(struct tb_port *port); 1078 + bool tb_port_width_supported(struct tb_port *port, unsigned int width); 1081 1079 int tb_port_set_link_width(struct tb_port *port, enum tb_link_width width); 1082 1080 int tb_port_lane_bonding_enable(struct tb_port *port); 1083 1081 void tb_port_lane_bonding_disable(struct tb_port *port); 1084 - int tb_port_wait_for_link_width(struct tb_port *port, unsigned int width_mask, 1082 + int tb_port_wait_for_link_width(struct tb_port *port, unsigned int width, 1085 1083 int timeout_msec); 1086 1084 int tb_port_update_credits(struct tb_port *port); 1087 1085 ··· 1292 1256 int usb4_port_enumerate_retimers(struct tb_port *port); 1293 1257 bool usb4_port_clx_supported(struct tb_port *port); 1294 1258 int usb4_port_margining_caps(struct tb_port *port, u32 *caps); 1259 + 1260 + bool usb4_port_asym_supported(struct tb_port *port); 1261 + int usb4_port_asym_set_link_width(struct tb_port *port, enum tb_link_width width); 1262 + int usb4_port_asym_start(struct tb_port *port); 1263 + 1295 1264 int usb4_port_hw_margin(struct tb_port *port, unsigned int lanes, 1296 1265 unsigned int ber_level, bool timing, bool right_high, 1297 1266 u32 *results); ··· 1324 1283 unsigned int address, void *buf, size_t size); 1325 1284 1326 1285 int usb4_usb3_port_max_link_rate(struct tb_port *port); 1327 - int usb4_usb3_port_actual_link_rate(struct tb_port *port); 1328 1286 int usb4_usb3_port_allocated_bandwidth(struct tb_port *port, int *upstream_bw, 1329 1287 int *downstream_bw); 1330 1288 int usb4_usb3_port_allocate_bandwidth(struct tb_port *port, int *upstream_bw,
+12 -7
drivers/thunderbolt/tb_regs.h
··· 346 346 #define LANE_ADP_CS_1 0x01 347 347 #define LANE_ADP_CS_1_TARGET_SPEED_MASK GENMASK(3, 0) 348 348 #define LANE_ADP_CS_1_TARGET_SPEED_GEN3 0xc 349 - #define LANE_ADP_CS_1_TARGET_WIDTH_MASK GENMASK(9, 4) 349 + #define LANE_ADP_CS_1_TARGET_WIDTH_MASK GENMASK(5, 4) 350 350 #define LANE_ADP_CS_1_TARGET_WIDTH_SHIFT 4 351 351 #define LANE_ADP_CS_1_TARGET_WIDTH_SINGLE 0x1 352 352 #define LANE_ADP_CS_1_TARGET_WIDTH_DUAL 0x3 353 + #define LANE_ADP_CS_1_TARGET_WIDTH_ASYM_MASK GENMASK(7, 6) 354 + #define LANE_ADP_CS_1_TARGET_WIDTH_ASYM_TX 0x1 355 + #define LANE_ADP_CS_1_TARGET_WIDTH_ASYM_RX 0x2 356 + #define LANE_ADP_CS_1_TARGET_WIDTH_ASYM_DUAL 0x0 353 357 #define LANE_ADP_CS_1_CL0S_ENABLE BIT(10) 354 358 #define LANE_ADP_CS_1_CL1_ENABLE BIT(11) 355 359 #define LANE_ADP_CS_1_CL2_ENABLE BIT(12) ··· 386 382 #define PORT_CS_18_WOCS BIT(16) 387 383 #define PORT_CS_18_WODS BIT(17) 388 384 #define PORT_CS_18_WOU4S BIT(18) 385 + #define PORT_CS_18_CSA BIT(22) 386 + #define PORT_CS_18_TIP BIT(24) 389 387 #define PORT_CS_19 0x13 390 388 #define PORT_CS_19_PC BIT(3) 391 389 #define PORT_CS_19_PID BIT(4) 392 390 #define PORT_CS_19_WOC BIT(16) 393 391 #define PORT_CS_19_WOD BIT(17) 394 392 #define PORT_CS_19_WOU4 BIT(18) 393 + #define PORT_CS_19_START_ASYM BIT(24) 395 394 396 395 /* Display Port adapter registers */ 397 396 #define ADP_DP_CS_0 0x00 ··· 407 400 #define ADP_DP_CS_1_AUX_RX_HOPID_SHIFT 11 408 401 #define ADP_DP_CS_2 0x02 409 402 #define ADP_DP_CS_2_NRD_MLC_MASK GENMASK(2, 0) 410 - #define ADP_DP_CS_2_HDP BIT(6) 403 + #define ADP_DP_CS_2_HPD BIT(6) 411 404 #define ADP_DP_CS_2_NRD_MLR_MASK GENMASK(9, 7) 412 405 #define ADP_DP_CS_2_NRD_MLR_SHIFT 7 413 406 #define ADP_DP_CS_2_CA BIT(10) ··· 424 417 #define ADP_DP_CS_2_ESTIMATED_BW_MASK GENMASK(31, 24) 425 418 #define ADP_DP_CS_2_ESTIMATED_BW_SHIFT 24 426 419 #define ADP_DP_CS_3 0x03 427 - #define ADP_DP_CS_3_HDPC BIT(9) 420 + #define ADP_DP_CS_3_HPDC BIT(9) 428 421 #define DP_LOCAL_CAP 0x04 429 422 #define DP_REMOTE_CAP 0x05 430 423 /* For DP IN adapter */ ··· 491 484 #define ADP_USB3_CS_3 0x03 492 485 #define ADP_USB3_CS_3_SCALE_MASK GENMASK(5, 0) 493 486 #define ADP_USB3_CS_4 0x04 494 - #define ADP_USB3_CS_4_ALR_MASK GENMASK(6, 0) 495 - #define ADP_USB3_CS_4_ALR_20G 0x1 496 - #define ADP_USB3_CS_4_ULV BIT(7) 497 487 #define ADP_USB3_CS_4_MSLR_MASK GENMASK(18, 12) 498 488 #define ADP_USB3_CS_4_MSLR_SHIFT 12 499 489 #define ADP_USB3_CS_4_MSLR_20G 0x1 ··· 503 499 * out_port (on the incoming port of the next switch) 504 500 */ 505 501 u32 out_port:6; /* next port of the path (on the same switch) */ 506 - u32 initial_credits:8; 502 + u32 initial_credits:7; 503 + u32 pmps:1; 507 504 u32 unknown1:6; /* set to zero */ 508 505 bool enable:1; 509 506
+165 -98
drivers/thunderbolt/tunnel.c
··· 21 21 #define TB_PCI_PATH_DOWN 0 22 22 #define TB_PCI_PATH_UP 1 23 23 24 + #define TB_PCI_PRIORITY 3 25 + #define TB_PCI_WEIGHT 1 26 + 24 27 /* USB3 adapters use always HopID of 8 for both directions */ 25 28 #define TB_USB3_HOPID 8 26 29 27 30 #define TB_USB3_PATH_DOWN 0 28 31 #define TB_USB3_PATH_UP 1 32 + 33 + #define TB_USB3_PRIORITY 3 34 + #define TB_USB3_WEIGHT 2 29 35 30 36 /* DP adapters use HopID 8 for AUX and 9 for Video */ 31 37 #define TB_DP_AUX_TX_HOPID 8 ··· 42 36 #define TB_DP_AUX_PATH_OUT 1 43 37 #define TB_DP_AUX_PATH_IN 2 44 38 39 + #define TB_DP_VIDEO_PRIORITY 1 40 + #define TB_DP_VIDEO_WEIGHT 1 41 + 42 + #define TB_DP_AUX_PRIORITY 2 43 + #define TB_DP_AUX_WEIGHT 1 44 + 45 45 /* Minimum number of credits needed for PCIe path */ 46 46 #define TB_MIN_PCIE_CREDITS 6U 47 47 /* ··· 57 45 #define TB_DMA_CREDITS 14 58 46 /* Minimum number of credits for DMA path */ 59 47 #define TB_MIN_DMA_CREDITS 1 48 + 49 + #define TB_DMA_PRIORITY 5 50 + #define TB_DMA_WEIGHT 1 51 + 52 + /* 53 + * Reserve additional bandwidth for USB 3.x and PCIe bulk traffic 54 + * according to USB4 v2 Connection Manager guide. This ends up reserving 55 + * 1500 Mb/s for PCIe and 3000 Mb/s for USB 3.x taking weights into 56 + * account. 57 + */ 58 + #define USB4_V2_PCI_MIN_BANDWIDTH (1500 * TB_PCI_WEIGHT) 59 + #define USB4_V2_USB3_MIN_BANDWIDTH (1500 * TB_USB3_WEIGHT) 60 60 61 61 static unsigned int dma_credits = TB_DMA_CREDITS; 62 62 module_param(dma_credits, uint, 0444); ··· 81 57 "enable bandwidth allocation mode if supported (default: true)"); 82 58 83 59 static const char * const tb_tunnel_names[] = { "PCI", "DP", "DMA", "USB3" }; 84 - 85 - #define __TB_TUNNEL_PRINT(level, tunnel, fmt, arg...) \ 86 - do { \ 87 - struct tb_tunnel *__tunnel = (tunnel); \ 88 - level(__tunnel->tb, "%llx:%u <-> %llx:%u (%s): " fmt, \ 89 - tb_route(__tunnel->src_port->sw), \ 90 - __tunnel->src_port->port, \ 91 - tb_route(__tunnel->dst_port->sw), \ 92 - __tunnel->dst_port->port, \ 93 - tb_tunnel_names[__tunnel->type], \ 94 - ## arg); \ 95 - } while (0) 96 - 97 - #define tb_tunnel_WARN(tunnel, fmt, arg...) \ 98 - __TB_TUNNEL_PRINT(tb_WARN, tunnel, fmt, ##arg) 99 - #define tb_tunnel_warn(tunnel, fmt, arg...) \ 100 - __TB_TUNNEL_PRINT(tb_warn, tunnel, fmt, ##arg) 101 - #define tb_tunnel_info(tunnel, fmt, arg...) \ 102 - __TB_TUNNEL_PRINT(tb_info, tunnel, fmt, ##arg) 103 - #define tb_tunnel_dbg(tunnel, fmt, arg...) \ 104 - __TB_TUNNEL_PRINT(tb_dbg, tunnel, fmt, ##arg) 105 60 106 61 static inline unsigned int tb_usable_credits(const struct tb_port *port) 107 62 { ··· 134 131 return credits > 0 ? credits : 0; 135 132 } 136 133 134 + static void tb_init_pm_support(struct tb_path_hop *hop) 135 + { 136 + struct tb_port *out_port = hop->out_port; 137 + struct tb_port *in_port = hop->in_port; 138 + 139 + if (tb_port_is_null(in_port) && tb_port_is_null(out_port) && 140 + usb4_switch_version(in_port->sw) >= 2) 141 + hop->pm_support = true; 142 + } 143 + 137 144 static struct tb_tunnel *tb_tunnel_alloc(struct tb *tb, size_t npaths, 138 145 enum tb_tunnel_type type) 139 146 { ··· 169 156 170 157 static int tb_pci_set_ext_encapsulation(struct tb_tunnel *tunnel, bool enable) 171 158 { 159 + struct tb_port *port = tb_upstream_port(tunnel->dst_port->sw); 172 160 int ret; 173 161 174 162 /* Only supported of both routers are at least USB4 v2 */ 175 - if (usb4_switch_version(tunnel->src_port->sw) < 2 || 176 - usb4_switch_version(tunnel->dst_port->sw) < 2) 163 + if (tb_port_get_link_generation(port) < 4) 177 164 return 0; 178 165 179 166 ret = usb4_pci_port_set_ext_encapsulation(tunnel->src_port, enable); ··· 247 234 path->egress_shared_buffer = TB_PATH_NONE; 248 235 path->ingress_fc_enable = TB_PATH_ALL; 249 236 path->ingress_shared_buffer = TB_PATH_NONE; 250 - path->priority = 3; 251 - path->weight = 1; 237 + path->priority = TB_PCI_PRIORITY; 238 + path->weight = TB_PCI_WEIGHT; 252 239 path->drop_packages = 0; 253 240 254 241 tb_path_for_each_hop(path, hop) { ··· 387 374 err_free: 388 375 tb_tunnel_free(tunnel); 389 376 return NULL; 377 + } 378 + 379 + /** 380 + * tb_tunnel_reserved_pci() - Amount of bandwidth to reserve for PCIe 381 + * @port: Lane 0 adapter 382 + * @reserved_up: Upstream bandwidth in Mb/s to reserve 383 + * @reserved_down: Downstream bandwidth in Mb/s to reserve 384 + * 385 + * Can be called to any connected lane 0 adapter to find out how much 386 + * bandwidth needs to be left in reserve for possible PCIe bulk traffic. 387 + * Returns true if there is something to be reserved and writes the 388 + * amount to @reserved_down/@reserved_up. Otherwise returns false and 389 + * does not touch the parameters. 390 + */ 391 + bool tb_tunnel_reserved_pci(struct tb_port *port, int *reserved_up, 392 + int *reserved_down) 393 + { 394 + if (WARN_ON_ONCE(!port->remote)) 395 + return false; 396 + 397 + if (!tb_acpi_may_tunnel_pcie()) 398 + return false; 399 + 400 + if (tb_port_get_link_generation(port) < 4) 401 + return false; 402 + 403 + /* Must have PCIe adapters */ 404 + if (tb_is_upstream_port(port)) { 405 + if (!tb_switch_find_port(port->sw, TB_TYPE_PCIE_UP)) 406 + return false; 407 + if (!tb_switch_find_port(port->remote->sw, TB_TYPE_PCIE_DOWN)) 408 + return false; 409 + } else { 410 + if (!tb_switch_find_port(port->sw, TB_TYPE_PCIE_DOWN)) 411 + return false; 412 + if (!tb_switch_find_port(port->remote->sw, TB_TYPE_PCIE_UP)) 413 + return false; 414 + } 415 + 416 + *reserved_up = USB4_V2_PCI_MIN_BANDWIDTH; 417 + *reserved_down = USB4_V2_PCI_MIN_BANDWIDTH; 418 + 419 + tb_port_dbg(port, "reserving %u/%u Mb/s for PCIe\n", *reserved_up, 420 + *reserved_down); 421 + return true; 390 422 } 391 423 392 424 static bool tb_dp_is_usb4(const struct tb_switch *sw) ··· 672 614 673 615 in_rate = tb_dp_cap_get_rate(in_dp_cap); 674 616 in_lanes = tb_dp_cap_get_lanes(in_dp_cap); 675 - tb_port_dbg(in, "maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", 676 - in_rate, in_lanes, tb_dp_bandwidth(in_rate, in_lanes)); 617 + tb_tunnel_dbg(tunnel, 618 + "DP IN maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", 619 + in_rate, in_lanes, tb_dp_bandwidth(in_rate, in_lanes)); 677 620 678 621 /* 679 622 * If the tunnel bandwidth is limited (max_bw is set) then see ··· 683 624 out_rate = tb_dp_cap_get_rate(out_dp_cap); 684 625 out_lanes = tb_dp_cap_get_lanes(out_dp_cap); 685 626 bw = tb_dp_bandwidth(out_rate, out_lanes); 686 - tb_port_dbg(out, "maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", 687 - out_rate, out_lanes, bw); 627 + tb_tunnel_dbg(tunnel, 628 + "DP OUT maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", 629 + out_rate, out_lanes, bw); 688 630 689 - if (in->sw->config.depth < out->sw->config.depth) 631 + if (tb_port_path_direction_downstream(in, out)) 690 632 max_bw = tunnel->max_down; 691 633 else 692 634 max_bw = tunnel->max_up; ··· 699 639 out_rate, out_lanes, &new_rate, 700 640 &new_lanes); 701 641 if (ret) { 702 - tb_port_info(out, "not enough bandwidth for DP tunnel\n"); 642 + tb_tunnel_info(tunnel, "not enough bandwidth\n"); 703 643 return ret; 704 644 } 705 645 706 646 new_bw = tb_dp_bandwidth(new_rate, new_lanes); 707 - tb_port_dbg(out, "bandwidth reduced to %u Mb/s x%u = %u Mb/s\n", 708 - new_rate, new_lanes, new_bw); 647 + tb_tunnel_dbg(tunnel, 648 + "bandwidth reduced to %u Mb/s x%u = %u Mb/s\n", 649 + new_rate, new_lanes, new_bw); 709 650 710 651 /* 711 652 * Set new rate and number of lanes before writing it to ··· 723 662 */ 724 663 if (tb_route(out->sw) && tb_switch_is_titan_ridge(out->sw)) { 725 664 out_dp_cap |= DP_COMMON_CAP_LTTPR_NS; 726 - tb_port_dbg(out, "disabling LTTPR\n"); 665 + tb_tunnel_dbg(tunnel, "disabling LTTPR\n"); 727 666 } 728 667 729 668 return tb_port_write(in, &out_dp_cap, TB_CFG_PORT, ··· 773 712 lanes = min(in_lanes, out_lanes); 774 713 tmp = tb_dp_bandwidth(rate, lanes); 775 714 776 - tb_port_dbg(in, "non-reduced bandwidth %u Mb/s x%u = %u Mb/s\n", rate, 777 - lanes, tmp); 715 + tb_tunnel_dbg(tunnel, "non-reduced bandwidth %u Mb/s x%u = %u Mb/s\n", 716 + rate, lanes, tmp); 778 717 779 718 ret = usb4_dp_port_set_nrd(in, rate, lanes); 780 719 if (ret) ··· 789 728 rate = min(in_rate, out_rate); 790 729 tmp = tb_dp_bandwidth(rate, lanes); 791 730 792 - tb_port_dbg(in, 793 - "maximum bandwidth through allocation mode %u Mb/s x%u = %u Mb/s\n", 794 - rate, lanes, tmp); 731 + tb_tunnel_dbg(tunnel, 732 + "maximum bandwidth through allocation mode %u Mb/s x%u = %u Mb/s\n", 733 + rate, lanes, tmp); 795 734 796 735 for (granularity = 250; tmp / granularity > 255 && granularity <= 1000; 797 736 granularity *= 2) 798 737 ; 799 738 800 - tb_port_dbg(in, "granularity %d Mb/s\n", granularity); 739 + tb_tunnel_dbg(tunnel, "granularity %d Mb/s\n", granularity); 801 740 802 741 /* 803 742 * Returns -EINVAL if granularity above is outside of the ··· 812 751 * max_up/down fields. For discovery we just read what the 813 752 * estimation was set to. 814 753 */ 815 - if (in->sw->config.depth < out->sw->config.depth) 754 + if (tb_port_path_direction_downstream(in, out)) 816 755 estimated_bw = tunnel->max_down; 817 756 else 818 757 estimated_bw = tunnel->max_up; 819 758 820 - tb_port_dbg(in, "estimated bandwidth %d Mb/s\n", estimated_bw); 759 + tb_tunnel_dbg(tunnel, "estimated bandwidth %d Mb/s\n", estimated_bw); 821 760 822 761 ret = usb4_dp_port_set_estimated_bandwidth(in, estimated_bw); 823 762 if (ret) ··· 828 767 if (ret) 829 768 return ret; 830 769 831 - tb_port_dbg(in, "bandwidth allocation mode enabled\n"); 770 + tb_tunnel_dbg(tunnel, "bandwidth allocation mode enabled\n"); 832 771 return 0; 833 772 } 834 773 ··· 849 788 if (!usb4_dp_port_bandwidth_mode_supported(in)) 850 789 return 0; 851 790 852 - tb_port_dbg(in, "bandwidth allocation mode supported\n"); 791 + tb_tunnel_dbg(tunnel, "bandwidth allocation mode supported\n"); 853 792 854 793 ret = usb4_dp_port_set_cm_id(in, tb->index); 855 794 if (ret) ··· 866 805 return; 867 806 if (usb4_dp_port_bandwidth_mode_enabled(in)) { 868 807 usb4_dp_port_set_cm_bandwidth_mode_supported(in, false); 869 - tb_port_dbg(in, "bandwidth allocation mode disabled\n"); 808 + tb_tunnel_dbg(tunnel, "bandwidth allocation mode disabled\n"); 870 809 } 871 810 } 872 811 ··· 982 921 if (allocated_bw == max_bw) 983 922 allocated_bw = ret; 984 923 985 - tb_port_dbg(in, "consumed bandwidth through allocation mode %d Mb/s\n", 986 - allocated_bw); 987 - 988 - if (in->sw->config.depth < out->sw->config.depth) { 924 + if (tb_port_path_direction_downstream(in, out)) { 989 925 *consumed_up = 0; 990 926 *consumed_down = allocated_bw; 991 927 } else { ··· 1017 959 if (allocated_bw == max_bw) 1018 960 allocated_bw = ret; 1019 961 1020 - if (in->sw->config.depth < out->sw->config.depth) { 962 + if (tb_port_path_direction_downstream(in, out)) { 1021 963 *allocated_up = 0; 1022 964 *allocated_down = allocated_bw; 1023 965 } else { ··· 1045 987 if (ret < 0) 1046 988 return ret; 1047 989 1048 - if (in->sw->config.depth < out->sw->config.depth) { 990 + if (tb_port_path_direction_downstream(in, out)) { 1049 991 tmp = min(*alloc_down, max_bw); 1050 992 ret = usb4_dp_port_allocate_bandwidth(in, tmp); 1051 993 if (ret) ··· 1064 1006 /* Now we can use BW mode registers to figure out the bandwidth */ 1065 1007 /* TODO: need to handle discovery too */ 1066 1008 tunnel->bw_mode = true; 1067 - 1068 - tb_port_dbg(in, "allocated bandwidth through allocation mode %d Mb/s\n", 1069 - tmp); 1070 1009 return 0; 1071 1010 } 1072 1011 ··· 1090 1035 *rate = tb_dp_cap_get_rate(val); 1091 1036 *lanes = tb_dp_cap_get_lanes(val); 1092 1037 1093 - tb_port_dbg(in, "consumed bandwidth through DPRX %d Mb/s\n", 1094 - tb_dp_bandwidth(*rate, *lanes)); 1038 + tb_tunnel_dbg(tunnel, "DPRX read done\n"); 1095 1039 return 0; 1096 1040 } 1097 1041 usleep_range(100, 150); ··· 1127 1073 1128 1074 *rate = tb_dp_cap_get_rate(val); 1129 1075 *lanes = tb_dp_cap_get_lanes(val); 1130 - 1131 - tb_port_dbg(in, "bandwidth from %#x capability %d Mb/s\n", cap, 1132 - tb_dp_bandwidth(*rate, *lanes)); 1133 1076 return 0; 1134 1077 } 1135 1078 ··· 1143 1092 if (ret < 0) 1144 1093 return ret; 1145 1094 1146 - if (in->sw->config.depth < tunnel->dst_port->sw->config.depth) { 1095 + if (tb_port_path_direction_downstream(in, tunnel->dst_port)) { 1147 1096 *max_up = 0; 1148 1097 *max_down = ret; 1149 1098 } else { ··· 1201 1150 return 0; 1202 1151 } 1203 1152 1204 - if (in->sw->config.depth < tunnel->dst_port->sw->config.depth) { 1153 + if (tb_port_path_direction_downstream(in, tunnel->dst_port)) { 1205 1154 *consumed_up = 0; 1206 1155 *consumed_down = tb_dp_bandwidth(rate, lanes); 1207 1156 } else { ··· 1223 1172 hop->initial_credits = 1; 1224 1173 } 1225 1174 1226 - static void tb_dp_init_aux_path(struct tb_path *path) 1175 + static void tb_dp_init_aux_path(struct tb_path *path, bool pm_support) 1227 1176 { 1228 1177 struct tb_path_hop *hop; 1229 1178 ··· 1231 1180 path->egress_shared_buffer = TB_PATH_NONE; 1232 1181 path->ingress_fc_enable = TB_PATH_ALL; 1233 1182 path->ingress_shared_buffer = TB_PATH_NONE; 1234 - path->priority = 2; 1235 - path->weight = 1; 1183 + path->priority = TB_DP_AUX_PRIORITY; 1184 + path->weight = TB_DP_AUX_WEIGHT; 1236 1185 1237 - tb_path_for_each_hop(path, hop) 1186 + tb_path_for_each_hop(path, hop) { 1238 1187 tb_dp_init_aux_credits(hop); 1188 + if (pm_support) 1189 + tb_init_pm_support(hop); 1190 + } 1239 1191 } 1240 1192 1241 1193 static int tb_dp_init_video_credits(struct tb_path_hop *hop) ··· 1270 1216 return 0; 1271 1217 } 1272 1218 1273 - static int tb_dp_init_video_path(struct tb_path *path) 1219 + static int tb_dp_init_video_path(struct tb_path *path, bool pm_support) 1274 1220 { 1275 1221 struct tb_path_hop *hop; 1276 1222 ··· 1278 1224 path->egress_shared_buffer = TB_PATH_NONE; 1279 1225 path->ingress_fc_enable = TB_PATH_NONE; 1280 1226 path->ingress_shared_buffer = TB_PATH_NONE; 1281 - path->priority = 1; 1282 - path->weight = 1; 1227 + path->priority = TB_DP_VIDEO_PRIORITY; 1228 + path->weight = TB_DP_VIDEO_WEIGHT; 1283 1229 1284 1230 tb_path_for_each_hop(path, hop) { 1285 1231 int ret; ··· 1287 1233 ret = tb_dp_init_video_credits(hop); 1288 1234 if (ret) 1289 1235 return ret; 1236 + if (pm_support) 1237 + tb_init_pm_support(hop); 1290 1238 } 1291 1239 1292 1240 return 0; ··· 1309 1253 rate = tb_dp_cap_get_rate(dp_cap); 1310 1254 lanes = tb_dp_cap_get_lanes(dp_cap); 1311 1255 1312 - tb_port_dbg(in, "maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", 1313 - rate, lanes, tb_dp_bandwidth(rate, lanes)); 1256 + tb_tunnel_dbg(tunnel, 1257 + "DP IN maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", 1258 + rate, lanes, tb_dp_bandwidth(rate, lanes)); 1314 1259 1315 1260 out = tunnel->dst_port; 1316 1261 ··· 1322 1265 rate = tb_dp_cap_get_rate(dp_cap); 1323 1266 lanes = tb_dp_cap_get_lanes(dp_cap); 1324 1267 1325 - tb_port_dbg(out, "maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", 1326 - rate, lanes, tb_dp_bandwidth(rate, lanes)); 1268 + tb_tunnel_dbg(tunnel, 1269 + "DP OUT maximum supported bandwidth %u Mb/s x%u = %u Mb/s\n", 1270 + rate, lanes, tb_dp_bandwidth(rate, lanes)); 1327 1271 1328 1272 if (tb_port_read(in, &dp_cap, TB_CFG_PORT, 1329 1273 in->cap_adap + DP_REMOTE_CAP, 1)) ··· 1333 1275 rate = tb_dp_cap_get_rate(dp_cap); 1334 1276 lanes = tb_dp_cap_get_lanes(dp_cap); 1335 1277 1336 - tb_port_dbg(in, "reduced bandwidth %u Mb/s x%u = %u Mb/s\n", 1337 - rate, lanes, tb_dp_bandwidth(rate, lanes)); 1278 + tb_tunnel_dbg(tunnel, "reduced bandwidth %u Mb/s x%u = %u Mb/s\n", 1279 + rate, lanes, tb_dp_bandwidth(rate, lanes)); 1338 1280 } 1339 1281 1340 1282 /** ··· 1380 1322 goto err_free; 1381 1323 } 1382 1324 tunnel->paths[TB_DP_VIDEO_PATH_OUT] = path; 1383 - if (tb_dp_init_video_path(tunnel->paths[TB_DP_VIDEO_PATH_OUT])) 1325 + if (tb_dp_init_video_path(tunnel->paths[TB_DP_VIDEO_PATH_OUT], false)) 1384 1326 goto err_free; 1385 1327 1386 1328 path = tb_path_discover(in, TB_DP_AUX_TX_HOPID, NULL, -1, NULL, "AUX TX", ··· 1388 1330 if (!path) 1389 1331 goto err_deactivate; 1390 1332 tunnel->paths[TB_DP_AUX_PATH_OUT] = path; 1391 - tb_dp_init_aux_path(tunnel->paths[TB_DP_AUX_PATH_OUT]); 1333 + tb_dp_init_aux_path(tunnel->paths[TB_DP_AUX_PATH_OUT], false); 1392 1334 1393 1335 path = tb_path_discover(tunnel->dst_port, -1, in, TB_DP_AUX_RX_HOPID, 1394 1336 &port, "AUX RX", alloc_hopid); 1395 1337 if (!path) 1396 1338 goto err_deactivate; 1397 1339 tunnel->paths[TB_DP_AUX_PATH_IN] = path; 1398 - tb_dp_init_aux_path(tunnel->paths[TB_DP_AUX_PATH_IN]); 1340 + tb_dp_init_aux_path(tunnel->paths[TB_DP_AUX_PATH_IN], false); 1399 1341 1400 1342 /* Validate that the tunnel is complete */ 1401 1343 if (!tb_port_is_dpout(tunnel->dst_port)) { ··· 1450 1392 struct tb_tunnel *tunnel; 1451 1393 struct tb_path **paths; 1452 1394 struct tb_path *path; 1395 + bool pm_support; 1453 1396 1454 1397 if (WARN_ON(!in->cap_adap || !out->cap_adap)) 1455 1398 return NULL; ··· 1472 1413 tunnel->max_down = max_down; 1473 1414 1474 1415 paths = tunnel->paths; 1416 + pm_support = usb4_switch_version(in->sw) >= 2; 1475 1417 1476 1418 path = tb_path_alloc(tb, in, TB_DP_VIDEO_HOPID, out, TB_DP_VIDEO_HOPID, 1477 1419 link_nr, "Video"); 1478 1420 if (!path) 1479 1421 goto err_free; 1480 - tb_dp_init_video_path(path); 1422 + tb_dp_init_video_path(path, pm_support); 1481 1423 paths[TB_DP_VIDEO_PATH_OUT] = path; 1482 1424 1483 1425 path = tb_path_alloc(tb, in, TB_DP_AUX_TX_HOPID, out, 1484 1426 TB_DP_AUX_TX_HOPID, link_nr, "AUX TX"); 1485 1427 if (!path) 1486 1428 goto err_free; 1487 - tb_dp_init_aux_path(path); 1429 + tb_dp_init_aux_path(path, pm_support); 1488 1430 paths[TB_DP_AUX_PATH_OUT] = path; 1489 1431 1490 1432 path = tb_path_alloc(tb, out, TB_DP_AUX_RX_HOPID, in, 1491 1433 TB_DP_AUX_RX_HOPID, link_nr, "AUX RX"); 1492 1434 if (!path) 1493 1435 goto err_free; 1494 - tb_dp_init_aux_path(path); 1436 + tb_dp_init_aux_path(path, pm_support); 1495 1437 paths[TB_DP_AUX_PATH_IN] = path; 1496 1438 1497 1439 return tunnel; ··· 1557 1497 path->ingress_fc_enable = TB_PATH_ALL; 1558 1498 path->egress_shared_buffer = TB_PATH_NONE; 1559 1499 path->ingress_shared_buffer = TB_PATH_NONE; 1560 - path->priority = 5; 1561 - path->weight = 1; 1500 + path->priority = TB_DMA_PRIORITY; 1501 + path->weight = TB_DMA_WEIGHT; 1562 1502 path->clear_fc = true; 1563 1503 1564 1504 /* ··· 1591 1531 path->ingress_fc_enable = TB_PATH_ALL; 1592 1532 path->egress_shared_buffer = TB_PATH_NONE; 1593 1533 path->ingress_shared_buffer = TB_PATH_NONE; 1594 - path->priority = 5; 1595 - path->weight = 1; 1534 + path->priority = TB_DMA_PRIORITY; 1535 + path->weight = TB_DMA_WEIGHT; 1596 1536 path->clear_fc = true; 1597 1537 1598 1538 tb_path_for_each_hop(path, hop) { ··· 1818 1758 static int tb_usb3_consumed_bandwidth(struct tb_tunnel *tunnel, 1819 1759 int *consumed_up, int *consumed_down) 1820 1760 { 1821 - int pcie_enabled = tb_acpi_may_tunnel_pcie(); 1761 + struct tb_port *port = tb_upstream_port(tunnel->dst_port->sw); 1762 + int pcie_weight = tb_acpi_may_tunnel_pcie() ? TB_PCI_WEIGHT : 0; 1822 1763 1823 1764 /* 1824 1765 * PCIe tunneling, if enabled, affects the USB3 bandwidth so 1825 1766 * take that it into account here. 1826 1767 */ 1827 - *consumed_up = tunnel->allocated_up * (3 + pcie_enabled) / 3; 1828 - *consumed_down = tunnel->allocated_down * (3 + pcie_enabled) / 3; 1768 + *consumed_up = tunnel->allocated_up * 1769 + (TB_USB3_WEIGHT + pcie_weight) / TB_USB3_WEIGHT; 1770 + *consumed_down = tunnel->allocated_down * 1771 + (TB_USB3_WEIGHT + pcie_weight) / TB_USB3_WEIGHT; 1772 + 1773 + if (tb_port_get_link_generation(port) >= 4) { 1774 + *consumed_up = max(*consumed_up, USB4_V2_USB3_MIN_BANDWIDTH); 1775 + *consumed_down = max(*consumed_down, USB4_V2_USB3_MIN_BANDWIDTH); 1776 + } 1777 + 1829 1778 return 0; 1830 1779 } 1831 1780 ··· 1859 1790 { 1860 1791 int ret, max_rate, allocate_up, allocate_down; 1861 1792 1862 - ret = usb4_usb3_port_actual_link_rate(tunnel->src_port); 1793 + ret = tb_usb3_max_link_rate(tunnel->dst_port, tunnel->src_port); 1863 1794 if (ret < 0) { 1864 - tb_tunnel_warn(tunnel, "failed to read actual link rate\n"); 1795 + tb_tunnel_warn(tunnel, "failed to read maximum link rate\n"); 1865 1796 return; 1866 - } else if (!ret) { 1867 - /* Use maximum link rate if the link valid is not set */ 1868 - ret = tb_usb3_max_link_rate(tunnel->dst_port, tunnel->src_port); 1869 - if (ret < 0) { 1870 - tb_tunnel_warn(tunnel, "failed to read maximum link rate\n"); 1871 - return; 1872 - } 1873 1797 } 1874 1798 1875 1799 /* ··· 1933 1871 path->egress_shared_buffer = TB_PATH_NONE; 1934 1872 path->ingress_fc_enable = TB_PATH_ALL; 1935 1873 path->ingress_shared_buffer = TB_PATH_NONE; 1936 - path->priority = 3; 1937 - path->weight = 3; 1874 + path->priority = TB_USB3_PRIORITY; 1875 + path->weight = TB_USB3_WEIGHT; 1938 1876 path->drop_packages = 0; 1939 1877 1940 1878 tb_path_for_each_hop(path, hop) ··· 2448 2386 if (tunnel->reclaim_available_bandwidth) 2449 2387 tunnel->reclaim_available_bandwidth(tunnel, available_up, 2450 2388 available_down); 2389 + } 2390 + 2391 + const char *tb_tunnel_type_name(const struct tb_tunnel *tunnel) 2392 + { 2393 + return tb_tunnel_names[tunnel->type]; 2451 2394 }
+25 -1
drivers/thunderbolt/tunnel.h
··· 80 80 bool alloc_hopid); 81 81 struct tb_tunnel *tb_tunnel_alloc_pci(struct tb *tb, struct tb_port *up, 82 82 struct tb_port *down); 83 + bool tb_tunnel_reserved_pci(struct tb_port *port, int *reserved_up, 84 + int *reserved_down); 83 85 struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb, struct tb_port *in, 84 86 bool alloc_hopid); 85 87 struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, struct tb_port *in, ··· 139 137 return tunnel->type == TB_TUNNEL_USB3; 140 138 } 141 139 142 - #endif 140 + const char *tb_tunnel_type_name(const struct tb_tunnel *tunnel); 143 141 142 + #define __TB_TUNNEL_PRINT(level, tunnel, fmt, arg...) \ 143 + do { \ 144 + struct tb_tunnel *__tunnel = (tunnel); \ 145 + level(__tunnel->tb, "%llx:%u <-> %llx:%u (%s): " fmt, \ 146 + tb_route(__tunnel->src_port->sw), \ 147 + __tunnel->src_port->port, \ 148 + tb_route(__tunnel->dst_port->sw), \ 149 + __tunnel->dst_port->port, \ 150 + tb_tunnel_type_name(__tunnel), \ 151 + ## arg); \ 152 + } while (0) 153 + 154 + #define tb_tunnel_WARN(tunnel, fmt, arg...) \ 155 + __TB_TUNNEL_PRINT(tb_WARN, tunnel, fmt, ##arg) 156 + #define tb_tunnel_warn(tunnel, fmt, arg...) \ 157 + __TB_TUNNEL_PRINT(tb_warn, tunnel, fmt, ##arg) 158 + #define tb_tunnel_info(tunnel, fmt, arg...) \ 159 + __TB_TUNNEL_PRINT(tb_info, tunnel, fmt, ##arg) 160 + #define tb_tunnel_dbg(tunnel, fmt, arg...) \ 161 + __TB_TUNNEL_PRINT(tb_dbg, tunnel, fmt, ##arg) 162 + 163 + #endif
+106 -29
drivers/thunderbolt/usb4.c
··· 1455 1455 } 1456 1456 1457 1457 /** 1458 + * usb4_port_asym_supported() - If the port supports asymmetric link 1459 + * @port: USB4 port 1460 + * 1461 + * Checks if the port and the cable supports asymmetric link and returns 1462 + * %true in that case. 1463 + */ 1464 + bool usb4_port_asym_supported(struct tb_port *port) 1465 + { 1466 + u32 val; 1467 + 1468 + if (!port->cap_usb4) 1469 + return false; 1470 + 1471 + if (tb_port_read(port, &val, TB_CFG_PORT, port->cap_usb4 + PORT_CS_18, 1)) 1472 + return false; 1473 + 1474 + return !!(val & PORT_CS_18_CSA); 1475 + } 1476 + 1477 + /** 1478 + * usb4_port_asym_set_link_width() - Set link width to asymmetric or symmetric 1479 + * @port: USB4 port 1480 + * @width: Asymmetric width to configure 1481 + * 1482 + * Sets USB4 port link width to @width. Can be called for widths where 1483 + * usb4_port_asym_width_supported() returned @true. 1484 + */ 1485 + int usb4_port_asym_set_link_width(struct tb_port *port, enum tb_link_width width) 1486 + { 1487 + u32 val; 1488 + int ret; 1489 + 1490 + if (!port->cap_phy) 1491 + return -EINVAL; 1492 + 1493 + ret = tb_port_read(port, &val, TB_CFG_PORT, 1494 + port->cap_phy + LANE_ADP_CS_1, 1); 1495 + if (ret) 1496 + return ret; 1497 + 1498 + val &= ~LANE_ADP_CS_1_TARGET_WIDTH_ASYM_MASK; 1499 + switch (width) { 1500 + case TB_LINK_WIDTH_DUAL: 1501 + val |= FIELD_PREP(LANE_ADP_CS_1_TARGET_WIDTH_ASYM_MASK, 1502 + LANE_ADP_CS_1_TARGET_WIDTH_ASYM_DUAL); 1503 + break; 1504 + case TB_LINK_WIDTH_ASYM_TX: 1505 + val |= FIELD_PREP(LANE_ADP_CS_1_TARGET_WIDTH_ASYM_MASK, 1506 + LANE_ADP_CS_1_TARGET_WIDTH_ASYM_TX); 1507 + break; 1508 + case TB_LINK_WIDTH_ASYM_RX: 1509 + val |= FIELD_PREP(LANE_ADP_CS_1_TARGET_WIDTH_ASYM_MASK, 1510 + LANE_ADP_CS_1_TARGET_WIDTH_ASYM_RX); 1511 + break; 1512 + default: 1513 + return -EINVAL; 1514 + } 1515 + 1516 + return tb_port_write(port, &val, TB_CFG_PORT, 1517 + port->cap_phy + LANE_ADP_CS_1, 1); 1518 + } 1519 + 1520 + /** 1521 + * usb4_port_asym_start() - Start symmetry change and wait for completion 1522 + * @port: USB4 port 1523 + * 1524 + * Start symmetry change of the link to asymmetric or symmetric 1525 + * (according to what was previously set in tb_port_set_link_width(). 1526 + * Wait for completion of the change. 1527 + * 1528 + * Returns %0 in case of success, %-ETIMEDOUT if case of timeout or 1529 + * a negative errno in case of a failure. 1530 + */ 1531 + int usb4_port_asym_start(struct tb_port *port) 1532 + { 1533 + int ret; 1534 + u32 val; 1535 + 1536 + ret = tb_port_read(port, &val, TB_CFG_PORT, 1537 + port->cap_usb4 + PORT_CS_19, 1); 1538 + if (ret) 1539 + return ret; 1540 + 1541 + val &= ~PORT_CS_19_START_ASYM; 1542 + val |= FIELD_PREP(PORT_CS_19_START_ASYM, 1); 1543 + 1544 + ret = tb_port_write(port, &val, TB_CFG_PORT, 1545 + port->cap_usb4 + PORT_CS_19, 1); 1546 + if (ret) 1547 + return ret; 1548 + 1549 + /* 1550 + * Wait for PORT_CS_19_START_ASYM to be 0. This means the USB4 1551 + * port started the symmetry transition. 1552 + */ 1553 + ret = usb4_port_wait_for_bit(port, port->cap_usb4 + PORT_CS_19, 1554 + PORT_CS_19_START_ASYM, 0, 1000); 1555 + if (ret) 1556 + return ret; 1557 + 1558 + /* Then wait for the transtion to be completed */ 1559 + return usb4_port_wait_for_bit(port, port->cap_usb4 + PORT_CS_18, 1560 + PORT_CS_18_TIP, 0, 5000); 1561 + } 1562 + 1563 + /** 1458 1564 * usb4_port_margining_caps() - Read USB4 port marginig capabilities 1459 1565 * @port: USB4 port 1460 1566 * @caps: Array with at least two elements to hold the results ··· 2048 1942 2049 1943 lr = (val & ADP_USB3_CS_4_MSLR_MASK) >> ADP_USB3_CS_4_MSLR_SHIFT; 2050 1944 ret = lr == ADP_USB3_CS_4_MSLR_20G ? 20000 : 10000; 2051 - 2052 - return usb4_usb3_port_max_bandwidth(port, ret); 2053 - } 2054 - 2055 - /** 2056 - * usb4_usb3_port_actual_link_rate() - Established USB3 link rate 2057 - * @port: USB3 adapter port 2058 - * 2059 - * Return actual established link rate of a USB3 adapter in Mb/s. If the 2060 - * link is not up returns %0 and negative errno in case of failure. 2061 - */ 2062 - int usb4_usb3_port_actual_link_rate(struct tb_port *port) 2063 - { 2064 - int ret, lr; 2065 - u32 val; 2066 - 2067 - if (!tb_port_is_usb3_down(port) && !tb_port_is_usb3_up(port)) 2068 - return -EINVAL; 2069 - 2070 - ret = tb_port_read(port, &val, TB_CFG_PORT, 2071 - port->cap_adap + ADP_USB3_CS_4, 1); 2072 - if (ret) 2073 - return ret; 2074 - 2075 - if (!(val & ADP_USB3_CS_4_ULV)) 2076 - return 0; 2077 - 2078 - lr = val & ADP_USB3_CS_4_ALR_MASK; 2079 - ret = lr == ADP_USB3_CS_4_ALR_20G ? 20000 : 10000; 2080 1945 2081 1946 return usb4_usb3_port_max_bandwidth(port, ret); 2082 1947 }
+1 -1
include/linux/thunderbolt.h
··· 175 175 * enum tb_link_width - Thunderbolt/USB4 link width 176 176 * @TB_LINK_WIDTH_SINGLE: Single lane link 177 177 * @TB_LINK_WIDTH_DUAL: Dual lane symmetric link 178 - * @TB_LINK_WIDTH_ASYM_TX: Dual lane asymmetric Gen 4 link with 3 trasmitters 178 + * @TB_LINK_WIDTH_ASYM_TX: Dual lane asymmetric Gen 4 link with 3 transmitters 179 179 * @TB_LINK_WIDTH_ASYM_RX: Dual lane asymmetric Gen 4 link with 3 receivers 180 180 */ 181 181 enum tb_link_width {