Commit cec06af8 authored by Patrick Mochel's avatar Patrick Mochel Committed by Patrick Mochel

Merge master.kernel.org:/home/mochel/BK/linux-2.5-linus

into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-linus
parents cd350717 b1d0e423
......@@ -18,5 +18,5 @@ extern void device_remove_dir(struct device * dev);
extern int device_bus_link(struct device * dev);
extern int driver_bind(struct device_driver * drv);
extern void driver_unbind(struct device_driver * drv);
extern int driver_attach(struct device_driver * drv);
extern void driver_detach(struct device_driver * drv);
......@@ -167,12 +167,13 @@ static int bus_make_dir(struct bus_type * bus)
int bus_register(struct bus_type * bus)
{
spin_lock(&device_lock);
rwlock_init(&bus->lock);
INIT_LIST_HEAD(&bus->devices);
INIT_LIST_HEAD(&bus->drivers);
list_add_tail(&bus->node,&bus_driver_list);
atomic_set(&bus->refcount,2);
spin_lock(&device_lock);
list_add_tail(&bus->node,&bus_driver_list);
spin_unlock(&device_lock);
pr_debug("bus type '%s' registered\n",bus->name);
......
......@@ -31,7 +31,7 @@ spinlock_t device_lock = SPIN_LOCK_UNLOCKED;
* @dev: device
* @drv: driver
*
* We're here because the bus's bind callback returned success for this
* We're here because the bus's match callback returned success for this
* pair. We call the driver's probe callback to verify they're really a
* match made in heaven.
*
......@@ -67,60 +67,71 @@ static int found_match(struct device * dev, struct device_driver * drv)
}
/**
* bind_device - try to associated device with a driver
* device_attach - try to associated device with a driver
* @drv: current driver to try
* @data: device in disguise
*
* This function is used as a callback to bus_for_each_drv.
* It calls the bus's ::bind callback to check if the driver supports
* It calls the bus's match callback to check if the driver supports
* the device. If so, it calls the found_match() function above to
* take care of all the details.
*/
static int do_device_bind(struct device_driver * drv, void * data)
static int do_device_attach(struct device_driver * drv, void * data)
{
struct device * dev = (struct device *)data;
int error = 0;
if (!dev->driver) {
if (drv->bus->bind && drv->bus->bind(dev,drv))
if (drv->bus->match && drv->bus->match(dev,drv))
error = found_match(dev,drv);
}
return error;
}
static int device_bind(struct device * dev)
static int device_attach(struct device * dev)
{
int error = 0;
if (dev->bus)
error = bus_for_each_drv(dev->bus,dev,do_device_bind);
error = bus_for_each_drv(dev->bus,dev,do_device_attach);
return error;
}
static void device_unbind(struct device * dev)
static void device_detach(struct device * dev)
{
/* unbind from driver */
if (dev->driver && dev->driver->remove)
if (dev->driver) {
write_lock(&dev->driver->lock);
list_del_init(&dev->driver_list);
write_unlock(&dev->driver->lock);
lock_device(dev);
dev->driver = NULL;
unlock_device(dev);
/* detach from driver */
if (dev->driver->remove)
dev->driver->remove(dev);
put_driver(dev->driver);
}
}
static int do_driver_bind(struct device * dev, void * data)
static int do_driver_attach(struct device * dev, void * data)
{
struct device_driver * drv = (struct device_driver *)data;
int error = 0;
if (!dev->driver) {
if (dev->bus->bind && dev->bus->bind(dev,drv))
if (dev->bus->match && dev->bus->match(dev,drv))
error = found_match(dev,drv);
}
return error;
}
int driver_bind(struct device_driver * drv)
int driver_attach(struct device_driver * drv)
{
return bus_for_each_dev(drv->bus,drv,do_driver_bind);
return bus_for_each_dev(drv->bus,drv,do_driver_attach);
}
static int do_driver_unbind(struct device * dev, struct device_driver * drv)
static int do_driver_detach(struct device * dev, struct device_driver * drv)
{
lock_device(dev);
if (dev->driver == drv) {
......@@ -133,31 +144,32 @@ static int do_driver_unbind(struct device * dev, struct device_driver * drv)
return 0;
}
void driver_unbind(struct device_driver * drv)
void driver_detach(struct device_driver * drv)
{
struct device * next;
struct device * dev = NULL;
struct list_head * node;
int error = 0;
read_lock(&drv->lock);
write_lock(&drv->lock);
node = drv->devices.next;
while (node != &drv->devices) {
next = list_entry(node,struct device,driver_list);
get_device(next);
read_unlock(&drv->lock);
list_del_init(&next->driver_list);
write_unlock(&drv->lock);
if (dev)
put_device(dev);
dev = next;
if ((error = do_driver_unbind(dev,drv))) {
if ((error = do_driver_detach(dev,drv))) {
put_device(dev);
break;
}
read_lock(&drv->lock);
node = dev->driver_list.next;
write_lock(&drv->lock);
node = drv->devices.next;
}
read_unlock(&drv->lock);
write_unlock(&drv->lock);
if (dev)
put_device(dev);
}
......@@ -181,13 +193,13 @@ int device_register(struct device *dev)
if (!dev || !strlen(dev->bus_id))
return -EINVAL;
spin_lock(&device_lock);
INIT_LIST_HEAD(&dev->node);
INIT_LIST_HEAD(&dev->children);
INIT_LIST_HEAD(&dev->g_list);
spin_lock_init(&dev->lock);
atomic_set(&dev->refcount,2);
spin_lock(&device_lock);
if (dev != &device_root) {
if (!dev->parent)
dev->parent = &device_root;
......@@ -212,7 +224,7 @@ int device_register(struct device *dev)
bus_add_device(dev);
/* bind to driver */
device_bind(dev);
device_attach(dev);
/* notify platform of device entry */
if (platform_notify)
......@@ -246,7 +258,7 @@ void put_device(struct device * dev)
if (platform_notify_remove)
platform_notify_remove(dev);
device_unbind(dev);
device_detach(dev);
bus_remove_device(dev);
/* remove the driverfs directory */
......
......@@ -74,33 +74,27 @@ int driver_register(struct device_driver * drv)
list_add(&drv->bus_list,&drv->bus->drivers);
write_unlock(&drv->bus->lock);
driver_make_dir(drv);
driver_bind(drv);
driver_attach(drv);
put_driver(drv);
return 0;
}
static void __remove_driver(struct device_driver * drv)
{
if (drv->bus) {
pr_debug("Unregistering driver '%s' from bus '%s'\n",drv->name,drv->bus->name);
driver_unbind(drv);
write_lock(&drv->bus->lock);
list_del_init(&drv->bus_list);
write_unlock(&drv->bus->lock);
driver_detach(drv);
driverfs_remove_dir(&drv->dir);
put_bus(drv->bus);
}
if (drv->release)
drv->release(drv);
put_bus(drv->bus);
}
void remove_driver(struct device_driver * drv)
{
spin_lock(&device_lock);
write_lock(&drv->bus->lock);
atomic_set(&drv->refcount,0);
spin_unlock(&device_lock);
list_del_init(&drv->bus_list);
write_unlock(&drv->bus->lock);
__remove_driver(drv);
}
......@@ -110,10 +104,13 @@ void remove_driver(struct device_driver * drv)
*/
void put_driver(struct device_driver * drv)
{
if (!atomic_dec_and_lock(&drv->refcount,&device_lock))
write_lock(&drv->bus->lock);
if (!atomic_dec_and_test(&drv->refcount)) {
write_unlock(&drv->bus->lock);
return;
spin_unlock(&device_lock);
}
list_del_init(&drv->bus_list);
write_unlock(&drv->bus->lock);
__remove_driver(drv);
}
......
......@@ -165,7 +165,7 @@ pci_dev_driver(const struct pci_dev *dev)
}
/**
* pci_bus_bind - Tell if a PCI device structure has a matching PCI device id structure
* pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure
* @ids: array of PCI device id structures to search in
* @dev: the PCI device structure to match against
*
......@@ -173,7 +173,7 @@ pci_dev_driver(const struct pci_dev *dev)
* system is in its list of supported devices.Returns the matching
* pci_device_id structure or %NULL if there is no match.
*/
static int pci_bus_bind(struct device * dev, struct device_driver * drv)
static int pci_bus_match(struct device * dev, struct device_driver * drv)
{
struct pci_dev * pci_dev = list_entry(dev, struct pci_dev, dev);
struct pci_driver * pci_drv = list_entry(drv,struct pci_driver,driver);
......@@ -196,7 +196,7 @@ static int pci_bus_bind(struct device * dev, struct device_driver * drv)
struct bus_type pci_bus_type = {
name: "pci",
bind: pci_bus_bind,
match: pci_bus_match,
};
static int __init pci_driver_init(void)
......
......@@ -64,7 +64,7 @@ struct bus_type {
struct driver_dir_entry device_dir;
struct driver_dir_entry driver_dir;
int (*bind) (struct device * dev, struct device_driver * drv);
int (*match) (struct device * dev, struct device_driver * drv);
};
......
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