Skip to content

Commit

Permalink
ieee1394: nodemgr: parallelize between several hosts
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Stefan Richter committed Jul 9, 2007
1 parent dd7f292 commit a0e857e
Showing 1 changed file with 43 additions and 26 deletions.
69 changes: 43 additions & 26 deletions drivers/ieee1394/nodemgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
Expand All @@ -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);
Expand All @@ -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);

Expand All @@ -1430,23 +1449,32 @@ 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) {
ud = container_of(dev, struct unit_directory, unit_dev);
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);
}
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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;
Expand Down

0 comments on commit a0e857e

Please sign in to comment.