diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 7daffbfd9913f83c7e00ad683b1402e3163782cf..559956c297635aba0218931439ca8dcbe3c58b5b 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -47,23 +47,21 @@ int bus_for_each_dev(struct bus_type * bus, void * data,
 	int error = 0;
 
 	get_bus(bus);
-	spin_lock(&device_lock);
+	down_write(&bus->rwsem);
 	list_for_each(node,&bus->devices) {
-		struct device * dev = get_device_locked(to_dev(node));
+		struct device * dev = get_device(to_dev(node));
 		if (dev) {
-			spin_unlock(&device_lock);
 			error = callback(dev,data);
 			if (prev)
 				put_device(prev);
 			prev = dev;
-			spin_lock(&device_lock);
 			if (error)
 				break;
 		}
 	}
-	spin_unlock(&device_lock);
 	if (prev)
 		put_device(prev);
+	up_write(&bus->rwsem);
 	put_bus(bus);
 	return error;
 }
@@ -77,24 +75,21 @@ int bus_for_each_drv(struct bus_type * bus, void * data,
 
 	/* pin bus in memory */
 	get_bus(bus);
-
-	spin_lock(&device_lock);
+	down_write(&bus->rwsem);
 	list_for_each(node,&bus->drivers) {
 		struct device_driver * drv = get_driver(to_drv(node));
 		if (drv) {
-			spin_unlock(&device_lock);
 			error = callback(drv,data);
 			if (prev)
 				put_driver(prev);
 			prev = drv;
-			spin_lock(&device_lock);
 			if (error)
 				break;
 		}
 	}
-	spin_unlock(&device_lock);
 	if (prev)
 		put_driver(prev);
+	up_write(&bus->rwsem);
 	put_bus(bus);
 	return error;
 }
@@ -111,11 +106,11 @@ int bus_for_each_drv(struct bus_type * bus, void * data,
 int bus_add_device(struct device * dev)
 {
 	if (dev->bus) {
+		down_write(&dev->bus->rwsem);
 		pr_debug("registering %s with bus '%s'\n",dev->bus_id,dev->bus->name);
 		get_bus(dev->bus);
-		spin_lock(&device_lock);
 		list_add_tail(&dev->bus_list,&dev->bus->devices);
-		spin_unlock(&device_lock);
+		up_write(&dev->bus->rwsem);
 		device_bus_link(dev);
 	}
 	return 0;
@@ -131,17 +126,43 @@ int bus_add_device(struct device * dev)
 void bus_remove_device(struct device * dev)
 {
 	if (dev->bus) {
+		down_write(&dev->bus->rwsem);
+		list_del_init(&dev->bus_list);
 		device_remove_symlink(&dev->bus->device_dir,dev->bus_id);
+		up_write(&dev->bus->rwsem);
 		put_bus(dev->bus);
 	}
 }
 
+struct bus_type * get_bus(struct bus_type * bus)
+{
+	struct bus_type * ret = bus;
+	spin_lock(&device_lock);
+	if (bus && bus->present && atomic_read(&bus->refcount))
+		atomic_inc(&bus->refcount);
+	else
+		ret = NULL;
+	spin_unlock(&device_lock);
+	return ret;
+}
+
+void put_bus(struct bus_type * bus)
+{
+	if (!atomic_dec_and_lock(&bus->refcount,&device_lock))
+		return;
+	list_del_init(&bus->node);
+	spin_unlock(&device_lock);
+	BUG_ON(bus->present);
+	bus_remove_dir(bus);
+}
+
 int bus_register(struct bus_type * bus)
 {
-	rwlock_init(&bus->lock);
+	init_rwsem(&bus->rwsem);
 	INIT_LIST_HEAD(&bus->devices);
 	INIT_LIST_HEAD(&bus->drivers);
 	atomic_set(&bus->refcount,2);
+	bus->present = 1;
 
 	spin_lock(&device_lock);
 	list_add_tail(&bus->node,&bus_driver_list);
@@ -156,13 +177,14 @@ int bus_register(struct bus_type * bus)
 	return 0;
 }
 
-void put_bus(struct bus_type * bus)
+void bus_unregister(struct bus_type * bus)
 {
-	if (!atomic_dec_and_lock(&bus->refcount,&device_lock))
-		return;
-	list_del_init(&bus->node);
+	spin_lock(&device_lock);
+	bus->present = 0;
 	spin_unlock(&device_lock);
-	bus_remove_dir(bus);
+
+	pr_debug("bus %s: unregistering\n",bus->name);
+	put_bus(bus);
 }
 
 EXPORT_SYMBOL(bus_for_each_dev);
@@ -170,4 +192,6 @@ EXPORT_SYMBOL(bus_for_each_drv);
 EXPORT_SYMBOL(bus_add_device);
 EXPORT_SYMBOL(bus_remove_device);
 EXPORT_SYMBOL(bus_register);
+EXPORT_SYMBOL(bus_unregister);
+EXPORT_SYMBOL(get_bus);
 EXPORT_SYMBOL(put_bus);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index dfef9793871a07e3f82fbe28cb22d78e100009d0..3c7024cc3efb2069ffa3f65d5c3f42561c7cf6e5 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -81,29 +81,55 @@ void devclass_remove_device(struct device * dev)
 	}
 }
 
