Skip to content

Commit 582620d

Browse files
committed
thunderbolt: Workaround an IOMMU fault on certain systems with Intel Maple Ridge
On some systems the IOMMU blocks the first couple of driver ready messages to the connection manager firmware as can be seen in below excerpts: thunderbolt 0000:06:00.0: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x0010 address=0xbb0e3400 flags=0x0020] or DMAR: DRHD: handling fault status reg 2 DMAR: [DMA Write] Request device [04:00.0] PASID ffffffff fault addr 6997400 [fault reason 05] PTE Write access is not set The reason is unknown and hard to debug because we were not able to reproduce this locally. This only happens on certain systems with Intel Maple Ridge Thunderbolt controller. If there is a device connected when the driver is loaded the issue does not happen either. Only when there is nothing connected (so typically when the system is booted up). We can work this around by sending the driver ready several times. After a couple of retries the message goes through and the controller works just fine. For this reason make the number of retries a parameter for icm_request() and then for Maple Ridge (and Titan Ridge as they us the same function but this should not matter) increase number of retries while shortening the timeout accordingly. Reported-by: Werner Sembach <wse@tuxedocomputers.com> Reported-by: Konrad J Hambrick <kjhambrick@gmail.com> Reported-by: Calvin Walton <calvin.walton@kepstin.ca> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=214259 Cc: stable@vger.kernel.org Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
1 parent 0bb80ec commit 582620d

File tree

1 file changed

+20
-20
lines changed

1 file changed

+20
-20
lines changed

drivers/thunderbolt/icm.c

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#define PHY_PORT_CS1_LINK_STATE_SHIFT 26
4242

4343
#define ICM_TIMEOUT 5000 /* ms */
44+
#define ICM_RETRIES 3
4445
#define ICM_APPROVE_TIMEOUT 10000 /* ms */
4546
#define ICM_MAX_LINK 4
4647

@@ -296,10 +297,9 @@ static bool icm_copy(struct tb_cfg_request *req, const struct ctl_pkg *pkg)
296297

297298
static int icm_request(struct tb *tb, const void *request, size_t request_size,
298299
void *response, size_t response_size, size_t npackets,
299-
unsigned int timeout_msec)
300+
int retries, unsigned int timeout_msec)
300301
{
301302
struct icm *icm = tb_priv(tb);
302-
int retries = 3;
303303

304304
do {
305305
struct tb_cfg_request *req;
@@ -410,7 +410,7 @@ static int icm_fr_get_route(struct tb *tb, u8 link, u8 depth, u64 *route)
410410
return -ENOMEM;
411411

412412
ret = icm_request(tb, &request, sizeof(request), switches,
413-
sizeof(*switches), npackets, ICM_TIMEOUT);
413+
sizeof(*switches), npackets, ICM_RETRIES, ICM_TIMEOUT);
414414
if (ret)
415415
goto err_free;
416416

@@ -463,7 +463,7 @@ icm_fr_driver_ready(struct tb *tb, enum tb_security_level *security_level,
463463

464464
memset(&reply, 0, sizeof(reply));
465465
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
466-
1, ICM_TIMEOUT);
466+
1, ICM_RETRIES, ICM_TIMEOUT);
467467
if (ret)
468468
return ret;
469469

@@ -488,7 +488,7 @@ static int icm_fr_approve_switch(struct tb *tb, struct tb_switch *sw)
488488
memset(&reply, 0, sizeof(reply));
489489
/* Use larger timeout as establishing tunnels can take some time */
490490
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
491-
1, ICM_APPROVE_TIMEOUT);
491+
1, ICM_RETRIES, ICM_APPROVE_TIMEOUT);
492492
if (ret)
493493
return ret;
494494

@@ -515,7 +515,7 @@ static int icm_fr_add_switch_key(struct tb *tb, struct tb_switch *sw)
515515

516516
memset(&reply, 0, sizeof(reply));
517517
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
518-
1, ICM_TIMEOUT);
518+
1, ICM_RETRIES, ICM_TIMEOUT);
519519
if (ret)
520520
return ret;
521521

@@ -543,7 +543,7 @@ static int icm_fr_challenge_switch_key(struct tb *tb, struct tb_switch *sw,
543543

544544
memset(&reply, 0, sizeof(reply));
545545
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
546-
1, ICM_TIMEOUT);
546+
1, ICM_RETRIES, ICM_TIMEOUT);
547547
if (ret)
548548
return ret;
549549

@@ -577,7 +577,7 @@ static int icm_fr_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd,
577577

578578
memset(&reply, 0, sizeof(reply));
579579
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
580-
1, ICM_TIMEOUT);
580+
1, ICM_RETRIES, ICM_TIMEOUT);
581581
if (ret)
582582
return ret;
583583

