Commit 32d57b6c authored by Patrick Mochel's avatar Patrick Mochel

[PATCH] driver model updates (5/5)

Remove struct iobus.

There is a lot of duplication between struct device and struct iobus, both
in their members and the code in their interfaces. Waxing struct iobus
removes this duplication and makes things a bit simpler.
parent 99f6d9fd
......@@ -18,10 +18,7 @@
# define DBG(x...)
#endif
static struct iobus device_root = {
bus_id: "root",
name: "Logical System Root",
};
static struct device * device_root;
int (*platform_notify)(struct device * dev) = NULL;
int (*platform_notify_remove)(struct device * dev) = NULL;
......@@ -29,9 +26,6 @@ int (*platform_notify_remove)(struct device * dev) = NULL;
extern int device_make_dir(struct device * dev);
extern void device_remove_dir(struct device * dev);
extern int iobus_make_dir(struct iobus * iobus);
extern void iobus_remove_dir(struct iobus * iobus);
static spinlock_t device_lock;
/**
......@@ -48,19 +42,23 @@ int device_register(struct device *dev)
if (!dev || !strlen(dev->bus_id))
return -EINVAL;
BUG_ON(!dev->parent);
spin_lock(&device_lock);
INIT_LIST_HEAD(&dev->node);
INIT_LIST_HEAD(&dev->children);
spin_lock_init(&dev->lock);
atomic_set(&dev->refcount,2);
get_iobus(dev->parent);
list_add_tail(&dev->node,&dev->parent->devices);
if (dev != device_root) {
if (!dev->parent)
dev->parent = device_root;
get_device(dev->parent);
list_add_tail(&dev->node,&dev->parent->children);
}
spin_unlock(&device_lock);
DBG("DEV: registering device: ID = '%s', name = %s, parent = %s\n",
dev->bus_id, dev->name, parent->bus_id);
DBG("DEV: registering device: ID = '%s', name = %s\n",
dev->bus_id, dev->name);
if ((error = device_make_dir(dev)))
goto register_done;
......@@ -71,8 +69,8 @@ int device_register(struct device *dev)
register_done:
put_device(dev);
if (error)
put_iobus(dev->parent);
if (error && dev->parent)
put_device(dev->parent);
return error;
}
......@@ -101,9 +99,6 @@ void put_device(struct device * dev)
/* remove the driverfs directory */
device_remove_dir(dev);
if (dev->subordinate)
iobus_remove_dir(dev->subordinate);
/* Notify the platform of the removal, in case they
* need to do anything...
*/
......@@ -117,70 +112,18 @@ void put_device(struct device * dev)
if (dev->driver && dev->driver->remove)
dev->driver->remove(dev,REMOVE_FREE_RESOURCES);
put_iobus(dev->parent);
}
int iobus_register(struct iobus *bus)
{
int error;
if (!bus || !strlen(bus->bus_id))
return -EINVAL;
spin_lock(&device_lock);
atomic_set(&bus->refcount,2);
spin_lock_init(&bus->lock);
INIT_LIST_HEAD(&bus->node);
INIT_LIST_HEAD(&bus->devices);
INIT_LIST_HEAD(&bus->children);
if (bus != &device_root) {
if (!bus->parent)
bus->parent = &device_root;
get_iobus(bus->parent);
list_add_tail(&bus->node,&bus->parent->children);
}
spin_unlock(&device_lock);
DBG("DEV: registering bus. ID = '%s' name = '%s' parent = %p\n",
bus->bus_id,bus->name,bus->parent);
error = iobus_make_dir(bus);
put_iobus(bus);
if (error && bus->parent)
put_iobus(bus->parent);
return error;
}
/**
* iobus_unregister - remove bus and children from device tree
* @bus: pointer to bus structure
*
* Remove device from parent's list of children and decrement
* reference count on controlling device. That should take care of
* the rest of the cleanup.
*/
void put_iobus(struct iobus * iobus)
{
if (!atomic_dec_and_lock(&iobus->refcount,&device_lock))
return;
list_del_init(&iobus->node);
spin_unlock(&device_lock);
if (!list_empty(&iobus->devices) ||
!list_empty(&iobus->children))
BUG();
put_iobus(iobus->parent);
/* unregister itself */
put_device(iobus->self);
put_device(dev->parent);
}
static int __init device_init_root(void)
{
/* initialize parent bus lists */
return iobus_register(&device_root);
device_root = kmalloc(sizeof(*device_root),GFP_KERNEL);
if (!device_root)
return -ENOMEM;
memset(device_root,0,sizeof(*device_root));
strcpy(device_root->bus_id,"root");
strcpy(device_root->name,"System Root");
return device_register(device_root);
}
static int __init device_driver_init(void)
......@@ -212,5 +155,3 @@ subsys_initcall(device_driver_init);
EXPORT_SYMBOL(device_register);
EXPORT_SYMBOL(put_device);
EXPORT_SYMBOL(iobus_register);
EXPORT_SYMBOL(put_iobus);
......@@ -104,28 +104,6 @@ int device_make_dir(struct device * dev)
return 0;
}
void iobus_remove_dir(struct iobus * iobus)
{
if (iobus)
driverfs_remove_dir(&iobus->dir);
}
int iobus_make_dir(struct iobus * iobus)
{
struct driver_dir_entry * parent = NULL;
int error;
INIT_LIST_HEAD(&iobus->dir.files);
iobus->dir.mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO);
iobus->dir.name = iobus->bus_id;
if (iobus->parent)
parent = &iobus->parent->dir;
error = driverfs_create_dir(&iobus->dir,parent);
return error;
}
EXPORT_SYMBOL(device_create_file);
EXPORT_SYMBOL(device_remove_file);
......@@ -1086,13 +1086,7 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de
child->parent = parent;
child->ops = parent->ops;
child->sysdata = parent->sysdata;
/* init generic fields */
child->iobus.self = &dev->dev;
child->iobus.parent = &parent->iobus;
dev->dev.subordinate = &child->iobus;
strcpy(child->iobus.name,dev->dev.name);
child->dev = &dev->dev;
/*
* Set up the primary, secondary and subordinate
......@@ -1361,16 +1355,11 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
DBG("Scanning bus %02x\n", bus->number);
max = bus->secondary;
/* we should know for sure what the bus number is, so set the bus ID
* for the bus and make sure it's registered in the device tree */
sprintf(bus->iobus.bus_id,"pci%d",bus->number);
iobus_register(&bus->iobus);
/* Create a device template */
memset(&dev0, 0, sizeof(dev0));
dev0.bus = bus;
dev0.sysdata = bus->sysdata;
dev0.dev.parent = &bus->iobus;
dev0.dev.parent = bus->dev;
dev0.dev.driver = &pci_device_driver;
/* Go find them, Rover! */
......@@ -1430,9 +1419,11 @@ struct pci_bus * __devinit pci_alloc_primary_bus(int bus)
return NULL;
list_add_tail(&b->node, &pci_root_buses);
sprintf(b->iobus.bus_id,"pci%d",bus);
strcpy(b->iobus.name,"Host/PCI Bridge");
iobus_register(&b->iobus);
b->dev = kmalloc(sizeof(*(b->dev)),GFP_KERNEL);
memset(b->dev,0,sizeof(*(b->dev)));
sprintf(b->dev->bus_id,"pci%d",bus);
strcpy(b->dev->name,"Host/PCI Bridge");
device_register(b->dev);
b->number = b->secondary = bus;
b->resource[0] = &ioport_resource;
......
......@@ -66,10 +66,8 @@ struct device_driver {
struct device {
struct list_head node; /* node in sibling list */
struct iobus *parent; /* parent bus */
struct iobus *subordinate; /* only valid if this device is a
bridge device */
struct list_head children;
struct device * parent;
char name[DEVICE_NAME_SIZE]; /* descriptive ascii string */
char bus_id[BUS_ID_SIZE]; /* position on parent bus */
......@@ -113,36 +111,12 @@ struct iobus_driver {
int (*add_device) (struct iobus*, char*);
};
struct iobus {
spinlock_t lock; /* lock for bus */
atomic_t refcount;
struct list_head node; /* node in sibling list */
struct iobus *parent; /* parent bus */
struct list_head children; /* children buses */
struct list_head devices; /* children devices */
struct device *self; /* pointer to controlling device */
struct driver_dir_entry dir; /* driverfs directory */
char name[DEVICE_NAME_SIZE];
char bus_id[BUS_ID_SIZE];
struct iobus_driver *driver; /* bus operations */
};
static inline struct device *
list_to_dev(struct list_head *node)
{
return list_entry(node, struct device, node);
}
static inline struct iobus *
list_to_iobus(const struct list_head *node)
{
return list_entry(node, struct iobus, node);
}
/*
* High level routines for use by the bus drivers
*/
......@@ -189,22 +163,4 @@ static inline void get_device(struct device * dev)
extern void put_device(struct device * dev);
static inline void lock_iobus(struct iobus * iobus)
{
spin_lock(&iobus->lock);
}
static inline void unlock_iobus(struct iobus * iobus)
{
spin_unlock(&iobus->lock);
}
static inline void get_iobus(struct iobus * iobus)
{
BUG_ON(!atomic_read(&iobus->refcount));
atomic_inc(&iobus->refcount);
}
extern void put_iobus(struct iobus * iobus);
#endif /* _DEVICE_H_ */
......@@ -432,8 +432,7 @@ struct pci_bus {
unsigned char productver; /* product version */
unsigned char checksum; /* if zero - checksum passed */
unsigned char pad1;
struct iobus iobus; /* Generic device interface */
struct device * dev;
};
#define pci_bus_b(n) list_entry(n, struct pci_bus, node)
......
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