+struct device_class * get_devclass(struct device_class * cls)
+{
+	struct device_class * ret = cls;
+	spin_lock(&device_lock);
+	if (cls && cls->present && atomic_read(&cls->refcount) > 0)
+		atomic_inc(&cls->refcount);
+	else
+		ret = NULL;
+	spin_unlock(&device_lock);
+	return ret;
+}
+
+void put_devclass(struct device_class * cls)
+{
+	if (atomic_dec_and_lock(&cls->refcount,&device_lock)) {
+		list_del_init(&cls->node);
+		spin_unlock(&device_lock);
+		devclass_remove_dir(cls);
+	}
+}
+
+
 int devclass_register(struct device_class * cls)
 {
 	INIT_LIST_HEAD(&cls->drivers);
 	INIT_LIST_HEAD(&cls->intf_list);
-
-	pr_debug("registering device class '%s'\n",cls->name);
+	atomic_set(&cls->refcount,2);
+	cls->present = 1;
+	pr_debug("device class '%s': registering\n",cls->name);
 
 	spin_lock(&device_lock);
 	list_add_tail(&cls->node,&class_list);
 	spin_unlock(&device_lock);
 	devclass_make_dir(cls);
+	put_devclass(cls);
 	return 0;
 }
 
 void devclass_unregister(struct device_class * cls)
 {
-	pr_debug("unregistering device class '%s'\n",cls->name);
-	devclass_remove_dir(cls);
 	spin_lock(&device_lock);
-	list_del_init(&class_list);
+	cls->present = 0;
 	spin_unlock(&device_lock);
+	pr_debug("device class '%s': unregistering\n",cls->name);
+	put_devclass(cls);
 }
 
 EXPORT_SYMBOL(devclass_register);
 EXPORT_SYMBOL(devclass_unregister);
+EXPORT_SYMBOL(get_devclass);
+EXPORT_SYMBOL(put_devclass);
 
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 83c31723d8447211514f1e84cce555f7214e8847..a1a41f4b0a07892ebf4a6a7d31cdf8bc4b56976e 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -259,34 +259,21 @@ struct device * get_device(struct device * dev)
  */
 void put_device(struct device * dev)
 {
-	struct device * parent;
 	if (!atomic_dec_and_lock(&dev->refcount,&device_lock))
 		return;
-	parent = dev->parent;
-	dev->parent = NULL;
+	list_del_init(&dev->node);
+	list_del_init(&dev->g_list);
+	list_del_init(&dev->driver_list);
 	spin_unlock(&device_lock);
 
 	BUG_ON(dev->present);
 
-	if (dev->release)
-		dev->release(dev);
-
-	if (parent)
-		put_device(parent);
+	device_del(dev);
 }
 
 void device_del(struct device * dev)
 {
-	spin_lock(&device_lock);
-	dev->present = 0;
-	list_del_init(&dev->node);
-	list_del_init(&dev->g_list);
-	list_del_init(&dev->bus_list);
-	list_del_init(&dev->driver_list);
-	spin_unlock(&device_lock);
-
-	pr_debug("DEV: Unregistering device. ID = '%s', name = '%s'\n",
-		 dev->bus_id,dev->name);
+	struct device * parent = dev->parent;
 
 	/* Notify the platform of the removal, in case they
 	 * need to do anything...
@@ -302,6 +289,12 @@ void device_del(struct device * dev)
 
 	/* remove the driverfs directory */
 	device_remove_dir(dev);
+
+	if (dev->release)
+		dev->release(dev);
+
+	if (parent)
+		put_device(parent);
 }
 
 /**
@@ -315,22 +308,15 @@ void device_del(struct device * dev)
  */
 void device_unregister(struct device * dev)
 {
-	device_del(dev);
-	put_device(dev);
-}
-
-static int __init device_init(void)
-{
-	int error;
+	spin_lock(&device_lock);
+	dev->present = 0;
+	spin_unlock(&device_lock);
 
-	error = init_driverfs_fs();
-	if (error)
-		panic("DEV: could not initialize driverfs");
-	return 0;
+	pr_debug("DEV: Unregistering device. ID = '%s', name = '%s'\n",
+		 dev->bus_id,dev->name);
+	put_device(dev);
 }
 
