firewire: core: use long bus reset on gap count error
[linux-2.6-microblaze.git] / drivers / firewire / core-card.c
index 6ac5ff2..401a77e 100644 (file)
@@ -429,7 +429,23 @@ static void bm_work(struct work_struct *work)
         */
        card->bm_generation = generation;
 
-       if (root_device == NULL) {
+       if (card->gap_count == 0) {
+               /*
+                * If self IDs have inconsistent gap counts, do a
+                * bus reset ASAP. The config rom read might never
+                * complete, so don't wait for it. However, still
+                * send a PHY configuration packet prior to the
+                * bus reset. The PHY configuration packet might
+                * fail, but 1394-2008 8.4.5.2 explicitly permits
+                * it in this case, so it should be safe to try.
+                */
+               new_root_id = local_id;
+               /*
+                * We must always send a bus reset if the gap count
+                * is inconsistent, so bypass the 5-reset limit.
+                */
+               card->bm_retries = 0;
+       } else if (root_device == NULL) {
                /*
                 * Either link_on is false, or we failed to read the
                 * config rom.  In either case, pick another root.
@@ -484,7 +500,19 @@ static void bm_work(struct work_struct *work)
                fw_notice(card, "phy config: new root=%x, gap_count=%d\n",
                          new_root_id, gap_count);
                fw_send_phy_config(card, new_root_id, generation, gap_count);
-               reset_bus(card, true);
+               /*
+                * Where possible, use a short bus reset to minimize
+                * disruption to isochronous transfers. But in the event
+                * of a gap count inconsistency, use a long bus reset.
+                *
+                * As noted in 1394a 8.4.6.2, nodes on a mixed 1394/1394a bus
+                * may set different gap counts after a bus reset. On a mixed
+                * 1394/1394a bus, a short bus reset can get doubled. Some
+                * nodes may treat the double reset as one bus reset and others
+                * may treat it as two, causing a gap count inconsistency
+                * again. Using a long bus reset prevents this.
+                */
+               reset_bus(card, card->gap_count != 0);
                /* Will allocate broadcast channel after the reset. */
                goto out;
        }