Commit 815f421b authored by Gil Fine's avatar Gil Fine Committed by Mika Westerberg

thunderbolt: debugfs: Handle fail reading block

There are cases when reading block of dwords in single transaction fail,
for several reasons, mostly if HW publish to implement all of the dwords,
while actually it doesn't or if some dwords not accessible for read
for security reasons. We handle these cases by trying to read the block,
dword-by-dword, one dword per transaction, till we get a failure.
Signed-off-by: default avatarGil Fine <gil.fine@intel.com>
Signed-off-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
parent a38fd874
...@@ -251,6 +251,31 @@ static ssize_t counters_write(struct file *file, const char __user *user_buf, ...@@ -251,6 +251,31 @@ static ssize_t counters_write(struct file *file, const char __user *user_buf,
return ret < 0 ? ret : count; return ret < 0 ? ret : count;
} }
static void cap_show_by_dw(struct seq_file *s, struct tb_switch *sw,
struct tb_port *port, unsigned int cap,
unsigned int offset, u8 cap_id, u8 vsec_id,
int dwords)
{
int i, ret;
u32 data;
for (i = 0; i < dwords; i++) {
if (port)
ret = tb_port_read(port, &data, TB_CFG_PORT, cap + offset + i, 1);
else
ret = tb_sw_read(sw, &data, TB_CFG_SWITCH, cap + offset + i, 1);
if (ret) {
seq_printf(s, "0x%04x <not accessible>\n", cap + offset);
if (dwords - i > 1)
seq_printf(s, "0x%04x ...\n", cap + offset + 1);
return;
}
seq_printf(s, "0x%04x %4d 0x%02x 0x%02x 0x%08x\n", cap + offset + i,
offset + i, cap_id, vsec_id, data);
}
}
static void cap_show(struct seq_file *s, struct tb_switch *sw, static void cap_show(struct seq_file *s, struct tb_switch *sw,
struct tb_port *port, unsigned int cap, u8 cap_id, struct tb_port *port, unsigned int cap, u8 cap_id,
u8 vsec_id, int length) u8 vsec_id, int length)
...@@ -267,10 +292,7 @@ static void cap_show(struct seq_file *s, struct tb_switch *sw, ...@@ -267,10 +292,7 @@ static void cap_show(struct seq_file *s, struct tb_switch *sw,
else else
ret = tb_sw_read(sw, data, TB_CFG_SWITCH, cap + offset, dwords); ret = tb_sw_read(sw, data, TB_CFG_SWITCH, cap + offset, dwords);
if (ret) { if (ret) {
seq_printf(s, "0x%04x <not accessible>\n", cap_show_by_dw(s, sw, port, cap, offset, cap_id, vsec_id, dwords);
cap + offset);
if (dwords > 1)
seq_printf(s, "0x%04x ...\n", cap + offset + 1);
return; return;
} }
...@@ -341,15 +363,6 @@ static void port_cap_show(struct tb_port *port, struct seq_file *s, ...@@ -341,15 +363,6 @@ static void port_cap_show(struct tb_port *port, struct seq_file *s,
} else { } else {
length = header.extended_short.length; length = header.extended_short.length;
vsec_id = header.extended_short.vsec_id; vsec_id = header.extended_short.vsec_id;
/*
* Ice Lake and Tiger Lake do not implement the
* full length of the capability, only first 32
* dwords so hard-code it here.
*/
if (!vsec_id &&
(tb_switch_is_ice_lake(port->sw) ||
tb_switch_is_tiger_lake(port->sw)))
length = 32;
} }
break; break;
......
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