Commit bee01166 authored by Linus Torvalds's avatar Linus Torvalds Committed by Linus Torvalds

Merge bk://ldm.bkbits.net/linux-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 6c90d305 52d16b41
......@@ -5,6 +5,8 @@
* 2002 Open Source Development Lab
*/
#define DEBUG 0
#include <linux/device.h>
#include <linux/module.h>
#include <linux/slab.h>
......@@ -118,9 +120,8 @@ int driver_bind(struct device_driver * drv)
return bus_for_each_dev(drv->bus,drv,do_driver_bind);
}
static int do_driver_unbind(struct device * dev, void * data)
static int do_driver_unbind(struct device * dev, struct device_driver * drv)
{
struct device_driver * drv = (struct device_driver *)data;
lock_device(dev);
if (dev->driver == drv) {
dev->driver = NULL;
......@@ -134,7 +135,31 @@ static int do_driver_unbind(struct device * dev, void * data)
void driver_unbind(struct device_driver * drv)
{
driver_for_each_dev(drv,drv,do_driver_unbind);
struct device * next;
struct device * dev = NULL;
struct list_head * node;
int error = 0;
read_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);
if (dev)
put_device(dev);
dev = next;
if ((error = do_driver_unbind(dev,drv))) {
put_device(dev);
break;
}
read_lock(&drv->lock);
node = dev->driver_list.next;
}
read_unlock(&drv->lock);
if (dev)
put_device(dev);
}
/**
......@@ -178,8 +203,8 @@ int device_register(struct device *dev)
}
spin_unlock(&device_lock);
DBG("DEV: registering device: ID = '%s', name = %s\n",
dev->bus_id, dev->name);
pr_debug("DEV: registering device: ID = '%s', name = %s\n",
dev->bus_id, dev->name);
if ((error = device_make_dir(dev)))
goto register_done;
......@@ -212,8 +237,8 @@ void put_device(struct device * dev)
list_del_init(&dev->g_list);
spin_unlock(&device_lock);
DBG("DEV: Unregistering device. ID = '%s', name = '%s'\n",
dev->bus_id,dev->name);
pr_debug("DEV: Unregistering device. ID = '%s', name = '%s'\n",
dev->bus_id,dev->name);
/* Notify the platform of the removal, in case they
* need to do anything...
......
......@@ -3,6 +3,8 @@
*
*/
#define DEBUG 0
#include <linux/device.h>
#include <linux/module.h>
#include <linux/errno.h>
......@@ -67,6 +69,7 @@ int driver_register(struct device_driver * drv)
get_bus(drv->bus);
atomic_set(&drv->refcount,2);
rwlock_init(&drv->lock);
INIT_LIST_HEAD(&drv->devices);
write_lock(&drv->bus->lock);
list_add(&drv->bus_list,&drv->bus->drivers);
write_unlock(&drv->bus->lock);
......@@ -76,16 +79,8 @@ int driver_register(struct device_driver * drv)
return 0;
}
/**
* put_driver - decrement driver's refcount and clean up if necessary
* @drv: driver in question
*/
void put_driver(struct device_driver * drv)
static void __remove_driver(struct device_driver * drv)
{
if (!atomic_dec_and_lock(&drv->refcount,&device_lock))
return;
spin_unlock(&device_lock);
if (drv->bus) {
pr_debug("Unregistering driver '%s' from bus '%s'\n",drv->name,drv->bus->name);
......@@ -101,6 +96,28 @@ void put_driver(struct device_driver * drv)
drv->release(drv);
}
void remove_driver(struct device_driver * drv)
{
spin_lock(&device_lock);
atomic_set(&drv->refcount,0);
spin_unlock(&device_lock);
__remove_driver(drv);
}
/**
* put_driver - decrement driver's refcount and clean up if necessary
* @drv: driver in question
*/
void put_driver(struct device_driver * drv)
{
if (!atomic_dec_and_lock(&drv->refcount,&device_lock))
return;
spin_unlock(&device_lock);
__remove_driver(drv);
}
EXPORT_SYMBOL(driver_for_each_dev);
EXPORT_SYMBOL(driver_register);
EXPORT_SYMBOL(put_driver);
EXPORT_SYMBOL(remove_driver);
......@@ -38,23 +38,35 @@ pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev)
static int pci_device_probe(struct device * dev)
{
int error = 0;
struct pci_driver * drv = list_entry(dev->driver,struct pci_driver,driver);
struct pci_dev * pci_dev = list_entry(dev,struct pci_dev,dev);
if (drv->probe)
error = drv->probe(pci_dev,drv->id_table);
return error > 0 ? 0 : -ENODEV;
struct pci_driver *drv;
struct pci_dev *pci_dev;
drv = list_entry(dev->driver, struct pci_driver, driver);
pci_dev = list_entry(dev, struct pci_dev, dev);
if (drv->probe) {
const struct pci_device_id *id;
id = pci_match_device(drv->id_table, pci_dev);
if (id)
error = drv->probe(pci_dev, id);
if (error >= 0) {
pci_dev->driver = drv;
error = 0;
}
}
return error;
}
static int pci_device_remove(struct device * dev)
{
struct pci_dev * pci_dev = list_entry(dev,struct pci_dev,dev);
struct pci_driver * drv = pci_dev->driver;
if (dev->driver) {
struct pci_driver * drv = list_entry(dev->driver,struct pci_driver,driver);
if (drv) {
if (drv->remove)
drv->remove(pci_dev);
pci_dev->driver = NULL;
}
return 0;
}
......@@ -124,7 +136,7 @@ pci_register_driver(struct pci_driver *drv)
void
pci_unregister_driver(struct pci_driver *drv)
{
put_driver(&drv->driver);
remove_driver(&drv->driver);
}
static struct pci_driver pci_compat_driver = {
......
......@@ -118,6 +118,7 @@ static inline struct device_driver * get_driver(struct device_driver * drv)
}
extern void put_driver(struct device_driver * drv);
extern void remove_driver(struct device_driver * drv);
extern int driver_for_each_dev(struct device_driver * drv, void * data,
int (*callback)(struct device * dev, 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