patch-2.4.17 linux/drivers/ieee1394/nodemgr.c
Next file: linux/drivers/ieee1394/ohci1394.c
Previous file: linux/drivers/ieee1394/ieee1394_syms.c
Back to the patch index
Back to the overall index
- Lines: 234
- Date:
Fri Dec 21 16:40:32 2001
- Orig file:
linux-2.4.16/drivers/ieee1394/nodemgr.c
- Orig date:
Wed Oct 17 21:19:20 2001
diff -Naur -X /home/marcelo/lib/dontdiff linux-2.4.16/drivers/ieee1394/nodemgr.c linux/drivers/ieee1394/nodemgr.c
@@ -359,7 +359,7 @@
kfree(buf);
kfree(envp);
if (value != 0)
- HPSB_DEBUG("NodeMgr: hotplug policy returned 0x%x", value);
+ HPSB_DEBUG("NodeMgr: hotplug policy returned %d", value);
}
#else
@@ -369,9 +369,8 @@
{
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
HPSB_DEBUG("NodeMgr: nodemgr_call_policy(): hotplug not enabled");
-#else
- return;
#endif
+ return;
}
#endif /* CONFIG_HOTPLUG */
@@ -582,13 +581,13 @@
struct hpsb_host *host, nodeid_t nodeid)
{
struct list_head *lh;
+ struct unit_directory *ud;
- if (ne->nodeid != nodeid)
+ if (ne->nodeid != nodeid) {
HPSB_DEBUG("Node " NODE_BUS_FMT " changed to " NODE_BUS_FMT,
NODE_BUS_ARGS(ne->nodeid), NODE_BUS_ARGS(nodeid));
-
- ne->host = host;
- ne->nodeid = nodeid;
+ ne->nodeid = nodeid;
+ }
if (ne->busopt.generation != ((busoptions >> 4) & 0xf))
nodemgr_process_config_rom (ne, busoptions);
@@ -597,8 +596,6 @@
atomic_set(&ne->generation, get_hpsb_generation(ne->host));
list_for_each (lh, &ne->unit_directories) {
- struct unit_directory *ud;
-
ud = list_entry (lh, struct unit_directory, node_list);
if (ud->driver != NULL && ud->driver->update != NULL)
ud->driver->update(ud);
@@ -679,57 +676,76 @@
return;
}
+/* Used to schedule each nodes config rom probe */
+struct node_probe_task {
+ nodeid_t nodeid;
+ struct hpsb_host *host;
+ atomic_t *count;
+ struct tq_struct task;
+};
+
/* This is where we probe the nodes for their information and provided
* features. */
-static void nodemgr_node_probe(void *data)
+static void nodemgr_node_probe_one(void *__npt)
{
- struct hpsb_host *host = (struct hpsb_host *)data;
- struct selfid *sid = (struct selfid *)host->topology_map;
- struct list_head *lh, *next;
+ struct node_probe_task *npt = (struct node_probe_task *)__npt;
struct node_entry *ne;
- int nodecount = host->node_count;
- nodeid_t nodeid = LOCAL_BUS;
quadlet_t buffer[5];
octlet_t guid;
- unsigned long flags;
/* We need to detect when the ConfigROM's generation has changed,
* so we only update the node's info when it needs to be. */
- for (; nodecount; nodecount--, nodeid++, sid++) {
- /* Skip extended, and non-active node's */
- while (sid->extended)
- sid++;
- if (!sid->link_active)
- continue;
- if (read_businfo_block (host, nodeid, buffer, sizeof(buffer) >> 2))
- continue;
+ if (read_businfo_block (npt->host, npt->nodeid, buffer, sizeof(buffer) >> 2))
+ goto probe_complete;
- if (buffer[1] != IEEE1394_BUSID_MAGIC) {
- /* This isn't a 1394 device */
- HPSB_ERR("Node " NODE_BUS_FMT " isn't an IEEE 1394 device",
- NODE_BUS_ARGS(nodeid));
- continue;
- }
+ if (buffer[1] != IEEE1394_BUSID_MAGIC) {
+ /* This isn't a 1394 device */
+ HPSB_ERR("Node " NODE_BUS_FMT " isn't an IEEE 1394 device",
+ NODE_BUS_ARGS(npt->nodeid));
+ goto probe_complete;
+ }
+
+ guid = ((u64)buffer[3] << 32) | buffer[4];
+ ne = hpsb_guid_get_entry(guid);
+
+ if (!ne)
+ nodemgr_create_node(guid, buffer[2], npt->host, npt->nodeid);
+ else
+ nodemgr_update_node(ne, buffer[2], npt->host, npt->nodeid);
+
+probe_complete:
+ atomic_dec(npt->count);
+
+ kfree(npt);
+
+ return;
+}
- guid = ((u64)buffer[3] << 32) | buffer[4];
- ne = hpsb_guid_get_entry(guid);
+static void nodemgr_node_probe_cleanup(void *__npt)
+{
+ struct node_probe_task *npt = (struct node_probe_task *)__npt;
+ unsigned long flags;
+ struct list_head *lh, *next;
+ struct node_entry *ne;
+
+ /* If things aren't done yet, reschedule ourselves. */
+ if (atomic_read(npt->count)) {
+ schedule_task(&npt->task);
+ return;
+ }
- if (!ne)
- nodemgr_create_node(guid, buffer[2], host, nodeid);
- else
- nodemgr_update_node(ne, buffer[2], host, nodeid);
- }
+ kfree(npt->count);
/* Now check to see if we have any nodes that aren't referenced
* any longer. */
- write_lock_irqsave(&node_lock, flags);
+ write_lock_irqsave(&node_lock, flags);
for (lh = node_list.next; lh != &node_list; lh = next) {
ne = list_entry(lh, struct node_entry, list);
next = lh->next;
/* Only checking this host */
- if (ne->host != host)
+ if (ne->host != npt->host)
continue;
/* If the generation didn't get updated, then either the
@@ -741,9 +757,70 @@
}
write_unlock_irqrestore(&node_lock, flags);
+ kfree(npt);
+
return;
}
+static void nodemgr_node_probe(void *__host)
+{
+ struct hpsb_host *host = (struct hpsb_host *)__host;
+ int nodecount = host->node_count;
+ struct selfid *sid = (struct selfid *)host->topology_map;
+ nodeid_t nodeid = LOCAL_BUS;
+ struct node_probe_task *npt;
+ atomic_t *count;
+
+ count = kmalloc(sizeof (*count), GFP_KERNEL);
+
+ if (count == NULL) {
+ HPSB_ERR ("NodeMgr: out of memory in nodemgr_node_probe");
+ return;
+ }
+
+ atomic_set(count, 0);
+
+ for (; nodecount; nodecount--, nodeid++, sid++) {
+ while (sid->extended)
+ sid++;
+ if (!sid->link_active || nodeid == host->node_id)
+ continue;
+
+ npt = kmalloc(sizeof (*npt), GFP_KERNEL);
+
+ if (npt == NULL) {
+ HPSB_ERR ("NodeMgr: out of memory in nodemgr_node_probe");
+ break;
+ }
+
+ INIT_TQUEUE(&npt->task, nodemgr_node_probe_one, npt);
+ npt->host = host;
+ npt->nodeid = nodeid;
+ npt->count = count;
+
+ atomic_inc(count);
+
+ schedule_task(&npt->task);
+ }
+
+ /* Now schedule a task to clean things up after the node probes
+ * are done. */
+ npt = kmalloc (sizeof (*npt), GFP_KERNEL);
+
+ if (npt == NULL) {
+ HPSB_ERR ("NodeMgr: out of memory in nodemgr_node_probe");
+ return;
+ }
+
+ INIT_TQUEUE(&npt->task, nodemgr_node_probe_cleanup, npt);
+ npt->host = host;
+ npt->nodeid = 0;
+ npt->count = count;
+
+ schedule_task(&npt->task);
+
+ return;
+}
struct node_entry *hpsb_guid_get_entry(u64 guid)
{
@@ -864,7 +941,7 @@
write_unlock_irqrestore(&node_lock, flags);
spin_lock_irqsave (&host_info_lock, flags);
- list_for_each(lh, &host_info_list) {
+ list_for_each_safe(lh, next, &host_info_list) {
struct host_info *hi = list_entry(lh, struct host_info, list);
if (hi->host == host) {
list_del(&hi->list);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)