aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Noever <andreas.noever@gmail.com>2014-08-26 11:42:21 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-08-26 17:54:48 -0400
commit72ad366f687d45f30a82d8b6e70ce757b21b5aab (patch)
tree76d191e82bc3cadf548bc9338214fd7274b95345
parent8e8248b1369c97c7bb6f8bcaee1f05deeabab8ef (diff)
thunderbolt: Clear hops before overwriting
Zero hops in tb_path_activate before writing a new path. This fixes the following scenario: - Boot with a coldplugged device - Unplug device - Plug device back in - PCI hotplug fails The hotplug operation fails because our new path matches the (now defunct) path which was setup by the firmware for the coldplugged device. By writing zeros before writing our path configuration we can force thunderbolt to retrain the path. Signed-off-by: Andreas Noever <andreas.noever@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/thunderbolt/path.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/drivers/thunderbolt/path.c b/drivers/thunderbolt/path.c
index 8fcf8a7b6c22..9562cd026dc0 100644
--- a/drivers/thunderbolt/path.c
+++ b/drivers/thunderbolt/path.c
@@ -150,7 +150,26 @@ int tb_path_activate(struct tb_path *path)
150 150
151 /* Activate hops. */ 151 /* Activate hops. */
152 for (i = path->path_length - 1; i >= 0; i--) { 152 for (i = path->path_length - 1; i >= 0; i--) {
153 struct tb_regs_hop hop; 153 struct tb_regs_hop hop = { 0 };
154
155 /*
156 * We do (currently) not tear down paths setup by the firmeware.
157 * If a firmware device is unplugged and plugged in again then
158 * it can happen that we reuse some of the hops from the (now
159 * defunct) firmeware path. This causes the hotplug operation to
160 * fail (the pci device does not show up). Clearing the hop
161 * before overwriting it fixes the problem.
162 *
163 * Should be removed once we discover and tear down firmeware
164 * paths.
165 */
166 res = tb_port_write(path->hops[i].in_port, &hop, TB_CFG_HOPS,
167 2 * path->hops[i].in_hop_index, 2);
168 if (res) {
169 __tb_path_deactivate_hops(path, i);
170 __tb_path_deallocate_nfc(path, 0);
171 goto err;
172 }
154 173
155 /* dword 0 */ 174 /* dword 0 */
156 hop.next_hop = path->hops[i].next_hop_index; 175 hop.next_hop = path->hops[i].next_hop_index;