summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGil Fine <gil.fine@intel.com>2021-02-16 15:04:26 +0200
committerMika Westerberg <mika.westerberg@linux.intel.com>2021-03-08 13:41:40 +0300
commit815f421b6f6d1aedc3ebc73bf46887e02e4349fd (patch)
tree9f10590e393d54808beddf4925352ef4ef20e8f3
parenta38fd8748464831584a19438cbb3082b5a2dab15 (diff)
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: Gil Fine <gil.fine@intel.com> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
-rw-r--r--drivers/thunderbolt/debugfs.c39
1 files changed, 26 insertions, 13 deletions
diff --git a/drivers/thunderbolt/debugfs.c b/drivers/thunderbolt/debugfs.c
index 9541d7409ab1..201036507cb8 100644
--- a/drivers/thunderbolt/debugfs.c
+++ b/drivers/thunderbolt/debugfs.c
@@ -251,6 +251,31 @@ out:
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,
struct tb_port *port, unsigned int cap, u8 cap_id,
u8 vsec_id, int length)
@@ -267,10 +292,7 @@ static void cap_show(struct seq_file *s, struct tb_switch *sw,
else
ret = tb_sw_read(sw, data, TB_CFG_SWITCH, cap + offset, dwords);
if (ret) {
- seq_printf(s, "0x%04x <not accessible>\n",
- cap + offset);
- if (dwords > 1)
- seq_printf(s, "0x%04x ...\n", cap + offset + 1);
+ cap_show_by_dw(s, sw, port, cap, offset, cap_id, vsec_id, dwords);
return;
}
@@ -341,15 +363,6 @@ static void port_cap_show(struct tb_port *port, struct seq_file *s,
} else {
length = header.extended_short.length;
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;