ieee1394: don't drop nodes during bus reset series
authorStefan Richter <stefanr@s5r6.in-berlin.de>
Sat, 16 Aug 2008 11:38:11 +0000 (13:38 +0200)
committerStefan Richter <stefanr@s5r6.in-berlin.de>
Tue, 19 Aug 2008 16:47:55 +0000 (18:47 +0200)
nodemgr_node_probe checked for generation increments too late and
therefore prematurely reported nodes as "suspended".

Fixes http://bugzilla.kernel.org/show_bug.cgi?id=11349.  Reported and
tested by Damien Benoist.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
drivers/ieee1394/nodemgr.c

index 2ebd09a894271306f612b81588c64f16ad8c346d..16240a7896509c024bacf59ff48bd8dd1c227d9d 100644 (file)
@@ -1574,6 +1574,9 @@ static int node_probe(struct device *dev, void *data)
        struct probe_param *p = data;
        struct node_entry *ne;
 
+       if (p->generation != get_hpsb_generation(p->hi->host))
+               return -EAGAIN;
+
        ne = container_of(dev, struct node_entry, node_dev);
        if (ne->needs_probe == p->probe_now)
                nodemgr_probe_ne(p->hi, ne, p->generation);
@@ -1582,42 +1585,41 @@ static int node_probe(struct device *dev, void *data)
 
 static void nodemgr_node_probe(struct host_info *hi, int generation)
 {
-       struct hpsb_host *host = hi->host;
        struct probe_param p;
 
        p.hi = hi;
        p.generation = generation;
-       /* Do some processing of the nodes we've probed. This pulls them
+       /*
+        * Do some processing of the nodes we've probed. This pulls them
         * into the sysfs layer if needed, and can result in processing of
         * unit-directories, or just updating the node and it's
         * unit-directories.
         *
         * Run updates before probes. Usually, updates are time-critical
-        * while probes are time-consuming. (Well, those probes need some
-        * improvement...) */
-
+        * while probes are time-consuming.
+        *
+        * Meanwhile, another bus reset may have happened. In this case we
+        * skip everything here and let the next bus scan handle it.
+        * Otherwise we may prematurely remove nodes which are still there.
+        */
        p.probe_now = false;
-       class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe);
-       p.probe_now = true;
-       class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe);
+       if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
+               return;
 
-       /* If we had a bus reset while we were scanning the bus, it is
-        * possible that we did not probe all nodes.  In that case, we
-        * skip the clean up for now, since we could remove nodes that
-        * were still on the bus.  Another bus scan is pending which will
-        * do the clean up eventually.
-        *
+       p.probe_now = true;
+       if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
+               return;
+       /*
         * Now let's tell the bus to rescan our devices. This may seem
         * like overhead, but the driver-model core will only scan a
         * device for a driver when either the device is added, or when a
         * new driver is added. A bus reset is a good reason to rescan
         * devices that were there before.  For example, an sbp2 device
         * may become available for login, if the host that held it was
-        * just removed.  */
-
-       if (generation == get_hpsb_generation(host))
-               if (bus_rescan_devices(&ieee1394_bus_type))
-                       HPSB_DEBUG("bus_rescan_devices had an error");
+        * just removed.
+        */
+       if (bus_rescan_devices(&ieee1394_bus_type) != 0)
+               HPSB_DEBUG("bus_rescan_devices had an error");
 }
 
 static int nodemgr_send_resume_packet(struct hpsb_host *host)