summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2007-06-17 23:47:45 +0200
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-07-10 00:07:39 +0200
commita0e857eeffba8976be6bdb9f4bb011c18eb2aff7 (patch)
tree2edceea4805bd9ab0dc91da9931d66c8bcd8d02a
parentdd7f2928d834f7ac67202bcdf24a44ba9b138f08 (diff)
downloadop-kernel-dev-a0e857eeffba8976be6bdb9f4bb011c18eb2aff7.zip
op-kernel-dev-a0e857eeffba8976be6bdb9f4bb011c18eb2aff7.tar.gz
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 8939552..c4d3d41 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -19,6 +19,7 @@
#include <linux/mutex.h>
#include <linux/freezer.h>
#include <asm/atomic.h>
+#include <asm/semaphore.h>
#include "csr.h"
#include "highlevel.h"
@@ -145,8 +146,6 @@ static struct csr1212_bus_ops nodemgr_csr_ops = {
* but now we are much simpler because of the LDM.
*/
-static DEFINE_MUTEX(nodemgr_serialize);
-
struct host_info {
struct hpsb_host *host;
struct list_head list;
@@ -1382,6 +1381,8 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
{
struct device *dev;
struct unit_directory *ud;
+ struct device_driver *drv;
+ int error;
HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
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)
if (ud->ne != ne)
continue;
- if (ud->device.driver &&
- (!ud->device.driver->suspend ||
- ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
+ drv = get_driver(ud->device.driver);
+ if (!drv)
+ continue;
+
+ error = 1; /* release if suspend is not implemented */
+ if (drv->suspend) {
+ down(&ud->device.sem);
+ error = drv->suspend(&ud->device, PMSG_SUSPEND);
+ up(&ud->device.sem);
+ }
+ if (error)
device_release_driver(&ud->device);
+ put_driver(drv);
}
up(&nodemgr_ud_class.sem);
}
@@ -1408,6 +1418,7 @@ static void nodemgr_resume_ne(struct node_entry *ne)
{
struct device *dev;
struct unit_directory *ud;
+ struct device_driver *drv;
ne->in_limbo = 0;
device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
@@ -1418,8 +1429,16 @@ static void nodemgr_resume_ne(struct node_entry *ne)
if (ud->ne != ne)
continue;
- if (ud->device.driver && ud->device.driver->resume)
- ud->device.driver->resume(&ud->device);
+ drv = get_driver(ud->device.driver);
+ if (!drv)
+ continue;
+
+ if (drv->resume) {
+ down(&ud->device.sem);
+ drv->resume(&ud->device);
+ up(&ud->device.sem);
+ }
+ put_driver(drv);
}
up(&nodemgr_ud_class.sem);
@@ -1430,9 +1449,11 @@ static void nodemgr_resume_ne(struct node_entry *ne)
static void nodemgr_update_pdrv(struct node_entry *ne)
{
+ struct device *dev;
struct unit_directory *ud;
+ struct device_driver *drv;
struct hpsb_protocol_driver *pdrv;
- struct device *dev;
+ int error;
down(&nodemgr_ud_class.sem);
list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
@@ -1440,13 +1461,20 @@ static void nodemgr_update_pdrv(struct node_entry *ne)
if (ud->ne != ne)
continue;
- if (ud->device.driver) {
- pdrv = container_of(ud->device.driver,
- struct hpsb_protocol_driver,
- driver);
- if (pdrv->update && pdrv->update(ud))
- device_release_driver(&ud->device);
+ drv = get_driver(ud->device.driver);
+ if (!drv)
+ continue;
+
+ error = 0;
+ pdrv = container_of(drv, struct hpsb_protocol_driver, driver);
+ if (pdrv->update) {
+ down(&ud->device.sem);
+ error = pdrv->update(ud);
+ up(&ud->device.sem);
}
+ if (error)
+ device_release_driver(&ud->device);
+ put_driver(drv);
}
up(&nodemgr_ud_class.sem);
}
@@ -1688,18 +1716,12 @@ static int nodemgr_host_thread(void *__hi)
if (kthread_should_stop())
goto exit;
- if (mutex_lock_interruptible(&nodemgr_serialize)) {
- if (try_to_freeze())
- continue;
- goto exit;
- }
-
/* Pause for 1/4 second in 1/16 second intervals,
* to make sure things settle down. */
g = get_hpsb_generation(host);
for (i = 0; i < 4 ; i++) {
if (msleep_interruptible(63) || kthread_should_stop())
- goto unlock_exit;
+ goto exit;
/* Now get the generation in which the node ID's we collect
* are valid. During the bus scan we will use this generation
@@ -1717,7 +1739,6 @@ static int nodemgr_host_thread(void *__hi)
if (!nodemgr_check_irm_capability(host, reset_cycles) ||
!nodemgr_do_irm_duties(host, reset_cycles)) {
reset_cycles++;
- mutex_unlock(&nodemgr_serialize);
continue;
}
reset_cycles = 0;
@@ -1734,11 +1755,7 @@ static int nodemgr_host_thread(void *__hi)
/* Update some of our sysfs symlinks */
nodemgr_update_host_dev_links(host);
-
- mutex_unlock(&nodemgr_serialize);
}
-unlock_exit:
- mutex_unlock(&nodemgr_serialize);
exit:
HPSB_VERBOSE("NodeMgr: Exiting thread");
return 0;
OpenPOWER on IntegriCloud