diff options
| author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-30 12:38:19 -0400 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-30 12:38:19 -0400 | 
| commit | 0cd43f83d381c4246a08cd775834833d6fd64805 (patch) | |
| tree | e69ddf876edfb4ff7d5d5d0c6e7c2ff0be885492 /drivers/ieee1394/nodemgr.c | |
| parent | db1a19b38f3a85f475b4ad716c71be133d8ca48e (diff) | |
| parent | 3253b669eed7194ae490acb4aadab7262bbfeb8d (diff) | |
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6: (48 commits)
  ieee1394: raw1394: arm functions slept in atomic context
  ieee1394: sbp2: enable auto spin-up for all SBP-2 devices
  MAINTAINERS: updates to IEEE 1394 subsystem maintainership
  ieee1394: ohci1394: check for errors in suspend or resume
  set power state of firewire host during suspend
  ieee1394: ohci1394: more obvious endianess handling
  ieee1394: ohci1394: fix endianess bug in debug message
  ieee1394: sbp2: don't prefer MODE SENSE 10
  ieee1394: nodemgr: grab class.subsys.rwsem in nodemgr_resume_ne
  ieee1394: nodemgr: fix rwsem recursion
  ieee1394: sbp2: more help in Kconfig
  ieee1394: sbp2: prevent rare deadlock in shutdown
  ieee1394: sbp2: update includes
  ieee1394: sbp2: better handling of transport errors
  ieee1394: sbp2: recheck node generation in sbp2_update
  ieee1394: sbp2: safer agent reset in error handlers
  ieee1394: sbp2: handle "sbp2util_node_write_no_wait failed"
  CONFIG_PM=n slim: drivers/ieee1394/ohci1394.c
  ieee1394: safer definition of empty macros
  video1394: add poll file operation support
  ...
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 = { | 
