summaryrefslogtreecommitdiff
path: root/drivers/base
diff options
context:
space:
mode:
authorPatrick Mochel <mochel@osdl.org>2002-10-15 20:54:20 -0700
committerPatrick Mochel <mochel@osdl.org>2002-10-15 20:54:20 -0700
commit4278bccc2d9707c9c4ee1769b464bffe4dfd820a (patch)
tree3e012877913aafa17597149206cc050c576ba995 /drivers/base
parent67d93a0ad7b87d740f25f93d12eb5d5e870d7030 (diff)
driver model: change bus refcounting scheme to match devices'.
Based on recent changes to device refcounting/unregistration. struct bus_type gets a ->present field, which is set when the bus is registered. bus_unregister() is added, which only clears ->present and calls put_bus(). get_bus() checks the ->present and returns NULL if clear. This allows all current references to buses to keep valid structures, while preventing any new references to the bus structure.
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/bus.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 7daffbfd9913..1343c64c5a38 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -136,12 +136,35 @@ void bus_remove_device(struct device * dev)
}
}
+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_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 +179,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 +194,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);