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>
This commit is contained in:
Andreas Noever 2014-08-26 17:42:21 +02:00 committed by Greg Kroah-Hartman
parent 8e8248b136
commit 72ad366f68
1 changed files with 20 additions and 1 deletions

View File

@ -150,7 +150,26 @@ int tb_path_activate(struct tb_path *path)
/* Activate hops. */
for (i = path->path_length - 1; i >= 0; i--) {
struct tb_regs_hop hop;
struct tb_regs_hop hop = { 0 };
/*
* We do (currently) not tear down paths setup by the firmeware.
* If a firmware device is unplugged and plugged in again then
* it can happen that we reuse some of the hops from the (now
* defunct) firmeware path. This causes the hotplug operation to
* fail (the pci device does not show up). Clearing the hop
* before overwriting it fixes the problem.
*
* Should be removed once we discover and tear down firmeware
* paths.
*/
res = tb_port_write(path->hops[i].in_port, &hop, TB_CFG_HOPS,
2 * path->hops[i].in_hop_index, 2);
if (res) {
__tb_path_deactivate_hops(path, i);
__tb_path_deallocate_nfc(path, 0);
goto err;
}
/* dword 0 */
hop.next_hop = path->hops[i].next_hop_index;