Commit fba46407 authored by Patrick Mochel's avatar Patrick Mochel

Driver model update:

Create global list in which all devices are inserted. Done by Kai Germaschewski.
parent e305166b
#undef DEBUG
#ifdef DEBUG
# define DBG(x...) printk(x)
#else
# define DBG(x...)
#endif
extern struct device device_root;
extern spinlock_t device_lock;
extern int device_make_dir(struct device * dev);
extern void device_remove_dir(struct device * dev);
...@@ -10,16 +10,9 @@ ...@@ -10,16 +10,9 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include "base.h"
#undef DEBUG struct device device_root = {
#ifdef DEBUG
# define DBG(x...) printk(x)
#else
# define DBG(x...)
#endif
static struct device device_root = {
bus_id: "root", bus_id: "root",
name: "System root", name: "System root",
}; };
...@@ -27,10 +20,7 @@ static struct device device_root = { ...@@ -27,10 +20,7 @@ static struct device device_root = {
int (*platform_notify)(struct device * dev) = NULL; int (*platform_notify)(struct device * dev) = NULL;
int (*platform_notify_remove)(struct device * dev) = NULL; int (*platform_notify_remove)(struct device * dev) = NULL;
extern int device_make_dir(struct device * dev); spinlock_t device_lock = SPIN_LOCK_UNLOCKED;
extern void device_remove_dir(struct device * dev);
static spinlock_t device_lock = SPIN_LOCK_UNLOCKED;
/** /**
* device_register - register a device * device_register - register a device
...@@ -39,10 +29,14 @@ static spinlock_t device_lock = SPIN_LOCK_UNLOCKED; ...@@ -39,10 +29,14 @@ static spinlock_t device_lock = SPIN_LOCK_UNLOCKED;
* First, make sure that the device has a parent, create * First, make sure that the device has a parent, create
* a directory for it, then add it to the parent's list of * a directory for it, then add it to the parent's list of
* children. * children.
*
* Maintains a global list of all devices, in depth-first ordering.
* The head for that list is device_root.g_list.
*/ */
int device_register(struct device *dev) int device_register(struct device *dev)
{ {
int error; int error;
struct device *prev_dev;
if (!dev || !strlen(dev->bus_id)) if (!dev || !strlen(dev->bus_id))
return -EINVAL; return -EINVAL;
...@@ -50,6 +44,7 @@ int device_register(struct device *dev) ...@@ -50,6 +44,7 @@ int device_register(struct device *dev)
spin_lock(&device_lock); spin_lock(&device_lock);
INIT_LIST_HEAD(&dev->node); INIT_LIST_HEAD(&dev->node);
INIT_LIST_HEAD(&dev->children); INIT_LIST_HEAD(&dev->children);
INIT_LIST_HEAD(&dev->g_list);
spin_lock_init(&dev->lock); spin_lock_init(&dev->lock);
atomic_set(&dev->refcount,2); atomic_set(&dev->refcount,2);
...@@ -57,6 +52,13 @@ int device_register(struct device *dev) ...@@ -57,6 +52,13 @@ int device_register(struct device *dev)
if (!dev->parent) if (!dev->parent)
dev->parent = &device_root; dev->parent = &device_root;
get_device(dev->parent); get_device(dev->parent);
if (list_empty(&dev->parent->children))
prev_dev = dev->parent;
else
prev_dev = list_entry(dev->parent->children.prev, struct device, node);
list_add(&dev->g_list, &prev_dev->g_list);
list_add_tail(&dev->node,&dev->parent->children); list_add_tail(&dev->node,&dev->parent->children);
} }
spin_unlock(&device_lock); spin_unlock(&device_lock);
...@@ -79,22 +81,15 @@ int device_register(struct device *dev) ...@@ -79,22 +81,15 @@ int device_register(struct device *dev)
} }
/** /**
* put_device - clean up device * put_device - decrement reference count, and clean up when it hits 0
* @dev: device in question * @dev: device in question
*
* Decrement reference count for device.
* If it hits 0, we need to clean it up.
* However, we may be here in interrupt context, and it may
* take some time to do proper clean up (removing files, calling
* back down to device to clean up everything it has).
* So, we remove it from its parent's list and add it to the list of
* devices to be cleaned up.
*/ */
void put_device(struct device * dev) void put_device(struct device * dev)
{ {
if (!atomic_dec_and_lock(&dev->refcount,&device_lock)) if (!atomic_dec_and_lock(&dev->refcount,&device_lock))
return; return;
list_del_init(&dev->node); list_del_init(&dev->node);
list_del_init(&dev->g_list);
spin_unlock(&device_lock); spin_unlock(&device_lock);
DBG("DEV: Unregistering device. ID = '%s', name = '%s'\n", DBG("DEV: Unregistering device. ID = '%s', name = '%s'\n",
......
...@@ -64,6 +64,7 @@ struct device_driver { ...@@ -64,6 +64,7 @@ struct device_driver {
}; };
struct device { struct device {
struct list_head g_list; /* node in depth-first order list */
struct list_head node; /* node in sibling list */ struct list_head node; /* node in sibling list */
struct list_head children; struct list_head children;
struct device * parent; struct device * parent;
...@@ -99,6 +100,12 @@ list_to_dev(struct list_head *node) ...@@ -99,6 +100,12 @@ list_to_dev(struct list_head *node)
return list_entry(node, struct device, node); return list_entry(node, struct device, node);
} }
static inline struct device *
g_list_to_dev(struct list_head *g_list)
{
return list_entry(g_list, struct device, g_list);
}
/* /*
* High level routines for use by the bus drivers * High level routines for use by the bus drivers
*/ */
......
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