History

thunderbolt: Add support for XDomain lane bonding

The USB4 Inter-Domain Service specification defines a protocol that can be used to establish lane bonding between two USB4 domains (hosts). So far we have not implemented it because the host controller DMA was not fast enough to be able to go over 20 Gbits/s even if lanes were bonded. However, starting from Intel Alder Lake CPUs the DMA can go over 20 Gbits/s so now it makes more sense to add this support to the driver. Because both ends need to negotiate the bonding we add a simple state machine that tracks the connection state and does the necessary steps described by the USB4 Inter-Domain Service specification. We only establish lane bonding when both sides of the link support it. Otherwise we default to use the single lane. Also this is only done when software connection manager is used. On systems with firmware based connection manager, it handles the high-speed tunneling so bonding lanes is specific to the implementation (Intel firmware based connection manager does not support lane bonding).

Mika Westerberg committed 4 years ago

Commit 8e1de701 parent 0a2e1665 files · +595 −83Browse files

Unified · Split

5 files
  1. drivers/thunderbolt/tb.c +0 −6
  2. drivers/thunderbolt/tb_msgs.h +39 −0
  3. drivers/thunderbolt/tb_regs.h +5 −0
  4. drivers/thunderbolt/xdomain.c +541 −68
  5. include/linux/thunderbolt.h +10 −9