-core_initcall(device_init);
-
 EXPORT_SYMBOL(device_register);
 EXPORT_SYMBOL(device_unregister);
 EXPORT_SYMBOL(get_device);
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 221e525736bd30e2b423cf448fc6af278f3f2580..b19b06201dd579c5ac62bcfd81d9963c9b954d0a 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -39,6 +39,43 @@ int driver_for_each_dev(struct device_driver * drv, void * data,
 	return error;
 }
 
+struct device_driver * get_driver(struct device_driver * drv)
+{
+	struct device_driver * ret = drv;
+	spin_lock(&device_lock);
+	if (drv && drv->present && atomic_read(&drv->refcount) > 0)
+		atomic_inc(&drv->refcount);
+	else
+		ret = NULL;
+	spin_unlock(&device_lock);
+	return ret;
+}
+
+
+void remove_driver(struct device_driver * drv)
+{
+	BUG();
+}
+
+/**
+ * put_driver - decrement driver's refcount and clean up if necessary
+ * @drv:	driver in question
+ */
+void put_driver(struct device_driver * drv)
+{
+	struct bus_type * bus = drv->bus;
+	if (!atomic_dec_and_lock(&drv->refcount,&device_lock))
+		return;
+	list_del_init(&drv->bus_list);
+	spin_unlock(&device_lock);
+	BUG_ON(drv->present);
+	driver_detach(drv);
+	driver_remove_dir(drv);
+	if (drv->release)
+		drv->release(drv);
+	put_bus(bus);
+}
+
 /**
  * driver_register - register driver with bus
  * @drv:	driver to register
@@ -50,12 +87,13 @@ int driver_register(struct device_driver * drv)
 	if (!drv->bus)
 		return -EINVAL;
 
-	pr_debug("Registering driver '%s' with bus '%s'\n",drv->name,drv->bus->name);
+	pr_debug("driver %s:%s: registering\n",drv->bus->name,drv->name);
 
 	get_bus(drv->bus);
 	atomic_set(&drv->refcount,2);
 	rwlock_init(&drv->lock);
 	INIT_LIST_HEAD(&drv->devices);
+	drv->present = 1;
 	spin_lock(&device_lock);
 	list_add(&drv->bus_list,&drv->bus->drivers);
 	spin_unlock(&device_lock);
@@ -65,39 +103,17 @@ int driver_register(struct device_driver * drv)
 	return 0;
 }
 
-static void __remove_driver(struct device_driver * drv)
-{
-	pr_debug("Unregistering driver '%s' from bus '%s'\n",drv->name,drv->bus->name);
-	driver_detach(drv);
-	driver_remove_dir(drv);
-	if (drv->release)
-		drv->release(drv);
-	put_bus(drv->bus);
-}
-
-void remove_driver(struct device_driver * drv)
+void driver_unregister(struct device_driver * drv)
 {
 	spin_lock(&device_lock);
-	atomic_set(&drv->refcount,0);
-	list_del_init(&drv->bus_list);
-	spin_unlock(&device_lock);
-	__remove_driver(drv);
-}
-
-/**
- * put_driver - decrement driver's refcount and clean up if necessary
- * @drv:	driver in question
- */
-void put_driver(struct device_driver * drv)
-{
-	if (!atomic_dec_and_lock(&drv->refcount,&device_lock))
-		return;
-	list_del_init(&drv->bus_list);
+	drv->present = 0;
 	spin_unlock(&device_lock);
-	__remove_driver(drv);
+	pr_debug("driver %s:%s: unregistering\n",drv->bus->name,drv->name);
+	put_driver(drv);
 }
 
 EXPORT_SYMBOL(driver_for_each_dev);
 EXPORT_SYMBOL(driver_register);
