diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2008-08-16 07:38:11 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2008-08-19 12:47:55 -0400 |
commit | c921a9745705ed62a949192ef9128c60d6c63874 (patch) | |
tree | 4a26e3e65b138c413ea5c0183038b4a25ccc882c /drivers/ieee1394/nodemgr.c | |
parent | 6848408abf1bc18d9a4d5fed3fcca812745ece05 (diff) |
ieee1394: don't drop nodes during bus reset series
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>
Diffstat (limited to 'drivers/ieee1394/nodemgr.c')
-rw-r--r-- | drivers/ieee1394/nodemgr.c | 40 |
1 files changed, 21 insertions, 19 deletions
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 2ebd09a89427..16240a789650 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c | |||
@@ -1574,6 +1574,9 @@ static int node_probe(struct device *dev, void *data) | |||
1574 | struct probe_param *p = data; | 1574 | struct probe_param *p = data; |
1575 | struct node_entry *ne; | 1575 | struct node_entry *ne; |
1576 | 1576 | ||
1577 | if (p->generation != get_hpsb_generation(p->hi->host)) | ||
1578 | return -EAGAIN; | ||
1579 | |||
1577 | ne = container_of(dev, struct node_entry, node_dev); | 1580 | ne = container_of(dev, struct node_entry, node_dev); |
1578 | if (ne->needs_probe == p->probe_now) | 1581 | if (ne->needs_probe == p->probe_now) |
1579 | nodemgr_probe_ne(p->hi, ne, p->generation); | 1582 | nodemgr_probe_ne(p->hi, ne, p->generation); |
@@ -1582,42 +1585,41 @@ static int node_probe(struct device *dev, void *data) | |||
1582 | 1585 | ||
1583 | static void nodemgr_node_probe(struct host_info *hi, int generation) | 1586 | static void nodemgr_node_probe(struct host_info *hi, int generation) |
1584 | { | 1587 | { |
1585 | struct hpsb_host *host = hi->host; | ||
1586 | struct probe_param p; | 1588 | struct probe_param p; |
1587 | 1589 | ||
1588 | p.hi = hi; | 1590 | p.hi = hi; |
1589 | p.generation = generation; | 1591 | p.generation = generation; |
1590 | /* Do some processing of the nodes we've probed. This pulls them | 1592 | /* |
1593 | * Do some processing of the nodes we've probed. This pulls them | ||
1591 | * into the sysfs layer if needed, and can result in processing of | 1594 | * into the sysfs layer if needed, and can result in processing of |
1592 | * unit-directories, or just updating the node and it's | 1595 | * unit-directories, or just updating the node and it's |
1593 | * unit-directories. | 1596 | * unit-directories. |
1594 | * | 1597 | * |
1595 | * Run updates before probes. Usually, updates are time-critical | 1598 | * Run updates before probes. Usually, updates are time-critical |
1596 | * while probes are time-consuming. (Well, those probes need some | 1599 | * while probes are time-consuming. |
1597 | * improvement...) */ | 1600 | * |
1598 | 1601 | * Meanwhile, another bus reset may have happened. In this case we | |
1602 | * skip everything here and let the next bus scan handle it. | ||
1603 | * Otherwise we may prematurely remove nodes which are still there. | ||
1604 | */ | ||
1599 | p.probe_now = false; | 1605 | p.probe_now = false; |
1600 | class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe); | 1606 | if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0) |
1601 | p.probe_now = true; | 1607 | return; |
1602 | class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe); | ||
1603 | 1608 | ||
1604 | /* If we had a bus reset while we were scanning the bus, it is | 1609 | p.probe_now = true; |
1605 | * possible that we did not probe all nodes. In that case, we | 1610 | if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0) |
1606 | * skip the clean up for now, since we could remove nodes that | 1611 | return; |
1607 | * were still on the bus. Another bus scan is pending which will | 1612 | /* |
1608 | * do the clean up eventually. | ||
1609 | * | ||
1610 | * Now let's tell the bus to rescan our devices. This may seem | 1613 | * Now let's tell the bus to rescan our devices. This may seem |
1611 | * like overhead, but the driver-model core will only scan a | 1614 | * like overhead, but the driver-model core will only scan a |
1612 | * device for a driver when either the device is added, or when a | 1615 | * device for a driver when either the device is added, or when a |
1613 | * new driver is added. A bus reset is a good reason to rescan | 1616 | * new driver is added. A bus reset is a good reason to rescan |
1614 | * devices that were there before. For example, an sbp2 device | 1617 | * devices that were there before. For example, an sbp2 device |
1615 | * may become available for login, if the host that held it was | 1618 | * may become available for login, if the host that held it was |
1616 | * just removed. */ | 1619 | * just removed. |
1617 | 1620 | */ | |
1618 | if (generation == get_hpsb_generation(host)) | 1621 | if (bus_rescan_devices(&ieee1394_bus_type) != 0) |
1619 | if (bus_rescan_devices(&ieee1394_bus_type)) | 1622 | HPSB_DEBUG("bus_rescan_devices had an error"); |
1620 | HPSB_DEBUG("bus_rescan_devices had an error"); | ||
1621 | } | 1623 | } |
1622 | 1624 | ||
1623 | static int nodemgr_send_resume_packet(struct hpsb_host *host) | 1625 | static int nodemgr_send_resume_packet(struct hpsb_host *host) |