#include <linux/mutex.h>
#include <linux/freezer.h>
#include <asm/atomic.h>
+#include <asm/semaphore.h>
#include "csr.h"
#include "highlevel.h"
* 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;
{
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);
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);
}
{
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);
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);
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) {
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);
}
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
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;
/* 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;