lkml.org 
[lkml]   [2008]   [Jan]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    SubjectRe: [PATCH 1/4] PM: Introduce destroy_suspended_device()
    Date
    On Wednesday, 2 of January 2008, Rafael J. Wysocki wrote:
    > From: Rafael J. Wysocki <rjw@sisk.pl>
    >
    > It sometimes is necessary to destroy a device object during a suspend or
    > hibernation, but the PM core is supposed to control all device objects in that
    > cases. For this reason, it is necessary to introduce a mechanism allowing one
    > to ask the PM core to remove a device object corresponding to a suspended
    > device on one's behalf.
    >
    > Define function destroy_suspended_device() that will schedule the removal of
    > a device object corresponding to a suspended device by the PM core during the
    > subsequent resume.
    >
    > Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>

    Sorry, a small fix is needed for this patch. Namely, dpm_sysfs_remove(dev)
    should not be called by device_pm_schedule_removal(), because it will be called
    anyway from device_pm_remove() when the device object is finally unregistered
    (we're talking here about unlikely error paths only, but still).

    Corrected patch follows.

    Thanks,
    Rafael

    ---
    From: Rafael J. Wysocki <rjw@sisk.pl>

    It sometimes is necessary to destroy a device object during a suspend or
    hibernation, but the PM core is supposed to control all device objects in that
    cases. For this reason, it is necessary to introduce a mechanism allowing one
    to ask the PM core to remove a device object corresponding to a suspended
    device on one's behalf.

    Define function destroy_suspended_device() that will schedule the removal of
    a device object corresponding to a suspended device by the PM core during the
    subsequent resume.

    Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
    ---
    drivers/base/core.c | 44 +++++++++++++++++++++++++++++++++++++++-----
    drivers/base/power/main.c | 35 ++++++++++++++++++++++++++---------
    drivers/base/power/power.h | 1 +
    include/linux/device.h | 8 ++++++++
    4 files changed, 74 insertions(+), 14 deletions(-)

    Index: linux-2.6/drivers/base/core.c
    ===================================================================
    --- linux-2.6.orig/drivers/base/core.c
    +++ linux-2.6/drivers/base/core.c
    @@ -1156,14 +1156,11 @@ error:
    EXPORT_SYMBOL_GPL(device_create);

    /**
    - * device_destroy - removes a device that was created with device_create()
    + * find_device - finds a device that was created with device_create()
    * @class: pointer to the struct class that this device was registered with
    * @devt: the dev_t of the device that was previously registered
    - *
    - * This call unregisters and cleans up a device that was created with a
    - * call to device_create().
    */
    -void device_destroy(struct class *class, dev_t devt)
    +static struct device *find_device(struct class *class, dev_t devt)
    {
    struct device *dev = NULL;
    struct device *dev_tmp;
    @@ -1176,12 +1173,49 @@ void device_destroy(struct class *class,
    }
    }
    up(&class->sem);
    + return dev;
    +}

    +/**
    + * device_destroy - removes a device that was created with device_create()
    + * @class: pointer to the struct class that this device was registered with
    + * @devt: the dev_t of the device that was previously registered
    + *
    + * This call unregisters and cleans up a device that was created with a
    + * call to device_create().
    + */
    +void device_destroy(struct class *class, dev_t devt)
    +{
    + struct device *dev;
    +
    + dev = find_device(class, devt);
    if (dev)
    device_unregister(dev);
    }
    EXPORT_SYMBOL_GPL(device_destroy);

    +#ifdef CONFIG_PM_SLEEP
    +/**
    + * destroy_suspended_device - schedules the removal of a suspended device
    + * @class: pointer to the struct class that this device was registered with
    + * @devt: the dev_t of the device that was previously registered
    + *
    + * This call notifies the PM core of the necessity to unregister a suspended
    + * device created with a call to device_create() (devices cannot be
    + * unregistered directly while suspended, since the PM core controls them in
    + * that cases).
    + */
    +void destroy_suspended_device(struct class *class, dev_t devt)
    +{
    + struct device *dev;
    +
    + dev = find_device(class, devt);
    + if (dev)
    + device_pm_schedule_removal(dev);
    +}
    +EXPORT_SYMBOL_GPL(destroy_suspended_device);
    +#endif /* CONFIG_PM_SLEEP */
    +
    /**
    * device_rename - renames a device
    * @dev: the pointer to the struct device to be renamed
    Index: linux-2.6/include/linux/device.h
    ===================================================================
    --- linux-2.6.orig/include/linux/device.h
    +++ linux-2.6/include/linux/device.h
    @@ -521,6 +521,14 @@ extern struct device *device_create(stru
    dev_t devt, const char *fmt, ...)
    __attribute__((format(printf,4,5)));
    extern void device_destroy(struct class *cls, dev_t devt);
    +#ifdef CONFIG_PM_SLEEP
    +extern void destroy_suspended_device(struct class *cls, dev_t devt);
    +#else /* !CONFIG_PM_SLEEP */
    +static inline void destroy_suspended_device(struct class *cls, dev_t devt)
    +{
    + device_destroy(cls, devt);
    +}
    +#endif /* !CONFIG_PM_SLEEP */

    /*
    * Platform "fixup" functions - allow the platform to have their say
    Index: linux-2.6/drivers/base/power/power.h
    ===================================================================
    --- linux-2.6.orig/drivers/base/power/power.h
    +++ linux-2.6/drivers/base/power/power.h
    @@ -20,6 +20,7 @@ static inline struct device *to_device(s

    extern void device_pm_add(struct device *);
    extern void device_pm_remove(struct device *);
    +extern void device_pm_schedule_removal(struct device *);

    #else /* CONFIG_PM_SLEEP */

    Index: linux-2.6/drivers/base/power/main.c
    ===================================================================
    --- linux-2.6.orig/drivers/base/power/main.c
    +++ linux-2.6/drivers/base/power/main.c
    @@ -31,6 +31,7 @@
    LIST_HEAD(dpm_active);
    static LIST_HEAD(dpm_off);
    static LIST_HEAD(dpm_off_irq);
    +static LIST_HEAD(dpm_destroy);

    static DEFINE_MUTEX(dpm_mtx);
    static DEFINE_MUTEX(dpm_list_mtx);
    @@ -59,6 +60,16 @@ void device_pm_remove(struct device *dev
    mutex_unlock(&dpm_list_mtx);
    }

    +void device_pm_schedule_removal(struct device *dev)
    +{
    + pr_debug("PM: Removing info for %s:%s\n",
    + dev->bus ? dev->bus->name : "No Bus",
    + kobject_name(&dev->kobj));
    + mutex_lock(&dpm_list_mtx);
    + list_move_tail(&dev->power.entry, &dpm_destroy);
    + mutex_unlock(&dpm_list_mtx);
    +}
    +

    /*------------------------- Resume routines -------------------------*/

    @@ -113,11 +124,14 @@ static int resume_device_early(struct de
    return error;
    }

    -/*
    - * Resume the devices that have either not gone through
    - * the late suspend, or that did go through it but also
    - * went through the early resume
    +/**
    + * dpm_resume - Restore state of each device in system.
    + *
    + * Walk the dpm_off list, remove each entry, resume the device,
    + * then add it to the dpm_active list. Unregister devices scheduled for
    + * removal.
    */
    +
    static void dpm_resume(void)
    {
    mutex_lock(&dpm_list_mtx);
    @@ -134,14 +148,17 @@ static void dpm_resume(void)
    put_device(dev);
    }
    mutex_unlock(&dpm_list_mtx);
    -}
    + /* Unregister devices scheduled for removal */
    + while (!list_empty(&dpm_destroy)) {
    + struct list_head *entry = dpm_destroy.next;
    + struct device *dev = to_device(entry);

    + device_unregister(dev);
    + }
    +}

    /**
    - * device_resume - Restore state of each device in system.
    - *
    - * Walk the dpm_off list, remove each entry, resume the device,
    - * then add it to the dpm_active list.
    + * device_resume - Invoke dpm_resume() under dpm_mtx.
    */

    void device_resume(void)

    \
     
     \ /
      Last update: 2008-01-02 14:35    [W:4.752 / U:0.588 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site