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

thunderbolt: Retry DROM read once if parsing fails

Kai-Heng reported that sometimes DROM parsing of ASUS PA27AC Thunderbolt 3
monitor fails. This makes the driver to fail to add the device so only
DisplayPort tunneling is functional.

It is not clear what exactly happens but waiting for 100 ms and retrying
the read seems to work this around so we do that here.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=206493
Reported-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Cc: stable@vger.kernel.org
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>

+16 -4
+16 -4
drivers/thunderbolt/eeprom.c
··· 7 7 */ 8 8 9 9 #include <linux/crc32.h> 10 + #include <linux/delay.h> 10 11 #include <linux/property.h> 11 12 #include <linux/slab.h> 12 13 #include "tb.h" ··· 390 389 struct tb_drom_entry_header *entry = (void *) (sw->drom + pos); 391 390 if (pos + 1 == drom_size || pos + entry->len > drom_size 392 391 || !entry->len) { 393 - tb_sw_warn(sw, "drom buffer overrun, aborting\n"); 394 - return -EIO; 392 + tb_sw_warn(sw, "DROM buffer overrun\n"); 393 + return -EILSEQ; 395 394 } 396 395 397 396 switch (entry->type) { ··· 527 526 u16 size; 528 527 u32 crc; 529 528 struct tb_drom_header *header; 530 - int res; 529 + int res, retries = 1; 530 + 531 531 if (sw->drom) 532 532 return 0; 533 533 ··· 614 612 tb_sw_warn(sw, "drom device_rom_revision %#x unknown\n", 615 613 header->device_rom_revision); 616 614 617 - return tb_drom_parse_entries(sw); 615 + res = tb_drom_parse_entries(sw); 616 + /* If the DROM parsing fails, wait a moment and retry once */ 617 + if (res == -EILSEQ && retries--) { 618 + tb_sw_warn(sw, "parsing DROM failed, retrying\n"); 619 + msleep(100); 620 + res = tb_drom_read_n(sw, 0, sw->drom, size); 621 + if (!res) 622 + goto parse; 623 + } 624 + 625 + return res; 618 626 err: 619 627 kfree(sw->drom); 620 628 sw->drom = NULL;