[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 |