aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2007-06-17 17:47:45 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-07-09 18:07:39 -0400
commita0e857eeffba8976be6bdb9f4bb011c18eb2aff7 (patch)
tree2edceea4805bd9ab0dc91da9931d66c8bcd8d02a
parentdd7f2928d834f7ac67202bcdf24a44ba9b138f08 (diff)
ieee1394: nodemgr: parallelize between several hosts
Remove the global nodemgr_serialize mutex which enclosed most of the host thread event loop. This allows for parallelism between several host adapter cards. Properly serialize the driver hooks .update(), .suspend(), .resume(), and .remove() by means of device->sem. These hooks can be called from outside the host threads' contexts. Get() and put() the device.driver when calling its hooks. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
-rw-r--r--drivers/ieee1394/nodemgr.c69
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
148static DEFINE_MUTEX(nodemgr_serialize);
149
150struct host_info { 149struct 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
1431static void nodemgr_update_pdrv(struct node_entry *ne) 1450static 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 }
1740unlock_exit:
1741 mutex_unlock(&nodemgr_serialize);
1742exit: 1759exit:
1743 HPSB_VERBOSE("NodeMgr: Exiting thread"); 1760 HPSB_VERBOSE("NodeMgr: Exiting thread");
1744 return 0; 1761 return 0;