+EXPORT_SYMBOL(driver_unregister);
+EXPORT_SYMBOL(get_driver);
 EXPORT_SYMBOL(put_driver);
-EXPORT_SYMBOL(remove_driver);
diff --git a/fs/driverfs/inode.c b/fs/driverfs/inode.c
index 0f35e27e669ca3b8d2df8cc8464359f06607d197..b4b5aa9f6a5552dd322f1de6974235a47c2e5dce 100644
--- a/fs/driverfs/inode.c
+++ b/fs/driverfs/inode.c
@@ -509,11 +509,13 @@ static void put_mount(void)
 	DBG("driverfs: mount_count = %d\n",mount_count);
 }
 
-int __init init_driverfs_fs(void)
+static int __init driverfs_init(void)
 {
 	return register_filesystem(&driverfs_fs_type);
 }
 
+core_initcall(driverfs_init);
+
 static struct dentry * get_dentry(struct dentry * parent, const char * name)
 {
 	struct qstr qstr;
diff --git a/include/linux/device.h b/include/linux/device.h
index 80a63939f9245e617488e973cd128e5e0588288c..c0f8d6c5e4bf120d3f84101cb64cf0184bfd1fcf 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -54,8 +54,9 @@ struct device_class;
 
 struct bus_type {
 	char			* name;
-	rwlock_t		lock;
+	struct rw_semaphore	rwsem;
 	atomic_t		refcount;
+	u32			present;
 
 	struct list_head	node;
 	struct list_head	devices;
@@ -73,14 +74,9 @@ struct bus_type {
 
 
 extern int bus_register(struct bus_type * bus);
+extern void bus_unregister(struct bus_type * bus);
 
-static inline struct bus_type * get_bus(struct bus_type * bus)
-{
-	BUG_ON(!atomic_read(&bus->refcount));
-	atomic_inc(&bus->refcount);
-	return bus;
-}
-
+extern struct bus_type * get_bus(struct bus_type * bus);
 extern void put_bus(struct bus_type * bus);
 
 extern int bus_for_each_dev(struct bus_type * bus, void * data, 
@@ -114,6 +110,7 @@ struct device_driver {
 
 	rwlock_t		lock;
 	atomic_t		refcount;
+	u32			present;
 
 	struct list_head	bus_list;
 	struct list_head	class_list;
@@ -131,16 +128,10 @@ struct device_driver {
 };
 
 
-
 extern int driver_register(struct device_driver * drv);
+extern void driver_unregister(struct device_driver * drv);
 
-static inline struct device_driver * get_driver(struct device_driver * drv)
-{
-	BUG_ON(!atomic_read(&drv->refcount));
-	atomic_inc(&drv->refcount);
-	return drv;
-}
-
+extern struct device_driver * get_driver(struct device_driver * drv);
 extern void put_driver(struct device_driver * drv);
 extern void remove_driver(struct device_driver * drv);
 
@@ -172,6 +163,9 @@ extern void driver_remove_file(struct device_driver *, struct driver_attribute *
  */
 struct device_class {
 	char			* name;
+	atomic_t		refcount;
+	u32			present;
+
 	u32			devnum;
 
 	struct list_head	node;
@@ -189,6 +183,9 @@ struct device_class {
 extern int devclass_register(struct device_class *);
 extern void devclass_unregister(struct device_class *);
 
+extern struct device_class * get_devclass(struct device_class *);
+extern void put_devclass(struct device_class *);
+
 
 struct devclass_attribute {
 	struct attribute	attr;
diff --git a/include/linux/driverfs_fs.h b/include/linux/driverfs_fs.h
index d859f8c2e041b43f38020fdf971c8c9b619abe8f..b4270e947a1e8999eb7cd482d7656edfb7290d4e 100644
--- a/include/linux/driverfs_fs.h
+++ b/include/linux/driverfs_fs.h
@@ -65,6 +65,4 @@ driverfs_create_symlink(struct driver_dir_entry * parent,
 extern void
 driverfs_remove_file(struct driver_dir_entry *, const char * name);
 
-extern int init_driverfs_fs(void);
-
 #endif /* _DDFS_H_ */