#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;