Commit 4278bccc authored by Patrick Mochel's avatar Patrick Mochel

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.
parent 67d93a0a
......@@ -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);
......@@ -56,6 +56,7 @@ struct bus_type {
char * name;
rwlock_t lock;
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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment