summaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-topology.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firewire/fw-topology.c')
-rw-r--r--drivers/firewire/fw-topology.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
index 5e204713002d..8dd6703b55cd 100644
--- a/drivers/firewire/fw-topology.c
+++ b/drivers/firewire/fw-topology.c
@@ -355,6 +355,9 @@ report_lost_node(struct fw_card *card,
{
fw_node_event(card, node, FW_NODE_DESTROYED);
fw_node_put(node);
+
+ /* Topology has changed - reset bus manager retry counter */
+ card->bm_retries = 0;
}
static void
@@ -374,6 +377,9 @@ report_found_node(struct fw_card *card,
}
fw_node_event(card, node, FW_NODE_CREATED);
+
+ /* Topology has changed - reset bus manager retry counter */
+ card->bm_retries = 0;
}
void fw_destroy_nodes(struct fw_card *card)
@@ -512,15 +518,19 @@ fw_core_handle_bus_reset(struct fw_card *card,
struct fw_node *local_node;
unsigned long flags;
- spin_lock_irqsave(&card->lock, flags);
-
/*
- * If the new topology has a different self_id_count the topology
- * changed, either nodes were added or removed. In that case we
- * reset the IRM reset counter.
+ * If the selfID buffer is not the immediate successor of the
+ * previously processed one, we cannot reliably compare the
+ * old and new topologies.
*/
- if (card->self_id_count != self_id_count)
+ if (!is_next_generation(generation, card->generation) &&
+ card->local_node != NULL) {
+ fw_notify("skipped bus generations, destroying all nodes\n");
+ fw_destroy_nodes(card);
card->bm_retries = 0;
+ }
+
+ spin_lock_irqsave(&card->lock, flags);
card->node_id = node_id;
/*
@@ -530,7 +540,7 @@ fw_core_handle_bus_reset(struct fw_card *card,
smp_wmb();
card->generation = generation;
card->reset_jiffies = jiffies;
- schedule_delayed_work(&card->work, 0);
+ fw_schedule_bm_work(card, 0);
local_node = build_tree(card, self_ids, self_id_count);