diff options
Diffstat (limited to 'drivers/ieee1394/nodemgr.c')
-rw-r--r-- | drivers/ieee1394/nodemgr.c | 227 |
1 files changed, 93 insertions, 134 deletions
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index d541b508a159..3e7974c57443 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c | |||
@@ -12,26 +12,23 @@ | |||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/list.h> | 13 | #include <linux/list.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/smp_lock.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/kmod.h> | ||
18 | #include <linux/completion.h> | ||
19 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
20 | #include <linux/pci.h> | 16 | #include <linux/kthread.h> |
21 | #include <linux/moduleparam.h> | 17 | #include <linux/moduleparam.h> |
22 | #include <asm/atomic.h> | 18 | #include <asm/atomic.h> |
23 | 19 | ||
24 | #include "ieee1394_types.h" | 20 | #include "csr.h" |
21 | #include "highlevel.h" | ||
22 | #include "hosts.h" | ||
25 | #include "ieee1394.h" | 23 | #include "ieee1394.h" |
26 | #include "ieee1394_core.h" | 24 | #include "ieee1394_core.h" |
27 | #include "hosts.h" | 25 | #include "ieee1394_hotplug.h" |
26 | #include "ieee1394_types.h" | ||
28 | #include "ieee1394_transactions.h" | 27 | #include "ieee1394_transactions.h" |
29 | #include "highlevel.h" | ||
30 | #include "csr.h" | ||
31 | #include "nodemgr.h" | 28 | #include "nodemgr.h" |
32 | 29 | ||
33 | static int ignore_drivers; | 30 | static int ignore_drivers; |
34 | module_param(ignore_drivers, int, 0444); | 31 | module_param(ignore_drivers, int, S_IRUGO | S_IWUSR); |
35 | MODULE_PARM_DESC(ignore_drivers, "Disable automatic probing for drivers."); | 32 | MODULE_PARM_DESC(ignore_drivers, "Disable automatic probing for drivers."); |
36 | 33 | ||
37 | struct nodemgr_csr_info { | 34 | struct nodemgr_csr_info { |
@@ -71,7 +68,7 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr, | |||
71 | u8 i, *speed, old_speed, good_speed; | 68 | u8 i, *speed, old_speed, good_speed; |
72 | int ret; | 69 | int ret; |
73 | 70 | ||
74 | speed = ci->host->speed + NODEID_TO_NODE(ci->nodeid); | 71 | speed = &(ci->host->speed[NODEID_TO_NODE(ci->nodeid)]); |
75 | old_speed = *speed; | 72 | old_speed = *speed; |
76 | good_speed = IEEE1394_SPEED_MAX + 1; | 73 | good_speed = IEEE1394_SPEED_MAX + 1; |
77 | 74 | ||
@@ -161,16 +158,12 @@ static struct csr1212_bus_ops nodemgr_csr_ops = { | |||
161 | * but now we are much simpler because of the LDM. | 158 | * but now we are much simpler because of the LDM. |
162 | */ | 159 | */ |
163 | 160 | ||
164 | static DECLARE_MUTEX(nodemgr_serialize); | 161 | static DEFINE_MUTEX(nodemgr_serialize); |
165 | 162 | ||
166 | struct host_info { | 163 | struct host_info { |
167 | struct hpsb_host *host; | 164 | struct hpsb_host *host; |
168 | struct list_head list; | 165 | struct list_head list; |
169 | struct completion exited; | 166 | struct task_struct *thread; |
170 | struct semaphore reset_sem; | ||
171 | int pid; | ||
172 | char daemon_name[15]; | ||
173 | int kill_me; | ||
174 | }; | 167 | }; |
175 | 168 | ||
176 | static int nodemgr_bus_match(struct device * dev, struct device_driver * drv); | 169 | static int nodemgr_bus_match(struct device * dev, struct device_driver * drv); |
@@ -334,34 +327,44 @@ static ssize_t fw_show_ne_bus_options(struct device *dev, struct device_attribut | |||
334 | static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL); | 327 | static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL); |
335 | 328 | ||
336 | 329 | ||
337 | /* tlabels_free, tlabels_allocations, tlabels_mask are read non-atomically | 330 | #ifdef HPSB_DEBUG_TLABELS |
338 | * here, therefore displayed values may be occasionally wrong. */ | 331 | static ssize_t fw_show_ne_tlabels_free(struct device *dev, |
339 | static ssize_t fw_show_ne_tlabels_free(struct device *dev, struct device_attribute *attr, char *buf) | 332 | struct device_attribute *attr, char *buf) |
340 | { | 333 | { |
341 | struct node_entry *ne = container_of(dev, struct node_entry, device); | 334 | struct node_entry *ne = container_of(dev, struct node_entry, device); |
342 | return sprintf(buf, "%d\n", 64 - bitmap_weight(ne->tpool->pool, 64)); | 335 | unsigned long flags; |
343 | } | 336 | unsigned long *tp = ne->host->tl_pool[NODEID_TO_NODE(ne->nodeid)].map; |
344 | static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL); | 337 | int tf; |
345 | 338 | ||
339 | spin_lock_irqsave(&hpsb_tlabel_lock, flags); | ||
340 | tf = 64 - bitmap_weight(tp, 64); | ||
341 | spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); | ||
346 | 342 | ||
347 | static ssize_t fw_show_ne_tlabels_allocations(struct device *dev, struct device_attribute *attr, char *buf) | 343 | return sprintf(buf, "%d\n", tf); |
348 | { | ||
349 | struct node_entry *ne = container_of(dev, struct node_entry, device); | ||
350 | return sprintf(buf, "%u\n", ne->tpool->allocations); | ||
351 | } | 344 | } |
352 | static DEVICE_ATTR(tlabels_allocations,S_IRUGO,fw_show_ne_tlabels_allocations,NULL); | 345 | static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL); |
353 | 346 | ||
354 | 347 | ||
355 | static ssize_t fw_show_ne_tlabels_mask(struct device *dev, struct device_attribute *attr, char *buf) | 348 | static ssize_t fw_show_ne_tlabels_mask(struct device *dev, |
349 | struct device_attribute *attr, char *buf) | ||
356 | { | 350 | { |
357 | struct node_entry *ne = container_of(dev, struct node_entry, device); | 351 | struct node_entry *ne = container_of(dev, struct node_entry, device); |
352 | unsigned long flags; | ||
353 | unsigned long *tp = ne->host->tl_pool[NODEID_TO_NODE(ne->nodeid)].map; | ||
354 | u64 tm; | ||
355 | |||
356 | spin_lock_irqsave(&hpsb_tlabel_lock, flags); | ||
358 | #if (BITS_PER_LONG <= 32) | 357 | #if (BITS_PER_LONG <= 32) |
359 | return sprintf(buf, "0x%08lx%08lx\n", ne->tpool->pool[0], ne->tpool->pool[1]); | 358 | tm = ((u64)tp[0] << 32) + tp[1]; |
360 | #else | 359 | #else |
361 | return sprintf(buf, "0x%016lx\n", ne->tpool->pool[0]); | 360 | tm = tp[0]; |
362 | #endif | 361 | #endif |
362 | spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); | ||
363 | |||
364 | return sprintf(buf, "0x%016llx\n", tm); | ||
363 | } | 365 | } |
364 | static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL); | 366 | static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL); |
367 | #endif /* HPSB_DEBUG_TLABELS */ | ||
365 | 368 | ||
366 | 369 | ||
367 | static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 370 | static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
@@ -408,26 +411,11 @@ static ssize_t fw_get_destroy_node(struct bus_type *bus, char *buf) | |||
408 | } | 411 | } |
409 | static BUS_ATTR(destroy_node, S_IWUSR | S_IRUGO, fw_get_destroy_node, fw_set_destroy_node); | 412 | static BUS_ATTR(destroy_node, S_IWUSR | S_IRUGO, fw_get_destroy_node, fw_set_destroy_node); |
410 | 413 | ||
411 | static int nodemgr_rescan_bus_thread(void *__unused) | ||
412 | { | ||
413 | /* No userlevel access needed */ | ||
414 | daemonize("kfwrescan"); | ||
415 | |||
416 | bus_rescan_devices(&ieee1394_bus_type); | ||
417 | |||
418 | return 0; | ||
419 | } | ||
420 | 414 | ||
421 | static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf, size_t count) | 415 | static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf, size_t count) |
422 | { | 416 | { |
423 | int state = simple_strtoul(buf, NULL, 10); | 417 | if (simple_strtoul(buf, NULL, 10) == 1) |
424 | 418 | bus_rescan_devices(&ieee1394_bus_type); | |
425 | /* Don't wait for this, or care about errors. Root could do | ||
426 | * something stupid and spawn this a lot of times, but that's | ||
427 | * root's fault. */ | ||
428 | if (state == 1) | ||
429 | kernel_thread(nodemgr_rescan_bus_thread, NULL, CLONE_KERNEL); | ||
430 | |||
431 | return count; | 419 | return count; |
432 | } | 420 | } |
433 | static ssize_t fw_get_rescan(struct bus_type *bus, char *buf) | 421 | static ssize_t fw_get_rescan(struct bus_type *bus, char *buf) |
@@ -483,9 +471,10 @@ static struct device_attribute *const fw_ne_attrs[] = { | |||
483 | &dev_attr_ne_vendor_id, | 471 | &dev_attr_ne_vendor_id, |
484 | &dev_attr_ne_nodeid, | 472 | &dev_attr_ne_nodeid, |
485 | &dev_attr_bus_options, | 473 | &dev_attr_bus_options, |
474 | #ifdef HPSB_DEBUG_TLABELS | ||
486 | &dev_attr_tlabels_free, | 475 | &dev_attr_tlabels_free, |
487 | &dev_attr_tlabels_allocations, | ||
488 | &dev_attr_tlabels_mask, | 476 | &dev_attr_tlabels_mask, |
477 | #endif | ||
489 | }; | 478 | }; |
490 | 479 | ||
491 | 480 | ||
@@ -804,8 +793,6 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr | |||
804 | if (!ne) | 793 | if (!ne) |
805 | return NULL; | 794 | return NULL; |
806 | 795 | ||
807 | ne->tpool = &host->tpool[nodeid & NODE_MASK]; | ||
808 | |||
809 | ne->host = host; | 796 | ne->host = host; |
810 | ne->nodeid = nodeid; | 797 | ne->nodeid = nodeid; |
811 | ne->generation = generation; | 798 | ne->generation = generation; |
@@ -1251,6 +1238,7 @@ static void nodemgr_node_scan_one(struct host_info *hi, | |||
1251 | octlet_t guid; | 1238 | octlet_t guid; |
1252 | struct csr1212_csr *csr; | 1239 | struct csr1212_csr *csr; |
1253 | struct nodemgr_csr_info *ci; | 1240 | struct nodemgr_csr_info *ci; |
1241 | u8 *speed; | ||
1254 | 1242 | ||
1255 | ci = kmalloc(sizeof(*ci), GFP_KERNEL); | 1243 | ci = kmalloc(sizeof(*ci), GFP_KERNEL); |
1256 | if (!ci) | 1244 | if (!ci) |
@@ -1259,8 +1247,12 @@ static void nodemgr_node_scan_one(struct host_info *hi, | |||
1259 | ci->host = host; | 1247 | ci->host = host; |
1260 | ci->nodeid = nodeid; | 1248 | ci->nodeid = nodeid; |
1261 | ci->generation = generation; | 1249 | ci->generation = generation; |
1262 | ci->speed_unverified = | 1250 | |
1263 | host->speed[NODEID_TO_NODE(nodeid)] > IEEE1394_SPEED_100; | 1251 | /* Prepare for speed probe which occurs when reading the ROM */ |
1252 | speed = &(host->speed[NODEID_TO_NODE(nodeid)]); | ||
1253 | if (*speed > host->csr.lnk_spd) | ||
1254 | *speed = host->csr.lnk_spd; | ||
1255 | ci->speed_unverified = *speed > IEEE1394_SPEED_100; | ||
1264 | 1256 | ||
1265 | /* We need to detect when the ConfigROM's generation has changed, | 1257 | /* We need to detect when the ConfigROM's generation has changed, |
1266 | * so we only update the node's info when it needs to be. */ | 1258 | * so we only update the node's info when it needs to be. */ |
@@ -1300,8 +1292,6 @@ static void nodemgr_node_scan_one(struct host_info *hi, | |||
1300 | nodemgr_create_node(guid, csr, hi, nodeid, generation); | 1292 | nodemgr_create_node(guid, csr, hi, nodeid, generation); |
1301 | else | 1293 | else |
1302 | nodemgr_update_node(ne, csr, hi, nodeid, generation); | 1294 | nodemgr_update_node(ne, csr, hi, nodeid, generation); |
1303 | |||
1304 | return; | ||
1305 | } | 1295 | } |
1306 | 1296 | ||
1307 | 1297 | ||
@@ -1326,6 +1316,7 @@ static void nodemgr_node_scan(struct host_info *hi, int generation) | |||
1326 | } | 1316 | } |
1327 | 1317 | ||
1328 | 1318 | ||
1319 | /* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */ | ||
1329 | static void nodemgr_suspend_ne(struct node_entry *ne) | 1320 | static void nodemgr_suspend_ne(struct node_entry *ne) |
1330 | { | 1321 | { |
1331 | struct class_device *cdev; | 1322 | struct class_device *cdev; |
@@ -1361,6 +1352,7 @@ static void nodemgr_resume_ne(struct node_entry *ne) | |||
1361 | ne->in_limbo = 0; | 1352 | ne->in_limbo = 0; |
1362 | device_remove_file(&ne->device, &dev_attr_ne_in_limbo); | 1353 | device_remove_file(&ne->device, &dev_attr_ne_in_limbo); |
1363 | 1354 | ||
1355 | down_read(&nodemgr_ud_class.subsys.rwsem); | ||
1364 | down_read(&ne->device.bus->subsys.rwsem); | 1356 | down_read(&ne->device.bus->subsys.rwsem); |
1365 | list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { | 1357 | list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { |
1366 | ud = container_of(cdev, struct unit_directory, class_dev); | 1358 | ud = container_of(cdev, struct unit_directory, class_dev); |
@@ -1372,21 +1364,21 @@ static void nodemgr_resume_ne(struct node_entry *ne) | |||
1372 | ud->device.driver->resume(&ud->device); | 1364 | ud->device.driver->resume(&ud->device); |
1373 | } | 1365 | } |
1374 | up_read(&ne->device.bus->subsys.rwsem); | 1366 | up_read(&ne->device.bus->subsys.rwsem); |
1367 | up_read(&nodemgr_ud_class.subsys.rwsem); | ||
1375 | 1368 | ||
1376 | HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", | 1369 | HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", |
1377 | NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); | 1370 | NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); |
1378 | } | 1371 | } |
1379 | 1372 | ||
1380 | 1373 | ||
1374 | /* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */ | ||
1381 | static void nodemgr_update_pdrv(struct node_entry *ne) | 1375 | static void nodemgr_update_pdrv(struct node_entry *ne) |
1382 | { | 1376 | { |
1383 | struct unit_directory *ud; | 1377 | struct unit_directory *ud; |
1384 | struct hpsb_protocol_driver *pdrv; | 1378 | struct hpsb_protocol_driver *pdrv; |
1385 | struct class *class = &nodemgr_ud_class; | ||
1386 | struct class_device *cdev; | 1379 | struct class_device *cdev; |
1387 | 1380 | ||
1388 | down_read(&class->subsys.rwsem); | 1381 | list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { |
1389 | list_for_each_entry(cdev, &class->children, node) { | ||
1390 | ud = container_of(cdev, struct unit_directory, class_dev); | 1382 | ud = container_of(cdev, struct unit_directory, class_dev); |
1391 | if (ud->ne != ne || !ud->device.driver) | 1383 | if (ud->ne != ne || !ud->device.driver) |
1392 | continue; | 1384 | continue; |
@@ -1399,7 +1391,6 @@ static void nodemgr_update_pdrv(struct node_entry *ne) | |||
1399 | up_write(&ud->device.bus->subsys.rwsem); | 1391 | up_write(&ud->device.bus->subsys.rwsem); |
1400 | } | 1392 | } |
1401 | } | 1393 | } |
1402 | up_read(&class->subsys.rwsem); | ||
1403 | } | 1394 | } |
1404 | 1395 | ||
1405 | 1396 | ||
@@ -1430,6 +1421,8 @@ static void nodemgr_irm_write_bc(struct node_entry *ne, int generation) | |||
1430 | } | 1421 | } |
1431 | 1422 | ||
1432 | 1423 | ||
1424 | /* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader because the | ||
1425 | * calls to nodemgr_update_pdrv() and nodemgr_suspend_ne() here require it. */ | ||
1433 | static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation) | 1426 | static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation) |
1434 | { | 1427 | { |
1435 | struct device *dev; | 1428 | struct device *dev; |
@@ -1492,9 +1485,8 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) | |||
1492 | /* If we had a bus reset while we were scanning the bus, it is | 1485 | /* If we had a bus reset while we were scanning the bus, it is |
1493 | * possible that we did not probe all nodes. In that case, we | 1486 | * possible that we did not probe all nodes. In that case, we |
1494 | * skip the clean up for now, since we could remove nodes that | 1487 | * skip the clean up for now, since we could remove nodes that |
1495 | * were still on the bus. The bus reset increased hi->reset_sem, | 1488 | * were still on the bus. Another bus scan is pending which will |
1496 | * so there's a bus scan pending which will do the clean up | 1489 | * do the clean up eventually. |
1497 | * eventually. | ||
1498 | * | 1490 | * |
1499 | * Now let's tell the bus to rescan our devices. This may seem | 1491 | * Now let's tell the bus to rescan our devices. This may seem |
1500 | * like overhead, but the driver-model core will only scan a | 1492 | * like overhead, but the driver-model core will only scan a |
@@ -1622,41 +1614,37 @@ static int nodemgr_host_thread(void *__hi) | |||
1622 | { | 1614 | { |
1623 | struct host_info *hi = (struct host_info *)__hi; | 1615 | struct host_info *hi = (struct host_info *)__hi; |
1624 | struct hpsb_host *host = hi->host; | 1616 | struct hpsb_host *host = hi->host; |
1625 | int reset_cycles = 0; | 1617 | unsigned int g, generation = get_hpsb_generation(host) - 1; |
1626 | 1618 | int i, reset_cycles = 0; | |
1627 | /* No userlevel access needed */ | ||
1628 | daemonize(hi->daemon_name); | ||
1629 | 1619 | ||
1630 | /* Setup our device-model entries */ | 1620 | /* Setup our device-model entries */ |
1631 | nodemgr_create_host_dev_files(host); | 1621 | nodemgr_create_host_dev_files(host); |
1632 | 1622 | ||
1633 | /* Sit and wait for a signal to probe the nodes on the bus. This | 1623 | for (;;) { |
1634 | * happens when we get a bus reset. */ | 1624 | /* Sleep until next bus reset */ |
1635 | while (1) { | 1625 | set_current_state(TASK_INTERRUPTIBLE); |
1636 | unsigned int generation = 0; | 1626 | if (get_hpsb_generation(host) == generation) |
1637 | int i; | 1627 | schedule(); |
1628 | __set_current_state(TASK_RUNNING); | ||
1629 | |||
1630 | /* Thread may have been woken up to freeze or to exit */ | ||
1631 | if (try_to_freeze()) | ||
1632 | continue; | ||
1633 | if (kthread_should_stop()) | ||
1634 | goto exit; | ||
1638 | 1635 | ||
1639 | if (down_interruptible(&hi->reset_sem) || | 1636 | if (mutex_lock_interruptible(&nodemgr_serialize)) { |
1640 | down_interruptible(&nodemgr_serialize)) { | ||
1641 | if (try_to_freeze()) | 1637 | if (try_to_freeze()) |
1642 | continue; | 1638 | continue; |
1643 | printk("NodeMgr: received unexpected signal?!\n" ); | 1639 | goto exit; |
1644 | break; | ||
1645 | } | ||
1646 | |||
1647 | if (hi->kill_me) { | ||
1648 | up(&nodemgr_serialize); | ||
1649 | break; | ||
1650 | } | 1640 | } |
1651 | 1641 | ||
1652 | /* Pause for 1/4 second in 1/16 second intervals, | 1642 | /* Pause for 1/4 second in 1/16 second intervals, |
1653 | * to make sure things settle down. */ | 1643 | * to make sure things settle down. */ |
1644 | g = get_hpsb_generation(host); | ||
1654 | for (i = 0; i < 4 ; i++) { | 1645 | for (i = 0; i < 4 ; i++) { |
1655 | set_current_state(TASK_INTERRUPTIBLE); | 1646 | if (msleep_interruptible(63) || kthread_should_stop()) |
1656 | if (msleep_interruptible(63)) { | 1647 | goto unlock_exit; |
1657 | up(&nodemgr_serialize); | ||
1658 | goto caught_signal; | ||
1659 | } | ||
1660 | 1648 | ||
1661 | /* Now get the generation in which the node ID's we collect | 1649 | /* Now get the generation in which the node ID's we collect |
1662 | * are valid. During the bus scan we will use this generation | 1650 | * are valid. During the bus scan we will use this generation |
@@ -1667,20 +1655,14 @@ static int nodemgr_host_thread(void *__hi) | |||
1667 | 1655 | ||
1668 | /* If we get a reset before we are done waiting, then | 1656 | /* If we get a reset before we are done waiting, then |
1669 | * start the the waiting over again */ | 1657 | * start the the waiting over again */ |
1670 | while (!down_trylock(&hi->reset_sem)) | 1658 | if (generation != g) |
1671 | i = 0; | 1659 | g = generation, i = 0; |
1672 | |||
1673 | /* Check the kill_me again */ | ||
1674 | if (hi->kill_me) { | ||
1675 | up(&nodemgr_serialize); | ||
1676 | goto caught_signal; | ||
1677 | } | ||
1678 | } | 1660 | } |
1679 | 1661 | ||
1680 | if (!nodemgr_check_irm_capability(host, reset_cycles) || | 1662 | if (!nodemgr_check_irm_capability(host, reset_cycles) || |
1681 | !nodemgr_do_irm_duties(host, reset_cycles)) { | 1663 | !nodemgr_do_irm_duties(host, reset_cycles)) { |
1682 | reset_cycles++; | 1664 | reset_cycles++; |
1683 | up(&nodemgr_serialize); | 1665 | mutex_unlock(&nodemgr_serialize); |
1684 | continue; | 1666 | continue; |
1685 | } | 1667 | } |
1686 | reset_cycles = 0; | 1668 | reset_cycles = 0; |
@@ -1698,13 +1680,13 @@ static int nodemgr_host_thread(void *__hi) | |||
1698 | /* Update some of our sysfs symlinks */ | 1680 | /* Update some of our sysfs symlinks */ |
1699 | nodemgr_update_host_dev_links(host); | 1681 | nodemgr_update_host_dev_links(host); |
1700 | 1682 | ||
1701 | up(&nodemgr_serialize); | 1683 | mutex_unlock(&nodemgr_serialize); |
1702 | } | 1684 | } |
1703 | 1685 | unlock_exit: | |
1704 | caught_signal: | 1686 | mutex_unlock(&nodemgr_serialize); |
1687 | exit: | ||
1705 | HPSB_VERBOSE("NodeMgr: Exiting thread"); | 1688 | HPSB_VERBOSE("NodeMgr: Exiting thread"); |
1706 | 1689 | return 0; | |
1707 | complete_and_exit(&hi->exited, 0); | ||
1708 | } | 1690 | } |
1709 | 1691 | ||
1710 | int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *)) | 1692 | int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *)) |
@@ -1764,41 +1746,27 @@ static void nodemgr_add_host(struct hpsb_host *host) | |||
1764 | struct host_info *hi; | 1746 | struct host_info *hi; |
1765 | 1747 | ||
1766 | hi = hpsb_create_hostinfo(&nodemgr_highlevel, host, sizeof(*hi)); | 1748 | hi = hpsb_create_hostinfo(&nodemgr_highlevel, host, sizeof(*hi)); |
1767 | |||
1768 | if (!hi) { | 1749 | if (!hi) { |
1769 | HPSB_ERR ("NodeMgr: out of memory in add host"); | 1750 | HPSB_ERR("NodeMgr: out of memory in add host"); |
1770 | return; | 1751 | return; |
1771 | } | 1752 | } |
1772 | |||
1773 | hi->host = host; | 1753 | hi->host = host; |
1774 | init_completion(&hi->exited); | 1754 | hi->thread = kthread_run(nodemgr_host_thread, hi, "knodemgrd_%d", |
1775 | sema_init(&hi->reset_sem, 0); | 1755 | host->id); |
1776 | 1756 | if (IS_ERR(hi->thread)) { | |
1777 | sprintf(hi->daemon_name, "knodemgrd_%d", host->id); | 1757 | HPSB_ERR("NodeMgr: cannot start thread for host %d", host->id); |
1778 | |||
1779 | hi->pid = kernel_thread(nodemgr_host_thread, hi, CLONE_KERNEL); | ||
1780 | |||
1781 | if (hi->pid < 0) { | ||
1782 | HPSB_ERR ("NodeMgr: failed to start %s thread for %s", | ||
1783 | hi->daemon_name, host->driver->name); | ||
1784 | hpsb_destroy_hostinfo(&nodemgr_highlevel, host); | 1758 | hpsb_destroy_hostinfo(&nodemgr_highlevel, host); |
1785 | return; | ||
1786 | } | 1759 | } |
1787 | |||
1788 | return; | ||
1789 | } | 1760 | } |
1790 | 1761 | ||
1791 | static void nodemgr_host_reset(struct hpsb_host *host) | 1762 | static void nodemgr_host_reset(struct hpsb_host *host) |
1792 | { | 1763 | { |
1793 | struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host); | 1764 | struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host); |
1794 | 1765 | ||
1795 | if (hi != NULL) { | 1766 | if (hi) { |
1796 | HPSB_VERBOSE("NodeMgr: Processing host reset for %s", hi->daemon_name); | 1767 | HPSB_VERBOSE("NodeMgr: Processing reset for host %d", host->id); |
1797 | up(&hi->reset_sem); | 1768 | wake_up_process(hi->thread); |
1798 | } else | 1769 | } |
1799 | HPSB_ERR ("NodeMgr: could not process reset of unused host"); | ||
1800 | |||
1801 | return; | ||
1802 | } | 1770 | } |
1803 | 1771 | ||
1804 | static void nodemgr_remove_host(struct hpsb_host *host) | 1772 | static void nodemgr_remove_host(struct hpsb_host *host) |
@@ -1806,18 +1774,9 @@ static void nodemgr_remove_host(struct hpsb_host *host) | |||
1806 | struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host); | 1774 | struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host); |
1807 | 1775 | ||
1808 | if (hi) { | 1776 | if (hi) { |
1809 | if (hi->pid >= 0) { | 1777 | kthread_stop(hi->thread); |
1810 | hi->kill_me = 1; | 1778 | nodemgr_remove_host_dev(&host->device); |
1811 | mb(); | 1779 | } |
1812 | up(&hi->reset_sem); | ||
1813 | wait_for_completion(&hi->exited); | ||
1814 | nodemgr_remove_host_dev(&host->device); | ||
1815 | } | ||
1816 | } else | ||
1817 | HPSB_ERR("NodeMgr: host %s does not exist, cannot remove", | ||
1818 | host->driver->name); | ||
1819 | |||
1820 | return; | ||
1821 | } | 1780 | } |
1822 | 1781 | ||
1823 | static struct hpsb_highlevel nodemgr_highlevel = { | 1782 | static struct hpsb_highlevel nodemgr_highlevel = { |