Commit f022ff7b authored by Mika Westerberg's avatar Mika Westerberg

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=206493Reported-by: default avatarKai-Heng Feng <kai.heng.feng@canonical.com>
Tested-by: default avatarKai-Heng Feng <kai.heng.feng@canonical.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
parent 813050e0
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
*/ */
#include <linux/crc32.h> #include <linux/crc32.h>
#include <linux/delay.h>
#include <linux/property.h> #include <linux/property.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "tb.h" #include "tb.h"
...@@ -389,8 +390,8 @@ static int tb_drom_parse_entries(struct tb_switch *sw) ...@@ -389,8 +390,8 @@ static int tb_drom_parse_entries(struct tb_switch *sw)
struct tb_drom_entry_header *entry = (void *) (sw->drom + pos); struct tb_drom_entry_header *entry = (void *) (sw->drom + pos);
if (pos + 1 == drom_size || pos + entry->len > drom_size if (pos + 1 == drom_size || pos + entry->len > drom_size
|| !entry->len) { || !entry->len) {
tb_sw_warn(sw, "drom buffer overrun, aborting\n"); tb_sw_warn(sw, "DROM buffer overrun\n");
return -EIO; return -EILSEQ;
} }
switch (entry->type) { switch (entry->type) {
...@@ -526,7 +527,8 @@ int tb_drom_read(struct tb_switch *sw) ...@@ -526,7 +527,8 @@ int tb_drom_read(struct tb_switch *sw)
u16 size; u16 size;
u32 crc; u32 crc;
struct tb_drom_header *header; struct tb_drom_header *header;
int res; int res, retries = 1;
if (sw->drom) if (sw->drom)
return 0; return 0;
...@@ -612,7 +614,17 @@ int tb_drom_read(struct tb_switch *sw) ...@@ -612,7 +614,17 @@ int tb_drom_read(struct tb_switch *sw)
tb_sw_warn(sw, "drom device_rom_revision %#x unknown\n", tb_sw_warn(sw, "drom device_rom_revision %#x unknown\n",
header->device_rom_revision); header->device_rom_revision);
return tb_drom_parse_entries(sw); res = tb_drom_parse_entries(sw);
/* If the DROM parsing fails, wait a moment and retry once */
if (res == -EILSEQ && retries--) {
tb_sw_warn(sw, "parsing DROM failed, retrying\n");
msleep(100);
res = tb_drom_read_n(sw, 0, sw->drom, size);
if (!res)
goto parse;
}
return res;
err: err:
kfree(sw->drom); kfree(sw->drom);
sw->drom = NULL; sw->drom = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment