[Linux1394-cvslog] rev 839 - branches/linux-2.4
Brought to you by:
aeb,
bencollins
|
From: SVN U. <ben...@li...> - 2003-03-14 21:50:00
|
Author: bencollins
Date: 2003-03-14 16:49:00 -0500 (Fri, 14 Mar 2003)
New Revision: 839
Modified:
branches/linux-2.4/nodemgr.c
Log:
Handle back-to-back resets better, and fix what appears to be a race in
the generation check. Also handle forced IRM reset better.
Patch from Jim Radford.
Modified: branches/linux-2.4/nodemgr.c
==============================================================================
--- branches/linux-2.4/nodemgr.c (original)
+++ branches/linux-2.4/nodemgr.c 2003-03-14 16:49:01.000000000 -0500
@@ -1124,26 +1124,11 @@
return;
}
-static void nodemgr_node_probe(struct hpsb_host *host)
+static void nodemgr_node_probe(struct hpsb_host *host, int generation)
{
int count;
struct selfid *sid = (struct selfid *)host->topology_map;
nodeid_t nodeid = LOCAL_BUS;
- unsigned int generation;
-
- /* Pause for 1/4 second, to make sure things settle down. If
- * schedule_timeout returns non-zero, it means we caught a signal
- * and need to return. */
- set_current_state(TASK_INTERRUPTIBLE);
- if (schedule_timeout (HZ/4))
- return;
-
- /* Now get the generation in which the node ID's we collect
- * are valid. During the bus scan we will use this generation
- * for the read transactions, so that if another reset occurs
- * during the scan the transactions will fail instead of
- * returning bogus data. */
- generation = get_hpsb_generation(host);
/* Scan each node on the bus */
for (count = host->selfid_count; count; count--, sid++) {
@@ -1158,15 +1143,6 @@
nodemgr_node_probe_one(host, nodeid++, generation);
}
- /* 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. The bus reset increased
- * hi->reset_sem, so there's a bus scan pending which will do
- * the clean up eventually. */
- if (generation == get_hpsb_generation(host))
- nodemgr_node_probe_cleanup(host, generation);
-
return;
}
@@ -1229,6 +1205,27 @@
* happens when we get a bus reset. */
while (!down_interruptible(&hi->reset_sem) &&
!down_interruptible(&nodemgr_serialize)) {
+ unsigned int generation;
+
+ /* Many resets can happen while we are waiting below.
+ * Make sure we respond only to the most recent one. */
+ do {
+ /* Pause for 1/4 second, to make sure things settle down. If
+ * schedule_timeout returns non-zero, it means we caught a signal
+ * and that we should exit. */
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (schedule_timeout (HZ/4)) {
+ up(&nodemgr_serialize);
+ goto caught_signal;
+ }
+
+ /* Now get the generation in which the node ID's we collect
+ * are valid. During the bus scan we will use this generation
+ * for the read transactions, so that if another reset occurs
+ * during the scan the transactions will fail instead of
+ * returning bogus data. */
+ generation = get_hpsb_generation(hi->host);
+ } while(!down_trylock(&hi->reset_sem));
if (!nodemgr_check_root_capability(hi->host)) {
/* Do nothing, we are resetting */
@@ -1236,11 +1233,23 @@
continue;
}
- nodemgr_node_probe(hi->host);
+ nodemgr_node_probe(hi->host, generation);
+
+ /* 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. The bus reset increased
+ * hi->reset_sem, so there's a bus scan pending which will do
+ * the clean up eventually. */
+ if (generation == get_hpsb_generation(hi->host))
+ nodemgr_node_probe_cleanup(hi->host, generation);
+
nodemgr_do_irm_duties(hi->host);
up(&nodemgr_serialize);
}
+
+ caught_signal:
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
HPSB_DEBUG ("NodeMgr: Exiting thread for %s", hi->host->driver->name);
#endif
|