lkml.org 
[lkml]   [2002]   [Oct]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: [bk/patch] driver model update: device_unregister()

    ChangeSet@1.598, 2002-10-08 17:23:05-07:00, mochel@osdl.org
    driver model: and present field to struct device and implement device_unregister().

    device_unregister() is intended to be the complement of device_register(), and assumes
    most of the functionality of the current put_device(). It should be called by the bus
    driver when a device is physically removed from the system.

    It should _not_ be called from a driver's remove() method, as that remove() method is called
    via device_detach() in device_unregister().

    dev->present is used to flag the physical presence of the device. It is set when the device
    is registered, and cleared when unregistered. get_device() checks this flag, and returns
    a NULL pointer if cleared. This prevents anyone from obtaining a reference to a device
    that has been unregistered (removed), but not yet been freed (e.g. if someone else is
    holding a reference to it).

    put_device() BUG()s if dev->present is set. A device should be unregistered before it is
    freed. This will catch people doing it in the wrong order.

    diff -Nru a/drivers/base/core.c b/drivers/base/core.c
    --- a/drivers/base/core.c Tue Oct 8 17:55:22 2002
    +++ b/drivers/base/core.c Tue Oct 8 17:55:22 2002
    @@ -175,7 +175,7 @@
    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 @@
    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 @@
    */
    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 @@
    /* 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 @@
    core_initcall(device_init);

    EXPORT_SYMBOL(device_register);
    +EXPORT_SYMBOL(device_unregister);
    EXPORT_SYMBOL(get_device);
    EXPORT_SYMBOL(put_device);
    diff -Nru a/include/linux/device.h b/include/linux/device.h
    --- a/include/linux/device.h Tue Oct 8 17:55:22 2002
    +++ b/include/linux/device.h Tue Oct 8 17:55:22 2002
    @@ -289,6 +289,7 @@
    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 @@
    * 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 */

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-03-22 13:29    [W:0.025 / U:88.400 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site