@@ -1020,7 +1020,7 @@ icm_tr_driver_ready(struct tb *tb, enum tb_security_level *security_level,
10201020

10211021
memset(&reply, 0, sizeof(reply));
10221022
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1023-
1, 20000);
1023+
1, 10, 2000);
10241024
if (ret)
10251025
return ret;
10261026

@@ -1053,7 +1053,7 @@ static int icm_tr_approve_switch(struct tb *tb, struct tb_switch *sw)
10531053

10541054
memset(&reply, 0, sizeof(reply));
10551055
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1056-
1, ICM_APPROVE_TIMEOUT);
1056+
1, ICM_RETRIES, ICM_APPROVE_TIMEOUT);
10571057
if (ret)
10581058
return ret;
10591059

@@ -1081,7 +1081,7 @@ static int icm_tr_add_switch_key(struct tb *tb, struct tb_switch *sw)
10811081

10821082
memset(&reply, 0, sizeof(reply));
10831083
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1084-
1, ICM_TIMEOUT);
1084+
1, ICM_RETRIES, ICM_TIMEOUT);
10851085
if (ret)
10861086
return ret;
10871087

@@ -1110,7 +1110,7 @@ static int icm_tr_challenge_switch_key(struct tb *tb, struct tb_switch *sw,
11101110

11111111
memset(&reply, 0, sizeof(reply));
11121112
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1113-
1, ICM_TIMEOUT);
1113+
1, ICM_RETRIES, ICM_TIMEOUT);
11141114
if (ret)
11151115
return ret;
11161116

@@ -1144,7 +1144,7 @@ static int icm_tr_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd,
11441144

11451145
memset(&reply, 0, sizeof(reply));
11461146
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1147-
1, ICM_TIMEOUT);
1147+
1, ICM_RETRIES, ICM_TIMEOUT);
11481148
if (ret)
11491149
return ret;
11501150

@@ -1170,7 +1170,7 @@ static int icm_tr_xdomain_tear_down(struct tb *tb, struct tb_xdomain *xd,
11701170

11711171
memset(&reply, 0, sizeof(reply));
11721172
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1173-
1, ICM_TIMEOUT);
1173+
1, ICM_RETRIES, ICM_TIMEOUT);
11741174
if (ret)
11751175
return ret;
11761176

@@ -1496,7 +1496,7 @@ icm_ar_driver_ready(struct tb *tb, enum tb_security_level *security_level,
14961496

14971497
memset(&reply, 0, sizeof(reply));
14981498
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1499-
1, ICM_TIMEOUT);
1499+
1, ICM_RETRIES, ICM_TIMEOUT);
15001500
if (ret)
15011501
return ret;
15021502

@@ -1522,7 +1522,7 @@ static int icm_ar_get_route(struct tb *tb, u8 link, u8 depth, u64 *route)
15221522

15231523
memset(&reply, 0, sizeof(reply));
15241524
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1525-
1, ICM_TIMEOUT);
1525+
1, ICM_RETRIES, ICM_TIMEOUT);
15261526
if (ret)
15271527
return ret;
15281528

@@ -1543,7 +1543,7 @@ static int icm_ar_get_boot_acl(struct tb *tb, uuid_t *uuids, size_t nuuids)
15431543

15441544
memset(&reply, 0, sizeof(reply));
15451545
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1546-
1, ICM_TIMEOUT);
1546+
1, ICM_RETRIES, ICM_TIMEOUT);
15471547
if (ret)
15481548
return ret;
15491549

@@ -1604,7 +1604,7 @@ static int icm_ar_set_boot_acl(struct tb *tb, const uuid_t *uuids,
16041604

16051605
memset(&reply, 0, sizeof(reply));
16061606
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1607-
1, ICM_TIMEOUT);
1607+
1, ICM_RETRIES, ICM_TIMEOUT);
16081608
if (ret)
16091609
return ret;
16101610

@@ -1626,7 +1626,7 @@ icm_icl_driver_ready(struct tb *tb, enum tb_security_level *security_level,
16261626

16271627
memset(&reply, 0, sizeof(reply));
16281628
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
1629-
1, 20000);
1629+
1, ICM_RETRIES, 20000);
16301630
if (ret)
16311631
return ret;
16321632

@@ -2298,7 +2298,7 @@ static int icm_usb4_switch_op(struct tb_switch *sw, u16 opcode, u32 *metadata,
22982298

22992299
memset(&reply, 0, sizeof(reply));
23002300
ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply),
2301-
1, ICM_TIMEOUT);
2301+
1, ICM_RETRIES, ICM_TIMEOUT);
23022302
if (ret)
23032303
return ret;
23042304

0 commit comments

Comments
 (0)