Commit d745be1e authored by Patrick Mochel's avatar Patrick Mochel

Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-virgin

into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-core
parents 8e12e1f9 3c0405be
......@@ -175,7 +175,7 @@ int device_register(struct device *dev)
INIT_LIST_HEAD(&dev->intf_list);
spin_lock_init(&dev->lock);
atomic_set(&dev->refcount,2);
dev->present = 1;
spin_lock(&device_lock);
if (dev->parent) {
get_device_locked(dev->parent);
......@@ -219,7 +219,7 @@ int device_register(struct device *dev)
struct device * get_device_locked(struct device * dev)
{
struct device * ret = dev;
if (dev && atomic_read(&dev->refcount) > 0)
if (dev && dev->present && atomic_read(&dev->refcount) > 0)
atomic_inc(&dev->refcount);
else
ret = NULL;
......@@ -241,8 +241,35 @@ struct device * get_device(struct device * dev)
*/
void put_device(struct device * dev)
{
struct device * parent;
if (!atomic_dec_and_lock(&dev->refcount,&device_lock))
return;
parent = dev->parent;
dev->parent = NULL;
spin_unlock(&device_lock);
BUG_ON(dev->present);
if (dev->release)
dev->release(dev);
if (parent)
put_device(parent);
}
/**
* device_unregister - unlink device
* @dev: device going away
*
* The device has been removed from the system, so we disavow knowledge
* of it. It might not be the final reference to the device, so we mark
* it as !present, so no more references to it can be acquired.
* In the end, we decrement the final reference count for it.
*/
void device_unregister(struct device * dev)
{
spin_lock(&device_lock);
dev->present = 0;
list_del_init(&dev->node);
list_del_init(&dev->g_list);
list_del_init(&dev->bus_list);
......@@ -267,11 +294,7 @@ void put_device(struct device * dev)
/* remove the driverfs directory */
device_remove_dir(dev);
if (dev->release)
dev->release(dev);
if (dev->parent)
put_device(dev->parent);
put_device(dev);
}
static int __init device_init(void)
......@@ -287,5 +310,6 @@ static int __init device_init(void)
core_initcall(device_init);
EXPORT_SYMBOL(device_register);
EXPORT_SYMBOL(device_unregister);
EXPORT_SYMBOL(get_device);
EXPORT_SYMBOL(put_device);
......@@ -90,8 +90,7 @@ int device_create_file(struct device * dev, struct device_attribute * entry)
{
int error = -EINVAL;
if (dev) {
get_device(dev);
if (get_device(dev)) {
error = driverfs_create_file(&entry->attr,&dev->dir);
put_device(dev);
}
......
......@@ -1802,7 +1802,7 @@ static int idedisk_cleanup (ide_drive_t *drive)
{
struct gendisk *g = drive->disk;
put_device(&drive->disk->disk_dev);
device_unregister(&drive->disk->disk_dev);
if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
if (do_idedisk_flushcache(drive))
printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
......
......@@ -789,7 +789,7 @@ void usb_disconnect(struct usb_device **pdev)
struct usb_interface *interface = &dev->actconfig->interface[i];
/* remove this interface */
put_device(&interface->dev);
device_unregister(&interface->dev);
}
}
......@@ -797,7 +797,7 @@ void usb_disconnect(struct usb_device **pdev)
if (dev->devnum > 0) {
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
usbfs_remove_device(dev);
put_device(&dev->dev);
device_unregister(&dev->dev);
}
/* Decrement the reference count, it'll auto free everything when */
......
......@@ -289,6 +289,7 @@ struct device {
void *platform_data; /* Platform specific data (e.g. ACPI,
BIOS data relevant to device) */
u32 present;
u32 current_state; /* Current operating state. In
ACPI-speak, this is D0-D3, D0
being fully functional, and D3
......@@ -327,7 +328,7 @@ dev_set_drvdata (struct device *dev, void *data)
* High level routines for use by the bus drivers
*/
extern int device_register(struct device * dev);
extern void device_unregister(struct device * dev);
/* driverfs interface for exporting device attributes */
......
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