diff options
-rw-r--r-- | drivers/ieee1394/nodemgr.c | 69 |
1 files changed, 43 insertions, 26 deletions
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 893955249bad..c4d3d4131f01 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
20 | #include <linux/freezer.h> | 20 | #include <linux/freezer.h> |
21 | #include <asm/atomic.h> | 21 | #include <asm/atomic.h> |
22 | #include <asm/semaphore.h> | ||
22 | 23 | ||
23 | #include "csr.h" | 24 | #include "csr.h" |
24 | #include "highlevel.h" | 25 | #include "highlevel.h" |
@@ -145,8 +146,6 @@ static struct csr1212_bus_ops nodemgr_csr_ops = { | |||
145 | * but now we are much simpler because of the LDM. | 146 | * but now we are much simpler because of the LDM. |
146 | */ | 147 | */ |
147 | 148 | ||
148 | static DEFINE_MUTEX(nodemgr_serialize); | ||
149 | |||
150 | struct host_info { | 149 | struct host_info { |
151 | struct hpsb_host *host; | 150 | struct hpsb_host *host; |
152 | struct list_head list; | 151 | struct list_head list; |
@@ -1382,6 +1381,8 @@ static void nodemgr_suspend_ne(struct node_entry *ne) | |||
1382 | { | 1381 | { |
1383 | struct device *dev; | 1382 | struct device *dev; |
1384 | struct unit_directory *ud; | 1383 | struct unit_directory *ud; |
1384 | struct device_driver *drv; | ||
1385 | int error; | ||
1385 | 1386 | ||
1386 | HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", | 1387 | HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", |
1387 | NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); | 1388 | NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); |
@@ -1395,10 +1396,19 @@ static void nodemgr_suspend_ne(struct node_entry *ne) | |||
1395 | if (ud->ne != ne) | 1396 | if (ud->ne != ne) |
1396 | continue; | 1397 | continue; |
1397 | 1398 | ||
1398 | if (ud->device.driver && | 1399 | drv = get_driver(ud->device.driver); |
1399 | (!ud->device.driver->suspend || | 1400 | if (!drv) |
1400 | ud->device.driver->suspend(&ud->device, PMSG_SUSPEND))) | 1401 | continue; |
1402 | |||
1403 | error = 1; /* release if suspend is not implemented */ | ||
1404 | if (drv->suspend) { | ||
1405 | down(&ud->device.sem); | ||
1406 | error = drv->suspend(&ud->device, PMSG_SUSPEND); | ||
1407 | up(&ud->device.sem); | ||
1408 | } | ||
1409 | if (error) | ||
1401 | device_release_driver(&ud->device); | 1410 | device_release_driver(&ud->device); |
1411 | put_driver(drv); | ||
1402 | } | 1412 | } |
1403 | up(&nodemgr_ud_class.sem); | 1413 | up(&nodemgr_ud_class.sem); |
1404 | } | 1414 | } |
@@ -1408,6 +1418,7 @@ static void nodemgr_resume_ne(struct node_entry *ne) | |||
1408 | { | 1418 | { |
1409 | struct device *dev; | 1419 | struct device *dev; |
1410 | struct unit_directory *ud; | 1420 | struct unit_directory *ud; |
1421 | struct device_driver *drv; | ||
1411 | 1422 | ||
1412 | ne->in_limbo = 0; | 1423 | ne->in_limbo = 0; |
1413 | device_remove_file(&ne->device, &dev_attr_ne_in_limbo); | 1424 | device_remove_file(&ne->device, &dev_attr_ne_in_limbo); |
@@ -1418,8 +1429,16 @@ static void nodemgr_resume_ne(struct node_entry *ne) | |||
1418 | if (ud->ne != ne) | 1429 | if (ud->ne != ne) |
1419 | continue; | 1430 | continue; |
1420 | 1431 | ||
1421 | if (ud->device.driver && ud->device.driver->resume) | 1432 | drv = get_driver(ud->device.driver); |
1422 | ud->device.driver->resume(&ud->device); | 1433 | if (!drv) |
1434 | continue; | ||
1435 | |||
1436 | if (drv->resume) { | ||
1437 | down(&ud->device.sem); | ||
1438 | drv->resume(&ud->device); | ||
1439 | up(&ud->device.sem); | ||
1440 | } | ||
1441 | put_driver(drv); | ||
1423 | } | 1442 | } |
1424 | up(&nodemgr_ud_class.sem); | 1443 | up(&nodemgr_ud_class.sem); |
1425 | 1444 | ||
@@ -1430,9 +1449,11 @@ static void nodemgr_resume_ne(struct node_entry *ne) | |||
1430 | 1449 | ||
1431 | static void nodemgr_update_pdrv(struct node_entry *ne) | 1450 | static void nodemgr_update_pdrv(struct node_entry *ne) |
1432 | { | 1451 | { |
1452 | struct device *dev; | ||
1433 | struct unit_directory *ud; | 1453 | struct unit_directory *ud; |
1454 | struct device_driver *drv; | ||
1434 | struct hpsb_protocol_driver *pdrv; | 1455 | struct hpsb_protocol_driver *pdrv; |
1435 | struct device *dev; | 1456 | int error; |
1436 | 1457 | ||
1437 | down(&nodemgr_ud_class.sem); | 1458 | down(&nodemgr_ud_class.sem); |
1438 | list_for_each_entry(dev, &nodemgr_ud_class.devices, node) { | 1459 | list_for_each_entry(dev, &nodemgr_ud_class.devices, node) { |
@@ -1440,13 +1461,20 @@ static void nodemgr_update_pdrv(struct node_entry *ne) | |||
1440 | if (ud->ne != ne) | 1461 | if (ud->ne != ne) |
1441 | continue; | 1462 | continue; |
1442 | 1463 | ||
1443 | if (ud->device.driver) { | 1464 | drv = get_driver(ud->device.driver); |
1444 | pdrv = container_of(ud->device.driver, | 1465 | if (!drv) |
1445 | struct hpsb_protocol_driver, | 1466 | continue; |
1446 | driver); | 1467 | |
1447 | if (pdrv->update && pdrv->update(ud)) | 1468 | error = 0; |
1448 | device_release_driver(&ud->device); | 1469 | pdrv = container_of(drv, struct hpsb_protocol_driver, driver); |
1470 | if (pdrv->update) { | ||
1471 | down(&ud->device.sem); | ||
1472 | error = pdrv->update(ud); | ||
1473 | up(&ud->device.sem); | ||
1449 | } | 1474 | } |
1475 | if (error) | ||
1476 | device_release_driver(&ud->device); | ||
1477 | put_driver(drv); | ||
1450 | } | 1478 | } |
1451 | up(&nodemgr_ud_class.sem); | 1479 | up(&nodemgr_ud_class.sem); |
1452 | } | 1480 | } |
@@ -1688,18 +1716,12 @@ static int nodemgr_host_thread(void *__hi) | |||
1688 | if (kthread_should_stop()) | 1716 | if (kthread_should_stop()) |
1689 | goto exit; | 1717 | goto exit; |
1690 | 1718 | ||
1691 | if (mutex_lock_interruptible(&nodemgr_serialize)) { | ||
1692 | if (try_to_freeze()) | ||
1693 | continue; | ||
1694 | goto exit; | ||
1695 | } | ||
1696 | |||
1697 | /* Pause for 1/4 second in 1/16 second intervals, | 1719 | /* Pause for 1/4 second in 1/16 second intervals, |
1698 | * to make sure things settle down. */ | 1720 | * to make sure things settle down. */ |
1699 | g = get_hpsb_generation(host); | 1721 | g = get_hpsb_generation(host); |
1700 | for (i = 0; i < 4 ; i++) { | 1722 | for (i = 0; i < 4 ; i++) { |
1701 | if (msleep_interruptible(63) || kthread_should_stop()) | 1723 | if (msleep_interruptible(63) || kthread_should_stop()) |
1702 | goto unlock_exit; | 1724 | goto exit; |
1703 | 1725 | ||
1704 | /* Now get the generation in which the node ID's we collect | 1726 | /* Now get the generation in which the node ID's we collect |
1705 | * are valid. During the bus scan we will use this generation | 1727 | * are valid. During the bus scan we will use this generation |
@@ -1717,7 +1739,6 @@ static int nodemgr_host_thread(void *__hi) | |||
1717 | if (!nodemgr_check_irm_capability(host, reset_cycles) || | 1739 | if (!nodemgr_check_irm_capability(host, reset_cycles) || |
1718 | !nodemgr_do_irm_duties(host, reset_cycles)) { | 1740 | !nodemgr_do_irm_duties(host, reset_cycles)) { |
1719 | reset_cycles++; | 1741 | reset_cycles++; |
1720 | mutex_unlock(&nodemgr_serialize); | ||
1721 | continue; | 1742 | continue; |
1722 | } | 1743 | } |
1723 | reset_cycles = 0; | 1744 | reset_cycles = 0; |
@@ -1734,11 +1755,7 @@ static int nodemgr_host_thread(void *__hi) | |||
1734 | 1755 | ||
1735 | /* Update some of our sysfs symlinks */ | 1756 | /* Update some of our sysfs symlinks */ |
1736 | nodemgr_update_host_dev_links(host); | 1757 | nodemgr_update_host_dev_links(host); |
1737 | |||
1738 | mutex_unlock(&nodemgr_serialize); | ||
1739 | } | 1758 | } |
1740 | unlock_exit: | ||
1741 | mutex_unlock(&nodemgr_serialize); | ||
1742 | exit: | 1759 | exit: |
1743 | HPSB_VERBOSE("NodeMgr: Exiting thread"); | 1760 | HPSB_VERBOSE("NodeMgr: Exiting thread"); |
1744 | return 0; | 1761 | return 0; |