drivers/thunderbolt/tb.c+0−6
@@ -169,12 +169,6 @@ static void tb_discover_tunnels(struct tb *tb) · 168 unmodified lines
169 169
170static int tb_port_configure_xdomain(struct tb_port *port)170static int tb_port_configure_xdomain(struct tb_port *port)
171{171{
172 /*
173 * XDomain paths currently only support single lane so we must
174 * disable the other lane according to USB4 spec.
175 */
176 tb_port_disable(port->dual_link_port);
177
178 if (tb_switch_is_usb4(port->sw))172 if (tb_switch_is_usb4(port->sw))
179 return usb4_port_configure_xdomain(port);173 return usb4_port_configure_xdomain(port);
180 return tb_lc_configure_xdomain(port);174 return tb_lc_configure_xdomain(port);
drivers/thunderbolt/tb_msgs.h+39−0
@@ -527,6 +527,10 @@ enum tb_xdp_type { · 526 unmodified lines
527 PROPERTIES_CHANGED_RESPONSE,527 PROPERTIES_CHANGED_RESPONSE,
528 ERROR_RESPONSE,528 ERROR_RESPONSE,
529 UUID_REQUEST = 12,529 UUID_REQUEST = 12,
530 LINK_STATE_STATUS_REQUEST = 15,
531 LINK_STATE_STATUS_RESPONSE,
532 LINK_STATE_CHANGE_REQUEST,
533 LINK_STATE_CHANGE_RESPONSE,
530};534};
531 535
532struct tb_xdp_header {536struct tb_xdp_header {
@@ -540,6 +544,41 @@ struct tb_xdp_error_response { · 7 unmodified lines
540 u32 error;544 u32 error;
541};545};
542 546
547struct tb_xdp_link_state_status {
548 struct tb_xdp_header hdr;
549};
550
551struct tb_xdp_link_state_status_response {
552 union {
553 struct tb_xdp_error_response err;
554 struct {
555 struct tb_xdp_header hdr;
556 u32 status;
557 u8 slw;
558 u8 tlw;
559 u8 sls;
560 u8 tls;
561 };
562 };
563};
564
565struct tb_xdp_link_state_change {
566 struct tb_xdp_header hdr;
567 u8 tlw;
568 u8 tls;
569 u16 reserved;
570};
571
572struct tb_xdp_link_state_change_response {
573 union {
574 struct tb_xdp_error_response err;
575 struct {
576 struct tb_xdp_header hdr;
577 u32 status;
578 };
579 };
580};
581
543struct tb_xdp_uuid {582struct tb_xdp_uuid {
544 struct tb_xdp_header hdr;583 struct tb_xdp_header hdr;
545};584};
drivers/thunderbolt/tb_regs.h+5−0
@@ -311,11 +311,16 @@ struct tb_regs_port_header { · 310 unmodified lines
311 311
312/* Lane adapter registers */312/* Lane adapter registers */
313#define LANE_ADP_CS_0 0x00313#define LANE_ADP_CS_0 0x00
314#define LANE_ADP_CS_0_SUPPORTED_SPEED_MASK GENMASK(19, 16)
315#define LANE_ADP_CS_0_SUPPORTED_SPEED_SHIFT 16
314#define LANE_ADP_CS_0_SUPPORTED_WIDTH_MASK GENMASK(25, 20)316#define LANE_ADP_CS_0_SUPPORTED_WIDTH_MASK GENMASK(25, 20)
315#define LANE_ADP_CS_0_SUPPORTED_WIDTH_SHIFT 20317#define LANE_ADP_CS_0_SUPPORTED_WIDTH_SHIFT 20
318#define LANE_ADP_CS_0_SUPPORTED_WIDTH_DUAL 0x2
316#define LANE_ADP_CS_0_CL0S_SUPPORT BIT(26)319#define LANE_ADP_CS_0_CL0S_SUPPORT BIT(26)
317#define LANE_ADP_CS_0_CL1_SUPPORT BIT(27)320#define LANE_ADP_CS_0_CL1_SUPPORT BIT(27)
318#define LANE_ADP_CS_1 0x01321#define LANE_ADP_CS_1 0x01
322#define LANE_ADP_CS_1_TARGET_SPEED_MASK GENMASK(3, 0)
323#define LANE_ADP_CS_1_TARGET_SPEED_GEN3 0xc
319#define LANE_ADP_CS_1_TARGET_WIDTH_MASK GENMASK(9, 4)324#define LANE_ADP_CS_1_TARGET_WIDTH_MASK GENMASK(9, 4)
320#define LANE_ADP_CS_1_TARGET_WIDTH_SHIFT 4325#define LANE_ADP_CS_1_TARGET_WIDTH_SHIFT 4
321#define LANE_ADP_CS_1_TARGET_WIDTH_SINGLE 0x1326#define LANE_ADP_CS_1_TARGET_WIDTH_SINGLE 0x1
drivers/thunderbolt/xdomain.c+541−68
@@ -19,13 +19,38 @@ · 18 unmodified lines
19 19
20#include "tb.h"20#include "tb.h"
21 21
22#define XDOMAIN_DEFAULT_TIMEOUT 1000 /* ms */22#define XDOMAIN_SHORT_TIMEOUT 100 /* ms */
23#define XDOMAIN_UUID_RETRIES 1023#define XDOMAIN_DEFAULT_TIMEOUT 1000 /* ms */
24#define XDOMAIN_PROPERTIES_RETRIES 1024#define XDOMAIN_BONDING_TIMEOUT 10000 /* ms */
25#define XDOMAIN_PROPERTIES_CHANGED_RETRIES 1025#define XDOMAIN_RETRIES 10
26#define XDOMAIN_BONDING_WAIT 100 /* ms */
27#define XDOMAIN_DEFAULT_MAX_HOPID 1526#define XDOMAIN_DEFAULT_MAX_HOPID 15
28 27
28enum {
29 XDOMAIN_STATE_INIT,
30 XDOMAIN_STATE_UUID,
31 XDOMAIN_STATE_LINK_STATUS,
32 XDOMAIN_STATE_LINK_STATE_CHANGE,
33 XDOMAIN_STATE_LINK_STATUS2,
34 XDOMAIN_STATE_BONDING_UUID_LOW,
35 XDOMAIN_STATE_BONDING_UUID_HIGH,
36 XDOMAIN_STATE_PROPERTIES,
37 XDOMAIN_STATE_ENUMERATED,
38 XDOMAIN_STATE_ERROR,
39};
40
41static const char * const state_names[] = {
42 [XDOMAIN_STATE_INIT] = "INIT",
43 [XDOMAIN_STATE_UUID] = "UUID",
44 [XDOMAIN_STATE_LINK_STATUS] = "LINK_STATUS",
45 [XDOMAIN_STATE_LINK_STATE_CHANGE] = "LINK_STATE_CHANGE",
46 [XDOMAIN_STATE_LINK_STATUS2] = "LINK_STATUS2",
47 [XDOMAIN_STATE_BONDING_UUID_LOW] = "BONDING_UUID_LOW",
48 [XDOMAIN_STATE_BONDING_UUID_HIGH] = "BONDING_UUID_HIGH",
49 [XDOMAIN_STATE_PROPERTIES] = "PROPERTIES",
50 [XDOMAIN_STATE_ENUMERATED] = "ENUMERATED",
51 [XDOMAIN_STATE_ERROR] = "ERROR",
52};
53
29struct xdomain_request_work {54struct xdomain_request_work {
30 struct work_struct work;55 struct work_struct work;
31 struct tb_xdp_header *pkg;56 struct tb_xdp_header *pkg;
@@ -235,7 +260,7 @@ static int tb_xdp_handle_error(const struct tb_xdp_error_response *res) · 203 unmodified lines
235}260}
236 261
237static int tb_xdp_uuid_request(struct tb_ctl *ctl, u64 route, int retry,262static int tb_xdp_uuid_request(struct tb_ctl *ctl, u64 route, int retry,
238 uuid_t *uuid)263 uuid_t *uuid, u64 *remote_route)
239{264{
240 struct tb_xdp_uuid_response res;265 struct tb_xdp_uuid_response res;
241 struct tb_xdp_uuid req;266 struct tb_xdp_uuid req;
@@ -258,6 +283,8 @@ static int tb_xdp_uuid_request(struct tb_ctl *ctl, u64 route, int retry, · 16 unmodified lines
258 return ret;283 return ret;
259 284
260 uuid_copy(uuid, &res.src_uuid);285 uuid_copy(uuid, &res.src_uuid);
286 *remote_route = (u64)res.src_route_hi << 32 | res.src_route_lo;
287
261 return 0;288 return 0;
262}289}
263 290
@@ -473,6 +500,112 @@ tb_xdp_properties_changed_response(struct tb_ctl *ctl, u64 route, u8 sequence) · 209 unmodified lines
473 TB_CFG_PKG_XDOMAIN_RESP);500 TB_CFG_PKG_XDOMAIN_RESP);
474}501}
475 502
503static int tb_xdp_link_state_status_request(struct tb_ctl *ctl, u64 route,
504 u8 sequence, u8 *slw, u8 *tlw,
505 u8 *sls, u8 *tls)
506{
507 struct tb_xdp_link_state_status_response res;
508 struct tb_xdp_link_state_status req;
509 int ret;
510
511 memset(&req, 0, sizeof(req));
512 tb_xdp_fill_header(&req.hdr, route, sequence, LINK_STATE_STATUS_REQUEST,
513 sizeof(req));
514
515 memset(&res, 0, sizeof(res));
516 ret = __tb_xdomain_request(ctl, &req, sizeof(req), TB_CFG_PKG_XDOMAIN_REQ,
517 &res, sizeof(res), TB_CFG_PKG_XDOMAIN_RESP,
518 XDOMAIN_DEFAULT_TIMEOUT);
519 if (ret)
520 return ret;
521
522 ret = tb_xdp_handle_error(&res.err);
523 if (ret)
524 return ret;
525
526 if (res.status != 0)
527 return -EREMOTEIO;
528
529 *slw = res.slw;
530 *tlw = res.tlw;
531 *sls = res.sls;
532 *tls = res.tls;
533
534 return 0;
535}
536
537static int tb_xdp_link_state_status_response(struct tb *tb, struct tb_ctl *ctl,
538 struct tb_xdomain *xd, u8 sequence)
539{
540 struct tb_switch *sw = tb_to_switch(xd->dev.parent);
541 struct tb_xdp_link_state_status_response res;
542 struct tb_port *port = tb_port_at(xd->route, sw);
543 u32 val[2];
544 int ret;
545
546 memset(&res, 0, sizeof(res));
547 tb_xdp_fill_header(&res.hdr, xd->route, sequence,
548 LINK_STATE_STATUS_RESPONSE, sizeof(res));
549
550 ret = tb_port_read(port, val, TB_CFG_PORT,
551 port->cap_phy + LANE_ADP_CS_0, ARRAY_SIZE(val));
552 if (ret)
553 return ret;
554
555 res.slw = (val[0] & LANE_ADP_CS_0_SUPPORTED_WIDTH_MASK) >>
556 LANE_ADP_CS_0_SUPPORTED_WIDTH_SHIFT;
557 res.sls = (val[0] & LANE_ADP_CS_0_SUPPORTED_SPEED_MASK) >>
558 LANE_ADP_CS_0_SUPPORTED_SPEED_SHIFT;
559 res.tls = val[1] & LANE_ADP_CS_1_TARGET_SPEED_MASK;
560 res.tlw = (val[1] & LANE_ADP_CS_1_TARGET_WIDTH_MASK) >>
561 LANE_ADP_CS_1_TARGET_WIDTH_SHIFT;
562
563 return __tb_xdomain_response(ctl, &res, sizeof(res),
564 TB_CFG_PKG_XDOMAIN_RESP);
565}
566
567static int tb_xdp_link_state_change_request(struct tb_ctl *ctl, u64 route,
568 u8 sequence, u8 tlw, u8 tls)
569{
570 struct tb_xdp_link_state_change_response res;
571 struct tb_xdp_link_state_change req;
572 int ret;
573
574 memset(&req, 0, sizeof(req));
575 tb_xdp_fill_header(&req.hdr, route, sequence, LINK_STATE_CHANGE_REQUEST,
576 sizeof(req));
577 req.tlw = tlw;
578 req.tls = tls;
579
580 memset(&res, 0, sizeof(res));
581 ret = __tb_xdomain_request(ctl, &req, sizeof(req), TB_CFG_PKG_XDOMAIN_REQ,
582 &res, sizeof(res), TB_CFG_PKG_XDOMAIN_RESP,
583 XDOMAIN_DEFAULT_TIMEOUT);
584 if (ret)
585 return ret;
586
587 ret = tb_xdp_handle_error(&res.err);
588 if (ret)
589 return ret;
590
591 return res.status != 0 ? -EREMOTEIO : 0;
592}
593
594static int tb_xdp_link_state_change_response(struct tb_ctl *ctl, u64 route,
595 u8 sequence, u32 status)
596{
597 struct tb_xdp_link_state_change_response res;
598
599 memset(&res, 0, sizeof(res));
600 tb_xdp_fill_header(&res.hdr, route, sequence, LINK_STATE_CHANGE_RESPONSE,
601 sizeof(res));
602
603 res.status = status;
604
605 return __tb_xdomain_response(ctl, &res, sizeof(res),
606 TB_CFG_PKG_XDOMAIN_RESP);
607}
608
476/**609/**
477 * tb_register_protocol_handler() - Register protocol handler610 * tb_register_protocol_handler() - Register protocol handler
478 * @handler: Handler to register611 * @handler: Handler to register
@@ -600,14 +733,13 @@ static void tb_xdp_handle_request(struct work_struct *work) · 121 unmodified lines
600 goto out;733 goto out;
601 }734 }
602 735
603 tb_dbg(tb, "%llx: received XDomain request %#x\n", route, pkg->type);
604
605 xd = tb_xdomain_find_by_route_locked(tb, route);736 xd = tb_xdomain_find_by_route_locked(tb, route);
606 if (xd)737 if (xd)
607 update_property_block(xd);738 update_property_block(xd);
608 739
609 switch (pkg->type) {740 switch (pkg->type) {
610 case PROPERTIES_REQUEST:741 case PROPERTIES_REQUEST:
742 tb_dbg(tb, "%llx: received XDomain properties request\n", route);
611 if (xd) {743 if (xd) {
612 ret = tb_xdp_properties_response(tb, ctl, xd, sequence,744 ret = tb_xdp_properties_response(tb, ctl, xd, sequence,
613 (const struct tb_xdp_properties *)pkg);745 (const struct tb_xdp_properties *)pkg);
@@ -615,6 +747,9 @@ static void tb_xdp_handle_request(struct work_struct *work) · 1 unmodified line
615 break;747 break;
616 748
617 case PROPERTIES_CHANGED_REQUEST:749 case PROPERTIES_CHANGED_REQUEST:
750 tb_dbg(tb, "%llx: received XDomain properties changed request\n",
751 route);
752
618 ret = tb_xdp_properties_changed_response(ctl, route, sequence);753 ret = tb_xdp_properties_changed_response(ctl, route, sequence);
619 754
620 /*755 /*
@@ -622,18 +757,51 @@ static void tb_xdp_handle_request(struct work_struct *work) · 1 unmodified line
622 * the xdomain related to this connection as well in757 * the xdomain related to this connection as well in
623 * case there is a change in services it offers.758 * case there is a change in services it offers.
624 */759 */
625 if (xd && device_is_registered(&xd->dev)) {760 if (xd && device_is_registered(&xd->dev))
626 queue_delayed_work(tb->wq, &xd->get_properties_work,761 queue_delayed_work(tb->wq, &xd->state_work,
627 msecs_to_jiffies(50));762 msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
628 }
629 break;763 break;
630 764
631 case UUID_REQUEST_OLD:765 case UUID_REQUEST_OLD:
632 case UUID_REQUEST:766 case UUID_REQUEST:
767 tb_dbg(tb, "%llx: received XDomain UUID request\n", route);
633 ret = tb_xdp_uuid_response(ctl, route, sequence, uuid);768 ret = tb_xdp_uuid_response(ctl, route, sequence, uuid);
634 break;769 break;
635 770
771 case LINK_STATE_STATUS_REQUEST:
772 tb_dbg(tb, "%llx: received XDomain link state status request\n",
773 route);
774
775 if (xd) {
776 ret = tb_xdp_link_state_status_response(tb, ctl, xd,
777 sequence);
778 } else {
779 tb_xdp_error_response(ctl, route, sequence,
780 ERROR_NOT_READY);
781 }
782 break;
783
784 case LINK_STATE_CHANGE_REQUEST:
785 tb_dbg(tb, "%llx: received XDomain link state change request\n",
786 route);
787
788 if (xd && xd->state == XDOMAIN_STATE_BONDING_UUID_HIGH) {
789 const struct tb_xdp_link_state_change *lsc =
790 (const struct tb_xdp_link_state_change *)pkg;
791
792 ret = tb_xdp_link_state_change_response(ctl, route,
793 sequence, 0);
794 xd->target_link_width = lsc->tlw;
795 queue_delayed_work(tb->wq, &xd->state_work,
796 msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
797 } else {
798 tb_xdp_error_response(ctl, route, sequence,
799 ERROR_NOT_READY);
800 }
801 break;
802
636 default:803 default:
804 tb_dbg(tb, "%llx: unknown XDomain request %#x\n", route, pkg->type);
637 tb_xdp_error_response(ctl, route, sequence,805 tb_xdp_error_response(ctl, route, sequence,
638 ERROR_NOT_SUPPORTED);806 ERROR_NOT_SUPPORTED);
639 break;807 break;
@@ -1000,32 +1168,38 @@ static int tb_xdomain_update_link_attributes(struct tb_xdomain *xd) · 360 unmodified lines
1000 return 0;1168 return 0;
1001}1169}
1002 1170
1003static void tb_xdomain_get_uuid(struct work_struct *work)1171static int tb_xdomain_get_uuid(struct tb_xdomain *xd)
1004{1172{
1005 struct tb_xdomain *xd = container_of(work, typeof(*xd),
1006 get_uuid_work.work);
1007 struct tb *tb = xd->tb;1173 struct tb *tb = xd->tb;
1008 uuid_t uuid;1174 uuid_t uuid;
1175 u64 route;
1009 int ret;1176 int ret;
1010 1177
1011 dev_dbg(&xd->dev, "requesting remote UUID\n");1178 dev_dbg(&xd->dev, "requesting remote UUID\n");
1012 1179
1013 ret = tb_xdp_uuid_request(tb->ctl, xd->route, xd->uuid_retries, &uuid);1180 ret = tb_xdp_uuid_request(tb->ctl, xd->route, xd->state_retries, &uuid,
1181 &route);
1014 if (ret < 0) {1182 if (ret < 0) {
1015 if (xd->uuid_retries-- > 0) {1183 if (xd->state_retries-- > 0) {
1016 dev_dbg(&xd->dev, "failed to request UUID, retrying\n");1184 dev_dbg(&xd->dev, "failed to request UUID, retrying\n");
1017 queue_delayed_work(xd->tb->wq, &xd->get_uuid_work,1185 return -EAGAIN;
1018 msecs_to_jiffies(100));
1019 } else {1186 } else {
1020 dev_dbg(&xd->dev, "failed to read remote UUID\n");1187 dev_dbg(&xd->dev, "failed to read remote UUID\n");
1021 }1188 }
1022 return;1189 return ret;
1023 }1190 }
1024 1191
1025 dev_dbg(&xd->dev, "got remote UUID %pUb\n", &uuid);1192 dev_dbg(&xd->dev, "got remote UUID %pUb\n", &uuid);
1026 1193
1027 if (uuid_equal(&uuid, xd->local_uuid))1194 if (uuid_equal(&uuid, xd->local_uuid)) {
1028 dev_dbg(&xd->dev, "intra-domain loop detected\n");1195 if (route == xd->route)
1196 dev_dbg(&xd->dev, "loop back detected\n");
1197 else
1198 dev_dbg(&xd->dev, "intra-domain loop detected\n");
1199
1200 /* Don't bond lanes automatically for loops */
1201 xd->bonding_possible = false;
1202 }
1029 1203
1030 /*1204 /*
1031 * If the UUID is different, there is another domain connected1205 * If the UUID is different, there is another domain connected
@@ -1035,27 +1209,152 @@ static void tb_xdomain_get_uuid(struct work_struct *work) · 3 unmodified lines
1035 if (xd->remote_uuid && !uuid_equal(&uuid, xd->remote_uuid)) {1209 if (xd->remote_uuid && !uuid_equal(&uuid, xd->remote_uuid)) {
1036 dev_dbg(&xd->dev, "remote UUID is different, unplugging\n");1210 dev_dbg(&xd->dev, "remote UUID is different, unplugging\n");
1037 xd->is_unplugged = true;1211 xd->is_unplugged = true;
1038 return;1212 return -ENODEV;
1039 }1213 }
1040 1214
1041 /* First time fill in the missing UUID */1215 /* First time fill in the missing UUID */
1042 if (!xd->remote_uuid) {1216 if (!xd->remote_uuid) {
1043 xd->remote_uuid = kmemdup(&uuid, sizeof(uuid_t), GFP_KERNEL);1217 xd->remote_uuid = kmemdup(&uuid, sizeof(uuid_t), GFP_KERNEL);
1044 if (!xd->remote_uuid)1218 if (!xd->remote_uuid)
1045 return;1219 return -ENOMEM;
1046 }1220 }
1047 1221
1048 /* Now we can start the normal properties exchange */1222 return 0;
1049 queue_delayed_work(xd->tb->wq, &xd->properties_changed_work,
1050 msecs_to_jiffies(100));
1051 queue_delayed_work(xd->tb->wq, &xd->get_properties_work,
1052 msecs_to_jiffies(1000));
1053}1223}
1054 1224
1055static void tb_xdomain_get_properties(struct work_struct *work)1225static int tb_xdomain_get_link_status(struct tb_xdomain *xd)
1226{
1227 struct tb *tb = xd->tb;
1228 u8 slw, tlw, sls, tls;
1229 int ret;
1230
1231 dev_dbg(&xd->dev, "sending link state status request to %pUb\n",
1232 xd->remote_uuid);
1233
1234 ret = tb_xdp_link_state_status_request(tb->ctl, xd->route,
1235 xd->state_retries, &slw, &tlw, &sls,
1236 &tls);
1237 if (ret) {
1238 if (ret != -EOPNOTSUPP && xd->state_retries-- > 0) {
1239 dev_dbg(&xd->dev,
1240 "failed to request remote link status, retrying\n");
1241 return -EAGAIN;
1242 }
1243 dev_dbg(&xd->dev, "failed to receive remote link status\n");
1244 return ret;
1245 }
1246
1247 dev_dbg(&xd->dev, "remote link supports width %#x speed %#x\n", slw, sls);
1248
1249 if (slw < LANE_ADP_CS_0_SUPPORTED_WIDTH_DUAL) {
1250 dev_dbg(&xd->dev, "remote adapter is single lane only\n");
1251 return -EOPNOTSUPP;
1252 }
1253
1254 return 0;
1255}
1256
1257static int tb_xdomain_link_state_change(struct tb_xdomain *xd,
1258 unsigned int width)
1259{
1260 struct tb_switch *sw = tb_to_switch(xd->dev.parent);
1261 struct tb_port *port = tb_port_at(xd->route, sw);
1262 struct tb *tb = xd->tb;
1263 u8 tlw, tls;
1264 u32 val;
1265 int ret;
1266
1267 if (width == 2)
1268 tlw = LANE_ADP_CS_1_TARGET_WIDTH_DUAL;
1269 else if (width == 1)
1270 tlw = LANE_ADP_CS_1_TARGET_WIDTH_SINGLE;
1271 else
1272 return -EINVAL;
1273
1274 /* Use the current target speed */
1275 ret = tb_port_read(port, &val, TB_CFG_PORT, port->cap_phy + LANE_ADP_CS_1, 1);
1276 if (ret)
1277 return ret;
1278 tls = val & LANE_ADP_CS_1_TARGET_SPEED_MASK;
1279
1280 dev_dbg(&xd->dev, "sending link state change request with width %#x speed %#x\n",
1281 tlw, tls);
1282
1283 ret = tb_xdp_link_state_change_request(tb->ctl, xd->route,
1284 xd->state_retries, tlw, tls);
1285 if (ret) {
1286 if (ret != -EOPNOTSUPP && xd->state_retries-- > 0) {
1287 dev_dbg(&xd->dev,
1288 "failed to change remote link state, retrying\n");
1289 return -EAGAIN;
1290 }
1291 dev_err(&xd->dev, "failed request link state change, aborting\n");
1292 return ret;
1293 }
1294
1295 dev_dbg(&xd->dev, "received link state change response\n");
1296 return 0;
1297}
1298
1299static int tb_xdomain_bond_lanes_uuid_high(struct tb_xdomain *xd)
1300{
1301 struct tb_port *port;
1302 int ret, width;
1303
1304 if (xd->target_link_width == LANE_ADP_CS_1_TARGET_WIDTH_SINGLE) {
1305 width = 1;
1306 } else if (xd->target_link_width == LANE_ADP_CS_1_TARGET_WIDTH_DUAL) {
1307 width = 2;
1308 } else {
1309 if (xd->state_retries-- > 0) {
1310 dev_dbg(&xd->dev,
1311 "link state change request not received yet, retrying\n");
1312 return -EAGAIN;
1313 }
1314 dev_dbg(&xd->dev, "timeout waiting for link change request\n");
1315 return -ETIMEDOUT;
1316 }
1317
1318 port = tb_port_at(xd->route, tb_xdomain_parent(xd));
1319
1320 /*
1321 * We can't use tb_xdomain_lane_bonding_enable() here because it
1322 * is the other side that initiates lane bonding. So here we
1323 * just set the width to both lane adapters and wait for the
1324 * link to transition bonded.
1325 */
1326 ret = tb_port_set_link_width(port->dual_link_port, width);
1327 if (ret) {
1328 tb_port_warn(port->dual_link_port,
1329 "failed to set link width to %d\n", width);
1330 return ret;
1331 }
1332
1333 ret = tb_port_set_link_width(port, width);
1334 if (ret) {
1335 tb_port_warn(port, "failed to set link width to %d\n", width);
1336 return ret;
1337 }
1338
1339 ret = tb_port_wait_for_link_width(port, width, XDOMAIN_BONDING_TIMEOUT);
1340 if (ret) {
1341 dev_warn(&xd->dev, "error waiting for link width to become %d\n",
1342 width);
1343 return ret;
1344 }
1345
1346 port->bonded = width == 2;
1347 port->dual_link_port->bonded = width == 2;
1348
1349 tb_port_update_credits(port);
1350 tb_xdomain_update_link_attributes(xd);
1351
1352 dev_dbg(&xd->dev, "lane bonding %sabled\n", width == 2 ? "en" : "dis");
1353 return 0;
1354}
1355
1356static int tb_xdomain_get_properties(struct tb_xdomain *xd)
1056{1357{
1057 struct tb_xdomain *xd = container_of(work, typeof(*xd),
1058 get_properties_work.work);
1059 struct tb_property_dir *dir;1358 struct tb_property_dir *dir;
1060 struct tb *tb = xd->tb;1359 struct tb *tb = xd->tb;
1061 bool update = false;1360 bool update = false;
@@ -1066,34 +1365,35 @@ static void tb_xdomain_get_properties(struct work_struct *work) · 4 unmodified lines
1066 dev_dbg(&xd->dev, "requesting remote properties\n");1365 dev_dbg(&xd->dev, "requesting remote properties\n");
1067 1366
1068 ret = tb_xdp_properties_request(tb->ctl, xd->route, xd->local_uuid,1367 ret = tb_xdp_properties_request(tb->ctl, xd->route, xd->local_uuid,
1069 xd->remote_uuid, xd->properties_retries,1368 xd->remote_uuid, xd->state_retries,
1070 &block, &gen);1369 &block, &gen);
1071 if (ret < 0) {1370 if (ret < 0) {
1072 if (xd->properties_retries-- > 0) {1371 if (xd->state_retries-- > 0) {
1073 dev_dbg(&xd->dev,1372 dev_dbg(&xd->dev,
1074 "failed to request remote properties, retrying\n");1373 "failed to request remote properties, retrying\n");
1075 queue_delayed_work(xd->tb->wq, &xd->get_properties_work,1374 return -EAGAIN;
1076 msecs_to_jiffies(1000));
1077 } else {1375 } else {
1078 /* Give up now */1376 /* Give up now */
1079 dev_err(&xd->dev,1377 dev_err(&xd->dev,
1080 "failed read XDomain properties from %pUb\n",1378 "failed read XDomain properties from %pUb\n",
1081 xd->remote_uuid);1379 xd->remote_uuid);
1082 }1380 }
1083 return;
1084 }
1085 1381
1086 xd->properties_retries = XDOMAIN_PROPERTIES_RETRIES;1382 return ret;
1383 }
1087 1384
1088 mutex_lock(&xd->lock);1385 mutex_lock(&xd->lock);
1089 1386
1090 /* Only accept newer generation properties */1387 /* Only accept newer generation properties */
1091 if (xd->remote_properties && gen <= xd->remote_property_block_gen)1388 if (xd->remote_properties && gen <= xd->remote_property_block_gen) {
1389 ret = 0;
1092 goto err_free_block;1390 goto err_free_block;
1391 }
1093 1392
1094 dir = tb_property_parse_dir(block, ret);1393 dir = tb_property_parse_dir(block, ret);
1095 if (!dir) {1394 if (!dir) {
1096 dev_err(&xd->dev, "failed to parse XDomain properties\n");1395 dev_err(&xd->dev, "failed to parse XDomain properties\n");
1396 ret = -ENOMEM;
1097 goto err_free_block;1397 goto err_free_block;
1098 }1398 }
1099 1399
@@ -1124,9 +1424,16 @@ static void tb_xdomain_get_properties(struct work_struct *work) · 24 unmodified lines
1124 * registered, we notify the userspace that it has changed.1424 * registered, we notify the userspace that it has changed.
1125 */1425 */
1126 if (!update) {1426 if (!update) {
1427 struct tb_port *port;
1428
1429 /* Now disable lane 1 if bonding was not enabled */
1430 port = tb_port_at(xd->route, tb_xdomain_parent(xd));
1431 if (!port->bonded)
1432 tb_port_disable(port->dual_link_port);
1433
1127 if (device_add(&xd->dev)) {1434 if (device_add(&xd->dev)) {
1128 dev_err(&xd->dev, "failed to add XDomain device\n");1435 dev_err(&xd->dev, "failed to add XDomain device\n");
1129 return;1436 return -ENODEV;
1130 }1437 }
1131 dev_info(&xd->dev, "new host found, vendor=%#x device=%#x\n",1438 dev_info(&xd->dev, "new host found, vendor=%#x device=%#x\n",
1132 xd->vendor, xd->device);1439 xd->vendor, xd->device);
@@ -1138,13 +1445,193 @@ static void tb_xdomain_get_properties(struct work_struct *work) · 5 unmodified lines
1138 }1445 }
1139 1446
1140 enumerate_services(xd);1447 enumerate_services(xd);
1141 return;1448 return 0;
1142 1449
1143err_free_dir:1450err_free_dir:
1144 tb_property_free_dir(dir);1451 tb_property_free_dir(dir);
1145err_free_block:1452err_free_block:
1146 kfree(block);1453 kfree(block);
1147 mutex_unlock(&xd->lock);1454 mutex_unlock(&xd->lock);
1455
1456 return ret;
1457}
1458
1459static void tb_xdomain_queue_uuid(struct tb_xdomain *xd)
1460{
1461 xd->state = XDOMAIN_STATE_UUID;
1462 xd->state_retries = XDOMAIN_RETRIES;
1463 queue_delayed_work(xd->tb->wq, &xd->state_work,
1464 msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
1465}
1466
1467static void tb_xdomain_queue_link_status(struct tb_xdomain *xd)
1468{
1469 xd->state = XDOMAIN_STATE_LINK_STATUS;
1470 xd->state_retries = XDOMAIN_RETRIES;
1471 queue_delayed_work(xd->tb->wq, &xd->state_work,
1472 msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT));
1473}
1474
1475static void tb_xdomain_queue_link_status2(struct tb_xdomain *xd)
1476{
1477 xd->state = XDOMAIN_STATE_LINK_STATUS2;
1478 xd->state_retries = XDOMAIN_RETRIES;
1479 queue_delayed_work(xd->tb->wq, &xd->state_work,
1480 msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT));
1481}
1482
1483static void tb_xdomain_queue_bonding(struct tb_xdomain *xd)
1484{
1485 if (memcmp(xd->local_uuid, xd->remote_uuid, UUID_SIZE) > 0) {
1486 dev_dbg(&xd->dev, "we have higher UUID, other side bonds the lanes\n");
1487 xd->state = XDOMAIN_STATE_BONDING_UUID_HIGH;
1488 } else {
1489 dev_dbg(&xd->dev, "we have lower UUID, bonding lanes\n");
1490 xd->state = XDOMAIN_STATE_LINK_STATE_CHANGE;
1491 }
1492
1493 xd->state_retries = XDOMAIN_RETRIES;
1494 queue_delayed_work(xd->tb->wq, &xd->state_work,
1495 msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT));
1496}
1497
1498static void tb_xdomain_queue_bonding_uuid_low(struct tb_xdomain *xd)
1499{
1500 xd->state = XDOMAIN_STATE_BONDING_UUID_LOW;
1501 xd->state_retries = XDOMAIN_RETRIES;
1502 queue_delayed_work(xd->tb->wq, &xd->state_work,
1503 msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT));
1504}
1505
1506static void tb_xdomain_queue_properties(struct tb_xdomain *xd)
1507{
1508 xd->state = XDOMAIN_STATE_PROPERTIES;
1509 xd->state_retries = XDOMAIN_RETRIES;
1510 queue_delayed_work(xd->tb->wq, &xd->state_work,
1511 msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT));
1512}
1513
1514static void tb_xdomain_queue_properties_changed(struct tb_xdomain *xd)
1515{
1516 xd->properties_changed_retries = XDOMAIN_RETRIES;
1517 queue_delayed_work(xd->tb->wq, &xd->properties_changed_work,
1518 msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
1519}
1520
1521static void tb_xdomain_state_work(struct work_struct *work)
1522{
1523 struct tb_xdomain *xd = container_of(work, typeof(*xd), state_work.work);
1524 int ret, state = xd->state;
1525
1526 if (WARN_ON_ONCE(state < XDOMAIN_STATE_INIT ||
1527 state > XDOMAIN_STATE_ERROR))
1528 return;
1529
1530 dev_dbg(&xd->dev, "running state %s\n", state_names[state]);
1531
1532 switch (state) {
1533 case XDOMAIN_STATE_INIT:
1534 if (xd->needs_uuid) {
1535 tb_xdomain_queue_uuid(xd);
1536 } else {
1537 tb_xdomain_queue_properties_changed(xd);
1538 tb_xdomain_queue_properties(xd);
1539 }
1540 break;
1541
1542 case XDOMAIN_STATE_UUID:
1543 ret = tb_xdomain_get_uuid(xd);
1544 if (ret) {
1545 if (ret == -EAGAIN)
1546 goto retry_state;
1547 xd->state = XDOMAIN_STATE_ERROR;
1548 } else {
1549 tb_xdomain_queue_properties_changed(xd);
1550 if (xd->bonding_possible)
1551 tb_xdomain_queue_link_status(xd);
1552 else
1553 tb_xdomain_queue_properties(xd);
1554 }
1555 break;
1556
1557 case XDOMAIN_STATE_LINK_STATUS:
1558 ret = tb_xdomain_get_link_status(xd);
1559 if (ret) {
1560 if (ret == -EAGAIN)
1561 goto retry_state;
1562
1563 /*
1564 * If any of the lane bonding states fail we skip
1565 * bonding completely and try to continue from
1566 * reading properties.
1567 */
1568 tb_xdomain_queue_properties(xd);
1569 } else {
1570 tb_xdomain_queue_bonding(xd);
1571 }
1572 break;
1573
1574 case XDOMAIN_STATE_LINK_STATE_CHANGE:
1575 ret = tb_xdomain_link_state_change(xd, 2);
1576 if (ret) {
1577 if (ret == -EAGAIN)
1578 goto retry_state;
1579 tb_xdomain_queue_properties(xd);
1580 } else {
1581 tb_xdomain_queue_link_status2(xd);
1582 }
1583 break;
1584
1585 case XDOMAIN_STATE_LINK_STATUS2:
1586 ret = tb_xdomain_get_link_status(xd);
1587 if (ret) {
1588 if (ret == -EAGAIN)
1589 goto retry_state;
1590 tb_xdomain_queue_properties(xd);
1591 } else {
1592 tb_xdomain_queue_bonding_uuid_low(xd);
1593 }
1594 break;
1595
1596 case XDOMAIN_STATE_BONDING_UUID_LOW:
1597 tb_xdomain_lane_bonding_enable(xd);
1598 tb_xdomain_queue_properties(xd);
1599 break;
1600
1601 case XDOMAIN_STATE_BONDING_UUID_HIGH:
1602 if (tb_xdomain_bond_lanes_uuid_high(xd) == -EAGAIN)
1603 goto retry_state;
1604 tb_xdomain_queue_properties(xd);
1605 break;
1606
1607 case XDOMAIN_STATE_PROPERTIES:
1608 ret = tb_xdomain_get_properties(xd);
1609 if (ret) {
1610 if (ret == -EAGAIN)
1611 goto retry_state;
1612 xd->state = XDOMAIN_STATE_ERROR;
1613 } else {
1614 xd->state = XDOMAIN_STATE_ENUMERATED;
1615 }
1616 break;
1617
1618 case XDOMAIN_STATE_ENUMERATED:
1619 tb_xdomain_queue_properties(xd);
1620 break;
1621
1622 case XDOMAIN_STATE_ERROR:
1623 break;
1624
1625 default:
1626 dev_warn(&xd->dev, "unexpected state %d\n", state);
1627 break;
1628 }
1629
1630 return;
1631
1632retry_state:
1633 queue_delayed_work(xd->tb->wq, &xd->state_work,
1634 msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT));
1148}1635}
1149 1636
1150static void tb_xdomain_properties_changed(struct work_struct *work)1637static void tb_xdomain_properties_changed(struct work_struct *work)
@@ -1163,13 +1650,13 @@ static void tb_xdomain_properties_changed(struct work_struct *work) · 12 unmodified lines
1163 "failed to send properties changed notification, retrying\n");1650 "failed to send properties changed notification, retrying\n");
1164 queue_delayed_work(xd->tb->wq,1651 queue_delayed_work(xd->tb->wq,
1165 &xd->properties_changed_work,1652 &xd->properties_changed_work,
1166 msecs_to_jiffies(1000));1653 msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT));
1167 }1654 }
1168 dev_err(&xd->dev, "failed to send properties changed notification\n");1655 dev_err(&xd->dev, "failed to send properties changed notification\n");
1169 return;1656 return;
1170 }1657 }
1171 1658
1172 xd->properties_changed_retries = XDOMAIN_PROPERTIES_CHANGED_RETRIES;1659 xd->properties_changed_retries = XDOMAIN_RETRIES;
1173}1660}
1174 1661
1175static ssize_t device_show(struct device *dev, struct device_attribute *attr,1662static ssize_t device_show(struct device *dev, struct device_attribute *attr,
@@ -1304,31 +1791,17 @@ static void tb_xdomain_release(struct device *dev) · 128 unmodified lines
1304 1791
1305static void start_handshake(struct tb_xdomain *xd)1792static void start_handshake(struct tb_xdomain *xd)
1306{1793{
1307 xd->uuid_retries = XDOMAIN_UUID_RETRIES;1794 xd->state = XDOMAIN_STATE_INIT;
1308 xd->properties_retries = XDOMAIN_PROPERTIES_RETRIES;1795 queue_delayed_work(xd->tb->wq, &xd->state_work,
1309 xd->properties_changed_retries = XDOMAIN_PROPERTIES_CHANGED_RETRIES;1796 msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
1310
1311 if (xd->needs_uuid) {
1312 queue_delayed_work(xd->tb->wq, &xd->get_uuid_work,
1313 msecs_to_jiffies(100));
1314 } else {
1315 /* Start exchanging properties with the other host */
1316 queue_delayed_work(xd->tb->wq, &xd->properties_changed_work,
1317 msecs_to_jiffies(100));
1318 queue_delayed_work(xd->tb->wq, &xd->get_properties_work,
1319 msecs_to_jiffies(1000));
1320 }
1321}1797}
1322 1798
1323static void stop_handshake(struct tb_xdomain *xd)1799static void stop_handshake(struct tb_xdomain *xd)
1324{1800{
1325 xd->uuid_retries = 0;
1326 xd->properties_retries = 0;
1327 xd->properties_changed_retries = 0;
1328
1329 cancel_delayed_work_sync(&xd->get_uuid_work);
1330 cancel_delayed_work_sync(&xd->get_properties_work);
1331 cancel_delayed_work_sync(&xd->properties_changed_work);1801 cancel_delayed_work_sync(&xd->properties_changed_work);
1802 cancel_delayed_work_sync(&xd->state_work);
1803 xd->properties_changed_retries = 0;
1804 xd->state_retries = 0;
1332}1805}
1333 1806
1334static int __maybe_unused tb_xdomain_suspend(struct device *dev)1807static int __maybe_unused tb_xdomain_suspend(struct device *dev)
@@ -1389,8 +1862,7 @@ struct tb_xdomain *tb_xdomain_alloc(struct tb *tb, struct device *parent, · 54 unmodified lines
1389 ida_init(&xd->in_hopids);1862 ida_init(&xd->in_hopids);
1390 ida_init(&xd->out_hopids);1863 ida_init(&xd->out_hopids);
1391 mutex_init(&xd->lock);1864 mutex_init(&xd->lock);
1392 INIT_DELAYED_WORK(&xd->get_uuid_work, tb_xdomain_get_uuid);1865 INIT_DELAYED_WORK(&xd->state_work, tb_xdomain_state_work);
1393 INIT_DELAYED_WORK(&xd->get_properties_work, tb_xdomain_get_properties);
1394 INIT_DELAYED_WORK(&xd->properties_changed_work,1866 INIT_DELAYED_WORK(&xd->properties_changed_work,
1395 tb_xdomain_properties_changed);1867 tb_xdomain_properties_changed);
1396 1868
@@ -1405,6 +1877,7 @@ struct tb_xdomain *tb_xdomain_alloc(struct tb *tb, struct device *parent, · 8 unmodified lines
1405 goto err_free_local_uuid;1877 goto err_free_local_uuid;
1406 } else {1878 } else {
1407 xd->needs_uuid = true;1879 xd->needs_uuid = true;
1880 xd->bonding_possible = !!down->dual_link_port;
1408 }1881 }
1409 1882
1410 device_initialize(&xd->dev);1883 device_initialize(&xd->dev);
@@ -1523,9 +1996,9 @@ int tb_xdomain_lane_bonding_enable(struct tb_xdomain *xd) · 112 unmodified lines
1523 return ret;1996 return ret;
1524 }1997 }
1525 1998
1526 ret = tb_port_wait_for_link_width(port, 2, 100);1999 ret = tb_port_wait_for_link_width(port, 2, XDOMAIN_BONDING_TIMEOUT);
1527 if (ret) {2000 if (ret) {
1528 tb_port_warn(port, "timeout enabling lane bonding\n");2001 tb_port_warn(port, "failed to enable lane bonding\n");
1529 return ret;2002 return ret;
1530 }2003 }
1531 2004
include/linux/thunderbolt.h+10−9
@@ -198,15 +198,15 @@ void tb_unregister_property_dir(const char *key, struct tb_property_dir *dir); · 197 unmodified lines
198 * @local_property_block_len: Length of the @local_property_block in dwords198 * @local_property_block_len: Length of the @local_property_block in dwords
199 * @remote_properties: Properties exported by the remote domain199 * @remote_properties: Properties exported by the remote domain
200 * @remote_property_block_gen: Generation of @remote_properties200 * @remote_property_block_gen: Generation of @remote_properties
201 * @get_uuid_work: Work used to retrieve @remote_uuid201 * @state: Next XDomain discovery state to run
202 * @uuid_retries: Number of times left @remote_uuid is requested before202 * @state_work: Work used to run the next state
203 * giving up203 * @state_retries: Number of retries remain for the state
204 * @get_properties_work: Work used to get remote domain properties
205 * @properties_retries: Number of times left to read properties
206 * @properties_changed_work: Work used to notify the remote domain that204 * @properties_changed_work: Work used to notify the remote domain that
207 * our properties have changed205 * our properties have changed
208 * @properties_changed_retries: Number of times left to send properties206 * @properties_changed_retries: Number of times left to send properties
209 * changed notification207 * changed notification
208 * @bonding_possible: True if lane bonding is possible on local side
209 * @target_link_width: Target link width from the remote host
210 * @link: Root switch link the remote domain is connected (ICM only)210 * @link: Root switch link the remote domain is connected (ICM only)
211 * @depth: Depth in the chain the remote domain is connected (ICM only)211 * @depth: Depth in the chain the remote domain is connected (ICM only)
212 *212 *
@@ -244,12 +244,13 @@ struct tb_xdomain { · 31 unmodified lines
244 u32 local_property_block_len;244 u32 local_property_block_len;
245 struct tb_property_dir *remote_properties;245 struct tb_property_dir *remote_properties;
246 u32 remote_property_block_gen;246 u32 remote_property_block_gen;
247 struct delayed_work get_uuid_work;247 int state;
248 int uuid_retries;248 struct delayed_work state_work;
249 struct delayed_work get_properties_work;249 int state_retries;
250 int properties_retries;
251 struct delayed_work properties_changed_work;250 struct delayed_work properties_changed_work;
252 int properties_changed_retries;251 int properties_changed_retries;
252 bool bonding_possible;
253 u8 target_link_width;
253 u8 link;254 u8 link;
254 u8 depth;255 u8 depth;
255};256};

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t