summaryrefslogtreecommitdiffstats
path: root/drivers/thunderbolt
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2019-01-08 19:08:06 +0200
committerMika Westerberg <mika.westerberg@linux.intel.com>2019-04-18 11:18:51 +0300
commitffd003b2f8cba8dde0f7259e2207d63f75691096 (patch)
treef6c046373e83597a1f3e8a48e629afa8998d5996 /drivers/thunderbolt
parent8b0110d9d10d211fc8a0e2cbb2db4533af30d36e (diff)
downloadlinux-ffd003b2f8cba8dde0f7259e2207d63f75691096.tar.bz2
thunderbolt: Add dummy read after port capability list walk on Light Ridge
Light Ridge has an issue where reading the next capability pointer location in port config space the read data is not cleared. It is fine to read capabilities each after another so only thing we need to do is to make sure we issue dummy read after tb_port_find_cap() is finished to avoid the issue in next read. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/thunderbolt')
-rw-r--r--drivers/thunderbolt/cap.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/thunderbolt/cap.c b/drivers/thunderbolt/cap.c
index a58585b4e6d9..8bf8e031f0bc 100644
--- a/drivers/thunderbolt/cap.c
+++ b/drivers/thunderbolt/cap.c
@@ -52,6 +52,21 @@ static int tb_port_enable_tmu(struct tb_port *port, bool enable)
return tb_sw_write(sw, &value, TB_CFG_SWITCH, offset, 1);
}
+static void tb_port_dummy_read(struct tb_port *port)
+{
+ /*
+ * When reading from next capability pointer location in port
+ * config space the read data is not cleared on LR. To avoid
+ * reading stale data on next read perform one dummy read after
+ * port capabilities are walked.
+ */
+ if (tb_switch_is_lr(port->sw)) {
+ u32 dummy;
+
+ tb_port_read(port, &dummy, TB_CFG_PORT, 0, 1);
+ }
+}
+
static int __tb_port_find_cap(struct tb_port *port, enum tb_port_cap cap)
{
u32 offset = 1;
@@ -92,6 +107,7 @@ int tb_port_find_cap(struct tb_port *port, enum tb_port_cap cap)
ret = __tb_port_find_cap(port, cap);
+ tb_port_dummy_read(port);
tb_port_enable_tmu(port, false);
return ret;