LKML Archive on lore.kernel.org help / color / mirror / Atom feed
* [PATCH 0/3] PM core fixes @ 2008-03-11 23:55 Rafael J. Wysocki 2008-03-11 23:57 ` [PATCH 1/3] PM: Handle device registrations during suspend/resume Rafael J. Wysocki ` (2 more replies) 0 siblings, 3 replies; 10+ messages in thread From: Rafael J. Wysocki @ 2008-03-11 23:55 UTC (permalink / raw) To: Greg KH Cc: Alan Stern, Andrew Morton, David Brownell, LKML, Pavel Machek, pm list Hi Greg, The following series of patches contains some fixes of the PM core related to the suspending and resuming of devices. All of the details are (hopefully) described in the patches' changelogs. These patches are targeted at 2.6.26, but we (the authors) would like them to get as much linux-next and -mm testing as possible, so please add them to your queue. Thanks, Rafael -- "Premature optimization is the root of all evil." - Donald Knuth ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/3] PM: Handle device registrations during suspend/resume 2008-03-11 23:55 [PATCH 0/3] PM core fixes Rafael J. Wysocki @ 2008-03-11 23:57 ` Rafael J. Wysocki 2008-03-13 8:37 ` Pavel Machek 2008-03-13 20:54 ` patch pm-handle-device-registrations-during-suspend-resume.patch added to gregkh-2.6 tree gregkh 2008-03-11 23:59 ` [PATCH 2/3] Driver core: Call device_pm_add() after bus_add_device() in device_add() Rafael J. Wysocki 2008-03-12 0:01 ` [PATCH 3/3] PM: make wakeup flags available whenever CONFIG_PM is set Rafael J. Wysocki 2 siblings, 2 replies; 10+ messages in thread From: Rafael J. Wysocki @ 2008-03-11 23:57 UTC (permalink / raw) To: Greg KH Cc: Alan Stern, Andrew Morton, David Brownell, LKML, Pavel Machek, pm list From: Rafael J. Wysocki <rjw@sisk.pl> Modify the PM core to protect its data structures, specifically the dpm_active list, from being corrupted if a child of the currently suspending device is registered concurrently with its ->suspend() callback. In that case, since the new device (the child) is added to dpm_active after its parent, the PM core will attempt to suspend it after the parent, which is wrong. Introduce a new member of struct dev_pm_info, called 'sleeping', and use it to check if the parent of the device being added to dpm_active has been suspended, in which case the device registration fails. Also, use 'sleeping' for checking if the ordering of devices on dpm_active is correct. Introduce variable 'all_sleeping' that will be set to 'true' once all devices have been suspended and make new device registrations fail until 'all_sleeping' is reset to 'false', in order to avoid having unsuspended devices around while the system is going into a sleep state. Remove pm_sleep_rwsem which is not necessary any more. Special thanks to Alan Stern for discussions and suggestions that lead to the creation of this patch. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> --- Documentation/power/devices.txt | 5 +++ drivers/base/core.c | 6 +++- drivers/base/power/main.c | 57 ++++++++++++++++++---------------------- drivers/base/power/power.h | 23 ++-------------- include/linux/pm.h | 1 5 files changed, 40 insertions(+), 52 deletions(-) Index: linux-2.6/include/linux/pm.h =================================================================== --- linux-2.6.orig/include/linux/pm.h +++ linux-2.6/include/linux/pm.h @@ -183,6 +183,7 @@ typedef struct pm_message { struct dev_pm_info { pm_message_t power_state; unsigned can_wakeup:1; + bool sleeping:1; /* Owned by the PM core */ #ifdef CONFIG_PM_SLEEP unsigned should_wakeup:1; struct list_head entry; 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 @@ -54,7 +54,8 @@ static LIST_HEAD(dpm_destroy); static DEFINE_MUTEX(dpm_list_mtx); -static DECLARE_RWSEM(pm_sleep_rwsem); +/* 'true' if all devices have been suspended, protected by dpm_list_mtx */ +static bool all_sleeping; int (*platform_enable_wakeup)(struct device *dev, int is_on); @@ -62,14 +63,28 @@ int (*platform_enable_wakeup)(struct dev * device_pm_add - add a device to the list of active devices * @dev: Device to be added to the list */ -void device_pm_add(struct device *dev) +int device_pm_add(struct device *dev) { + int error = 0; + pr_debug("PM: Adding info for %s:%s\n", dev->bus ? dev->bus->name : "No Bus", kobject_name(&dev->kobj)); mutex_lock(&dpm_list_mtx); - list_add_tail(&dev->power.entry, &dpm_active); + if ((dev->parent && dev->parent->power.sleeping) || all_sleeping) { + if (dev->parent->power.sleeping) + dev_warn(dev, + "parent %s is sleeping, will not add\n", + dev->parent->bus_id); + else + dev_warn(dev, "devices are sleeping, will not add\n"); + WARN_ON(true); + error = -EBUSY; + } else { + list_add_tail(&dev->power.entry, &dpm_active); + } mutex_unlock(&dpm_list_mtx); + return error; } /** @@ -107,32 +122,6 @@ void device_pm_schedule_removal(struct d } EXPORT_SYMBOL_GPL(device_pm_schedule_removal); -/** - * pm_sleep_lock - mutual exclusion for registration and suspend - * - * Returns 0 if no suspend is underway and device registration - * may proceed, otherwise -EBUSY. - */ -int pm_sleep_lock(void) -{ - if (down_read_trylock(&pm_sleep_rwsem)) - return 0; - - return -EBUSY; -} - -/** - * pm_sleep_unlock - mutual exclusion for registration and suspend - * - * This routine undoes the effect of device_pm_add_lock - * when a device's registration is complete. - */ -void pm_sleep_unlock(void) -{ - up_read(&pm_sleep_rwsem); -} - - /*------------------------- Resume routines -------------------------*/ /** @@ -242,11 +231,13 @@ static int resume_device(struct device * static void dpm_resume(void) { mutex_lock(&dpm_list_mtx); + all_sleeping = false; while(!list_empty(&dpm_off)) { struct list_head *entry = dpm_off.next; struct device *dev = to_device(entry); list_move_tail(entry, &dpm_active); + dev->power.sleeping = false; mutex_unlock(&dpm_list_mtx); resume_device(dev); mutex_lock(&dpm_list_mtx); @@ -285,7 +276,6 @@ void device_resume(void) might_sleep(); dpm_resume(); unregister_dropped_devices(); - up_write(&pm_sleep_rwsem); } EXPORT_SYMBOL_GPL(device_resume); @@ -426,6 +416,9 @@ static int dpm_suspend(pm_message_t stat struct list_head *entry = dpm_active.prev; struct device *dev = to_device(entry); + WARN_ON(dev->parent && dev->parent->power.sleeping); + + dev->power.sleeping = true; mutex_unlock(&dpm_list_mtx); error = suspend_device(dev, state); mutex_lock(&dpm_list_mtx); @@ -437,11 +430,14 @@ static int dpm_suspend(pm_message_t stat (error == -EAGAIN ? " (please convert to suspend_late)" : "")); + dev->power.sleeping = false; break; } if (!list_empty(&dev->power.entry)) list_move(&dev->power.entry, &dpm_off); } + if (!error) + all_sleeping = true; mutex_unlock(&dpm_list_mtx); return error; @@ -459,7 +455,6 @@ int device_suspend(pm_message_t state) int error; might_sleep(); - down_write(&pm_sleep_rwsem); error = dpm_suspend(state); if (error) device_resume(); 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 @@ -11,30 +11,13 @@ static inline struct device *to_device(s return container_of(entry, struct device, power.entry); } -extern void device_pm_add(struct device *); +extern int device_pm_add(struct device *); extern void device_pm_remove(struct device *); -extern int pm_sleep_lock(void); -extern void pm_sleep_unlock(void); #else /* CONFIG_PM_SLEEP */ - -static inline void device_pm_add(struct device *dev) -{ -} - -static inline void device_pm_remove(struct device *dev) -{ -} - -static inline int pm_sleep_lock(void) -{ - return 0; -} - -static inline void pm_sleep_unlock(void) -{ -} +static inline int device_pm_add(struct device *dev) { return 0; } +static inline void device_pm_remove(struct device *dev) {} #endif Index: linux-2.6/drivers/base/core.c =================================================================== --- linux-2.6.orig/drivers/base/core.c +++ linux-2.6/drivers/base/core.c @@ -815,7 +815,11 @@ int device_add(struct device *dev) error = dpm_sysfs_add(dev); if (error) goto PMError; - device_pm_add(dev); + error = device_pm_add(dev); + if (error) { + dpm_sysfs_remove(dev); + goto PMError; + } error = bus_add_device(dev); if (error) goto BusError; Index: linux-2.6/Documentation/power/devices.txt =================================================================== --- linux-2.6.orig/Documentation/power/devices.txt +++ linux-2.6/Documentation/power/devices.txt @@ -196,6 +196,11 @@ its parent; and can't be removed or susp The policy is that the device tree should match hardware bus topology. (Or at least the control bus, for devices which use multiple busses.) +In particular, this means that a device registration may fail if the parent of +the device is suspending (ie. has been chosen by the PM core as the next +device to suspend) or has already suspended, as well as after all of the other +devices have been suspended. Device drivers must be prepared to cope with such +situations. Suspending Devices ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/3] PM: Handle device registrations during suspend/resume 2008-03-11 23:57 ` [PATCH 1/3] PM: Handle device registrations during suspend/resume Rafael J. Wysocki @ 2008-03-13 8:37 ` Pavel Machek 2008-03-13 20:54 ` patch pm-handle-device-registrations-during-suspend-resume.patch added to gregkh-2.6 tree gregkh 1 sibling, 0 replies; 10+ messages in thread From: Pavel Machek @ 2008-03-13 8:37 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Greg KH, Alan Stern, Andrew Morton, David Brownell, LKML, pm list On Wed 2008-03-12 00:57:22, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki <rjw@sisk.pl> > > Modify the PM core to protect its data structures, specifically the > dpm_active list, from being corrupted if a child of the currently > suspending device is registered concurrently with its ->suspend() > callback. In that case, since the new device (the child) is added > to dpm_active after its parent, the PM core will attempt to > suspend it after the parent, which is wrong. > > Introduce a new member of struct dev_pm_info, called 'sleeping', > and use it to check if the parent of the device being added to > dpm_active has been suspended, in which case the device registration > fails. Also, use 'sleeping' for checking if the ordering of devices > on dpm_active is correct. > > Introduce variable 'all_sleeping' that will be set to 'true' once all > devices have been suspended and make new device registrations fail > until 'all_sleeping' is reset to 'false', in order to avoid having > unsuspended devices around while the system is going into a sleep state. > > Remove pm_sleep_rwsem which is not necessary any more. > > Special thanks to Alan Stern for discussions and suggestions that > lead to the creation of this patch. > > Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> ACK. -- (english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html ^ permalink raw reply [flat|nested] 10+ messages in thread
* patch pm-handle-device-registrations-during-suspend-resume.patch added to gregkh-2.6 tree 2008-03-11 23:57 ` [PATCH 1/3] PM: Handle device registrations during suspend/resume Rafael J. Wysocki 2008-03-13 8:37 ` Pavel Machek @ 2008-03-13 20:54 ` gregkh 1 sibling, 0 replies; 10+ messages in thread From: gregkh @ 2008-03-13 20:54 UTC (permalink / raw) To: rjw, akpm, david-b, greg, gregkh, linux-kernel, linux-pm, pavel, stern This is a note to let you know that I've just added the patch titled Subject: PM: Handle device registrations during suspend/resume to my gregkh-2.6 tree. Its filename is pm-handle-device-registrations-during-suspend-resume.patch This tree can be found at http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/ >From rjw@sisk.pl Thu Mar 13 13:44:50 2008 From: "Rafael J. Wysocki" <rjw@sisk.pl> Date: Wed, 12 Mar 2008 00:57:22 +0100 Subject: PM: Handle device registrations during suspend/resume To: Greg KH <greg@kroah.com> Cc: Alan Stern <stern@rowland.harvard.edu>, Andrew Morton <akpm@linux-foundation.org>, David Brownell <david-b@pacbell.net>, LKML <linux-kernel@vger.kernel.org>, Pavel Machek <pavel@ucw.cz>, pm list <linux-pm@lists.linux-foundation.org> Message-ID: <200803120057.23101.rjw@sisk.pl> Content-Disposition: inline From: Rafael J. Wysocki <rjw@sisk.pl> Modify the PM core to protect its data structures, specifically the dpm_active list, from being corrupted if a child of the currently suspending device is registered concurrently with its ->suspend() callback. In that case, since the new device (the child) is added to dpm_active after its parent, the PM core will attempt to suspend it after the parent, which is wrong. Introduce a new member of struct dev_pm_info, called 'sleeping', and use it to check if the parent of the device being added to dpm_active has been suspended, in which case the device registration fails. Also, use 'sleeping' for checking if the ordering of devices on dpm_active is correct. Introduce variable 'all_sleeping' that will be set to 'true' once all devices have been suspended and make new device registrations fail until 'all_sleeping' is reset to 'false', in order to avoid having unsuspended devices around while the system is going into a sleep state. Remove pm_sleep_rwsem which is not necessary any more. Special thanks to Alan Stern for discussions and suggestions that lead to the creation of this patch. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- Documentation/power/devices.txt | 5 +++ drivers/base/core.c | 6 +++- drivers/base/power/main.c | 57 ++++++++++++++++++---------------------- drivers/base/power/power.h | 23 ++-------------- include/linux/pm.h | 1 5 files changed, 40 insertions(+), 52 deletions(-) --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt @@ -196,6 +196,11 @@ its parent; and can't be removed or susp The policy is that the device tree should match hardware bus topology. (Or at least the control bus, for devices which use multiple busses.) +In particular, this means that a device registration may fail if the parent of +the device is suspending (ie. has been chosen by the PM core as the next +device to suspend) or has already suspended, as well as after all of the other +devices have been suspended. Device drivers must be prepared to cope with such +situations. Suspending Devices --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -821,7 +821,11 @@ int device_add(struct device *dev) error = dpm_sysfs_add(dev); if (error) goto PMError; - device_pm_add(dev); + error = device_pm_add(dev); + if (error) { + dpm_sysfs_remove(dev); + goto PMError; + } error = bus_add_device(dev); if (error) goto BusError; --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -54,7 +54,8 @@ static LIST_HEAD(dpm_destroy); static DEFINE_MUTEX(dpm_list_mtx); -static DECLARE_RWSEM(pm_sleep_rwsem); +/* 'true' if all devices have been suspended, protected by dpm_list_mtx */ +static bool all_sleeping; int (*platform_enable_wakeup)(struct device *dev, int is_on); @@ -62,14 +63,28 @@ int (*platform_enable_wakeup)(struct dev * device_pm_add - add a device to the list of active devices * @dev: Device to be added to the list */ -void device_pm_add(struct device *dev) +int device_pm_add(struct device *dev) { + int error = 0; + pr_debug("PM: Adding info for %s:%s\n", dev->bus ? dev->bus->name : "No Bus", kobject_name(&dev->kobj)); mutex_lock(&dpm_list_mtx); - list_add_tail(&dev->power.entry, &dpm_active); + if ((dev->parent && dev->parent->power.sleeping) || all_sleeping) { + if (dev->parent->power.sleeping) + dev_warn(dev, + "parent %s is sleeping, will not add\n", + dev->parent->bus_id); + else + dev_warn(dev, "devices are sleeping, will not add\n"); + WARN_ON(true); + error = -EBUSY; + } else { + list_add_tail(&dev->power.entry, &dpm_active); + } mutex_unlock(&dpm_list_mtx); + return error; } /** @@ -107,32 +122,6 @@ void device_pm_schedule_removal(struct d } EXPORT_SYMBOL_GPL(device_pm_schedule_removal); -/** - * pm_sleep_lock - mutual exclusion for registration and suspend - * - * Returns 0 if no suspend is underway and device registration - * may proceed, otherwise -EBUSY. - */ -int pm_sleep_lock(void) -{ - if (down_read_trylock(&pm_sleep_rwsem)) - return 0; - - return -EBUSY; -} - -/** - * pm_sleep_unlock - mutual exclusion for registration and suspend - * - * This routine undoes the effect of device_pm_add_lock - * when a device's registration is complete. - */ -void pm_sleep_unlock(void) -{ - up_read(&pm_sleep_rwsem); -} - - /*------------------------- Resume routines -------------------------*/ /** @@ -242,11 +231,13 @@ static int resume_device(struct device * static void dpm_resume(void) { mutex_lock(&dpm_list_mtx); + all_sleeping = false; while(!list_empty(&dpm_off)) { struct list_head *entry = dpm_off.next; struct device *dev = to_device(entry); list_move_tail(entry, &dpm_active); + dev->power.sleeping = false; mutex_unlock(&dpm_list_mtx); resume_device(dev); mutex_lock(&dpm_list_mtx); @@ -285,7 +276,6 @@ void device_resume(void) might_sleep(); dpm_resume(); unregister_dropped_devices(); - up_write(&pm_sleep_rwsem); } EXPORT_SYMBOL_GPL(device_resume); @@ -421,6 +411,9 @@ static int dpm_suspend(pm_message_t stat struct list_head *entry = dpm_active.prev; struct device *dev = to_device(entry); + WARN_ON(dev->parent && dev->parent->power.sleeping); + + dev->power.sleeping = true; mutex_unlock(&dpm_list_mtx); error = suspend_device(dev, state); mutex_lock(&dpm_list_mtx); @@ -432,11 +425,14 @@ static int dpm_suspend(pm_message_t stat (error == -EAGAIN ? " (please convert to suspend_late)" : "")); + dev->power.sleeping = false; break; } if (!list_empty(&dev->power.entry)) list_move(&dev->power.entry, &dpm_off); } + if (!error) + all_sleeping = true; mutex_unlock(&dpm_list_mtx); return error; @@ -454,7 +450,6 @@ int device_suspend(pm_message_t state) int error; might_sleep(); - down_write(&pm_sleep_rwsem); error = dpm_suspend(state); if (error) device_resume(); --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -11,30 +11,13 @@ static inline struct device *to_device(s return container_of(entry, struct device, power.entry); } -extern void device_pm_add(struct device *); +extern int device_pm_add(struct device *); extern void device_pm_remove(struct device *); -extern int pm_sleep_lock(void); -extern void pm_sleep_unlock(void); #else /* CONFIG_PM_SLEEP */ - -static inline void device_pm_add(struct device *dev) -{ -} - -static inline void device_pm_remove(struct device *dev) -{ -} - -static inline int pm_sleep_lock(void) -{ - return 0; -} - -static inline void pm_sleep_unlock(void) -{ -} +static inline int device_pm_add(struct device *dev) { return 0; } +static inline void device_pm_remove(struct device *dev) {} #endif --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -183,6 +183,7 @@ typedef struct pm_message { struct dev_pm_info { pm_message_t power_state; unsigned can_wakeup:1; + bool sleeping:1; /* Owned by the PM core */ #ifdef CONFIG_PM_SLEEP unsigned should_wakeup:1; struct list_head entry; Patches currently in gregkh-2.6 which might be from rjw@sisk.pl are driver-core/power_state-remove-it-from-driver-core.patch driver-core/pm-handle-device-registrations-during-suspend-resume.patch driver-core/pm-make-wakeup-flags-available-whenever-config_pm-is-set.patch driver-core/driver-core-call-device_pm_add-after-bus_add_device-in-device_add.patch ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 2/3] Driver core: Call device_pm_add() after bus_add_device() in device_add() 2008-03-11 23:55 [PATCH 0/3] PM core fixes Rafael J. Wysocki 2008-03-11 23:57 ` [PATCH 1/3] PM: Handle device registrations during suspend/resume Rafael J. Wysocki @ 2008-03-11 23:59 ` Rafael J. Wysocki 2008-03-13 9:30 ` Pavel Machek 2008-03-13 20:54 ` patch driver-core-call-device_pm_add-after-bus_add_device-in-device_add.patch added to gregkh-2.6 tree gregkh 2008-03-12 0:01 ` [PATCH 3/3] PM: make wakeup flags available whenever CONFIG_PM is set Rafael J. Wysocki 2 siblings, 2 replies; 10+ messages in thread From: Rafael J. Wysocki @ 2008-03-11 23:59 UTC (permalink / raw) To: Greg KH Cc: Alan Stern, Andrew Morton, David Brownell, LKML, Pavel Machek, pm list From: Rafael J. Wysocki <rjw@sisk.pl> Include dpm_sysfs_add() into device_pm_add(), in analogy with device_pm_remove(), and modify device_add() to call the latter after bus_add_device(), to avoid situations in which the PM core may attempt to suspend a device the registration of which has not been successful. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> --- drivers/base/core.c | 15 +++++---------- drivers/base/power/main.c | 4 +++- 2 files changed, 8 insertions(+), 11 deletions(-) Index: linux-2.6/drivers/base/core.c =================================================================== --- linux-2.6.orig/drivers/base/core.c +++ linux-2.6/drivers/base/core.c @@ -812,17 +812,12 @@ int device_add(struct device *dev) error = device_add_attrs(dev); if (error) goto AttrsError; - error = dpm_sysfs_add(dev); - if (error) - goto PMError; - error = device_pm_add(dev); - if (error) { - dpm_sysfs_remove(dev); - goto PMError; - } error = bus_add_device(dev); if (error) goto BusError; + error = device_pm_add(dev); + if (error) + goto PMError; kobject_uevent(&dev->kobj, KOBJ_ADD); bus_attach_device(dev); if (parent) @@ -842,9 +837,9 @@ int device_add(struct device *dev) Done: put_device(dev); return error; - BusError: - device_pm_remove(dev); PMError: + bus_remove_device(dev); + BusError: if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_DEL_DEVICE, dev); 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 @@ -81,7 +81,9 @@ int device_pm_add(struct device *dev) WARN_ON(true); error = -EBUSY; } else { - list_add_tail(&dev->power.entry, &dpm_active); + error = dpm_sysfs_add(dev); + if (!error) + list_add_tail(&dev->power.entry, &dpm_active); } mutex_unlock(&dpm_list_mtx); return error; ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/3] Driver core: Call device_pm_add() after bus_add_device() in device_add() 2008-03-11 23:59 ` [PATCH 2/3] Driver core: Call device_pm_add() after bus_add_device() in device_add() Rafael J. Wysocki @ 2008-03-13 9:30 ` Pavel Machek 2008-03-13 20:54 ` patch driver-core-call-device_pm_add-after-bus_add_device-in-device_add.patch added to gregkh-2.6 tree gregkh 1 sibling, 0 replies; 10+ messages in thread From: Pavel Machek @ 2008-03-13 9:30 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Greg KH, Alan Stern, Andrew Morton, David Brownell, LKML, pm list On Wed 2008-03-12 00:59:38, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki <rjw@sisk.pl> > > Include dpm_sysfs_add() into device_pm_add(), in analogy with > device_pm_remove(), and modify device_add() to call the latter after > bus_add_device(), to avoid situations in which the PM core may > attempt to suspend a device the registration of which has not been > successful. > > Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> ACK. -- (english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html ^ permalink raw reply [flat|nested] 10+ messages in thread
* patch driver-core-call-device_pm_add-after-bus_add_device-in-device_add.patch added to gregkh-2.6 tree 2008-03-11 23:59 ` [PATCH 2/3] Driver core: Call device_pm_add() after bus_add_device() in device_add() Rafael J. Wysocki 2008-03-13 9:30 ` Pavel Machek @ 2008-03-13 20:54 ` gregkh 1 sibling, 0 replies; 10+ messages in thread From: gregkh @ 2008-03-13 20:54 UTC (permalink / raw) To: rjw, akpm, david-b, greg, gregkh, linux-kernel, linux-pm, pavel, stern This is a note to let you know that I've just added the patch titled Subject: Driver core: Call device_pm_add() after bus_add_device() in device_add() to my gregkh-2.6 tree. Its filename is driver-core-call-device_pm_add-after-bus_add_device-in-device_add.patch This tree can be found at http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/ >From rjw@sisk.pl Thu Mar 13 13:45:38 2008 From: "Rafael J. Wysocki" <rjw@sisk.pl> Date: Wed, 12 Mar 2008 00:59:38 +0100 Subject: Driver core: Call device_pm_add() after bus_add_device() in device_add() To: Greg KH <greg@kroah.com> Cc: Alan Stern <stern@rowland.harvard.edu>, Andrew Morton <akpm@linux-foundation.org>, David Brownell <david-b@pacbell.net>, LKML <linux-kernel@vger.kernel.org>, Pavel Machek <pavel@ucw.cz>, pm list <linux-pm@lists.linux-foundation.org> Message-ID: <200803120059.39902.rjw@sisk.pl> Content-Disposition: inline From: Rafael J. Wysocki <rjw@sisk.pl> Include dpm_sysfs_add() into device_pm_add(), in analogy with device_pm_remove(), and modify device_add() to call the latter after bus_add_device(), to avoid situations in which the PM core may attempt to suspend a device the registration of which has not been successful. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/base/core.c | 15 +++++---------- drivers/base/power/main.c | 4 +++- 2 files changed, 8 insertions(+), 11 deletions(-) --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -818,17 +818,12 @@ int device_add(struct device *dev) error = device_add_attrs(dev); if (error) goto AttrsError; - error = dpm_sysfs_add(dev); - if (error) - goto PMError; - error = device_pm_add(dev); - if (error) { - dpm_sysfs_remove(dev); - goto PMError; - } error = bus_add_device(dev); if (error) goto BusError; + error = device_pm_add(dev); + if (error) + goto PMError; kobject_uevent(&dev->kobj, KOBJ_ADD); bus_attach_device(dev); if (parent) @@ -848,9 +843,9 @@ int device_add(struct device *dev) Done: put_device(dev); return error; - BusError: - device_pm_remove(dev); PMError: + bus_remove_device(dev); + BusError: if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_DEL_DEVICE, dev); --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -81,7 +81,9 @@ int device_pm_add(struct device *dev) WARN_ON(true); error = -EBUSY; } else { - list_add_tail(&dev->power.entry, &dpm_active); + error = dpm_sysfs_add(dev); + if (!error) + list_add_tail(&dev->power.entry, &dpm_active); } mutex_unlock(&dpm_list_mtx); return error; Patches currently in gregkh-2.6 which might be from rjw@sisk.pl are driver-core/power_state-remove-it-from-driver-core.patch driver-core/pm-handle-device-registrations-during-suspend-resume.patch driver-core/pm-make-wakeup-flags-available-whenever-config_pm-is-set.patch driver-core/driver-core-call-device_pm_add-after-bus_add_device-in-device_add.patch ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 3/3] PM: make wakeup flags available whenever CONFIG_PM is set 2008-03-11 23:55 [PATCH 0/3] PM core fixes Rafael J. Wysocki 2008-03-11 23:57 ` [PATCH 1/3] PM: Handle device registrations during suspend/resume Rafael J. Wysocki 2008-03-11 23:59 ` [PATCH 2/3] Driver core: Call device_pm_add() after bus_add_device() in device_add() Rafael J. Wysocki @ 2008-03-12 0:01 ` Rafael J. Wysocki 2008-03-13 9:31 ` Pavel Machek 2008-03-13 20:54 ` patch pm-make-wakeup-flags-available-whenever-config_pm-is-set.patch added to gregkh-2.6 tree gregkh 2 siblings, 2 replies; 10+ messages in thread From: Rafael J. Wysocki @ 2008-03-12 0:01 UTC (permalink / raw) To: Greg KH Cc: Alan Stern, Andrew Morton, David Brownell, LKML, Pavel Machek, pm list From: Alan Stern <stern@rowland.harvard.edu> The various wakeup flags and their accessor macros in struct dev_pm_info should be available whenever CONFIG_PM is enabled, not just when CONFIG_PM_SLEEP is on. Otherwise remote wakeup won't always be configurable for runtime power management. This patch (as1056) fixes the oversight. [rjw: rebased the patch on top of the previous two.] Signed-off-by: Alan Stern <stern@rowland.harvard.edu> CC: David Brownell <david-b@pacbell.net> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> --- drivers/base/power/main.c | 2 - drivers/base/power/sysfs.c | 2 + include/linux/pm.h | 64 +++++++++++++++++++++++++-------------------- 3 files changed, 38 insertions(+), 30 deletions(-) Index: linux-2.6/include/linux/pm.h =================================================================== --- linux-2.6.orig/include/linux/pm.h +++ linux-2.6/include/linux/pm.h @@ -183,9 +183,9 @@ typedef struct pm_message { struct dev_pm_info { pm_message_t power_state; unsigned can_wakeup:1; + unsigned should_wakeup:1; bool sleeping:1; /* Owned by the PM core */ #ifdef CONFIG_PM_SLEEP - unsigned should_wakeup:1; struct list_head entry; #endif }; @@ -198,11 +198,6 @@ extern void device_resume(void); extern int device_suspend(pm_message_t state); extern int device_prepare_suspend(pm_message_t state); -#define device_set_wakeup_enable(dev,val) \ - ((dev)->power.should_wakeup = !!(val)) -#define device_may_wakeup(dev) \ - (device_can_wakeup(dev) && (dev)->power.should_wakeup) - extern void __suspend_report_result(const char *function, void *fn, int ret); #define suspend_report_result(fn, ret) \ @@ -210,6 +205,35 @@ extern void __suspend_report_result(cons __suspend_report_result(__FUNCTION__, fn, ret); \ } while (0) +#else /* !CONFIG_PM_SLEEP */ + +static inline int device_suspend(pm_message_t state) +{ + return 0; +} + +#define suspend_report_result(fn, ret) do {} while (0) + +#endif /* !CONFIG_PM_SLEEP */ + +#ifdef CONFIG_PM + +/* changes to device_may_wakeup take effect on the next pm state change. + * by default, devices should wakeup if they can. + */ +#define device_can_wakeup(dev) \ + ((dev)->power.can_wakeup) +#define device_init_wakeup(dev,val) \ + do { \ + device_can_wakeup(dev) = !!(val); \ + device_set_wakeup_enable(dev,val); \ + } while(0) + +#define device_set_wakeup_enable(dev,val) \ + ((dev)->power.should_wakeup = !!(val)) +#define device_may_wakeup(dev) \ + (device_can_wakeup(dev) && (dev)->power.should_wakeup) + /* * Platform hook to activate device wakeup capability, if that's not already * handled by enable_irq_wake() etc. @@ -224,35 +248,19 @@ static inline int call_platform_enable_w return 0; } -#else /* !CONFIG_PM_SLEEP */ - -static inline int device_suspend(pm_message_t state) -{ - return 0; -} - -#define device_set_wakeup_enable(dev,val) do{}while(0) -#define device_may_wakeup(dev) (0) +#else /* !CONFIG_PM */ -#define suspend_report_result(fn, ret) do { } while (0) +#define device_can_wakeup(dev) 0 +#define device_init_wakeup(dev,val) do {} while (0) +#define device_set_wakeup_enable(dev,val) do {} while (0) +#define device_may_wakeup(dev) 0 static inline int call_platform_enable_wakeup(struct device *dev, int is_on) { return 0; } -#endif /* !CONFIG_PM_SLEEP */ - -/* changes to device_may_wakeup take effect on the next pm state change. - * by default, devices should wakeup if they can. - */ -#define device_can_wakeup(dev) \ - ((dev)->power.can_wakeup) -#define device_init_wakeup(dev,val) \ - do { \ - device_can_wakeup(dev) = !!(val); \ - device_set_wakeup_enable(dev,val); \ - } while(0) +#endif /* !CONFIG_PM */ /* * Global Power Management flags 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 @@ -57,8 +57,6 @@ static DEFINE_MUTEX(dpm_list_mtx); /* 'true' if all devices have been suspended, protected by dpm_list_mtx */ static bool all_sleeping; -int (*platform_enable_wakeup)(struct device *dev, int is_on); - /** * device_pm_add - add a device to the list of active devices * @dev: Device to be added to the list Index: linux-2.6/drivers/base/power/sysfs.c =================================================================== --- linux-2.6.orig/drivers/base/power/sysfs.c +++ linux-2.6/drivers/base/power/sysfs.c @@ -6,6 +6,8 @@ #include <linux/string.h> #include "power.h" +int (*platform_enable_wakeup)(struct device *dev, int is_on); + /* * wakeup - Report/change current wakeup option for device ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 3/3] PM: make wakeup flags available whenever CONFIG_PM is set 2008-03-12 0:01 ` [PATCH 3/3] PM: make wakeup flags available whenever CONFIG_PM is set Rafael J. Wysocki @ 2008-03-13 9:31 ` Pavel Machek 2008-03-13 20:54 ` patch pm-make-wakeup-flags-available-whenever-config_pm-is-set.patch added to gregkh-2.6 tree gregkh 1 sibling, 0 replies; 10+ messages in thread From: Pavel Machek @ 2008-03-13 9:31 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Greg KH, Alan Stern, Andrew Morton, David Brownell, LKML, pm list On Wed 2008-03-12 01:01:47, Rafael J. Wysocki wrote: > From: Alan Stern <stern@rowland.harvard.edu> > > The various wakeup flags and their accessor macros in struct > dev_pm_info should be available whenever CONFIG_PM is enabled, not > just when CONFIG_PM_SLEEP is on. Otherwise remote wakeup won't always > be configurable for runtime power management. This patch (as1056) > fixes the oversight. > > [rjw: rebased the patch on top of the previous two.] > > Signed-off-by: Alan Stern <stern@rowland.harvard.edu> > CC: David Brownell <david-b@pacbell.net> > Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> ACK. But I wonder if we should reduce ammount of config options we have in power management. All those combinations are hard to test... Pavel -- (english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html ^ permalink raw reply [flat|nested] 10+ messages in thread
* patch pm-make-wakeup-flags-available-whenever-config_pm-is-set.patch added to gregkh-2.6 tree 2008-03-12 0:01 ` [PATCH 3/3] PM: make wakeup flags available whenever CONFIG_PM is set Rafael J. Wysocki 2008-03-13 9:31 ` Pavel Machek @ 2008-03-13 20:54 ` gregkh 1 sibling, 0 replies; 10+ messages in thread From: gregkh @ 2008-03-13 20:54 UTC (permalink / raw) To: stern, akpm, david-b, greg, gregkh, linux-kernel, linux-pm, pavel, rjw This is a note to let you know that I've just added the patch titled Subject: PM: make wakeup flags available whenever CONFIG_PM is set to my gregkh-2.6 tree. Its filename is pm-make-wakeup-flags-available-whenever-config_pm-is-set.patch This tree can be found at http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/ >From rjw@sisk.pl Thu Mar 13 13:46:04 2008 From: Alan Stern <stern@rowland.harvard.edu> Date: Wed, 12 Mar 2008 01:01:47 +0100 Subject: PM: make wakeup flags available whenever CONFIG_PM is set To: Greg KH <greg@kroah.com> Cc: Alan Stern <stern@rowland.harvard.edu>, Andrew Morton <akpm@linux-foundation.org>, David Brownell <david-b@pacbell.net>, LKML <linux-kernel@vger.kernel.org>, Pavel Machek <pavel@ucw.cz>, pm list <linux-pm@lists.linux-foundation.org> Message-ID: <200803120101.48805.rjw@sisk.pl> Content-Disposition: inline From: Alan Stern <stern@rowland.harvard.edu> The various wakeup flags and their accessor macros in struct dev_pm_info should be available whenever CONFIG_PM is enabled, not just when CONFIG_PM_SLEEP is on. Otherwise remote wakeup won't always be configurable for runtime power management. This patch (as1056) fixes the oversight. [rjw: rebased the patch on top of the previous two.] Signed-off-by: Alan Stern <stern@rowland.harvard.edu> CC: David Brownell <david-b@pacbell.net> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/base/power/main.c | 2 - drivers/base/power/sysfs.c | 2 + include/linux/pm.h | 64 +++++++++++++++++++++++++-------------------- 3 files changed, 38 insertions(+), 30 deletions(-) --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -57,8 +57,6 @@ static DEFINE_MUTEX(dpm_list_mtx); /* 'true' if all devices have been suspended, protected by dpm_list_mtx */ static bool all_sleeping; -int (*platform_enable_wakeup)(struct device *dev, int is_on); - /** * device_pm_add - add a device to the list of active devices * @dev: Device to be added to the list --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -6,6 +6,8 @@ #include <linux/string.h> #include "power.h" +int (*platform_enable_wakeup)(struct device *dev, int is_on); + /* * wakeup - Report/change current wakeup option for device --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -183,9 +183,9 @@ typedef struct pm_message { struct dev_pm_info { pm_message_t power_state; unsigned can_wakeup:1; + unsigned should_wakeup:1; bool sleeping:1; /* Owned by the PM core */ #ifdef CONFIG_PM_SLEEP - unsigned should_wakeup:1; struct list_head entry; #endif }; @@ -198,11 +198,6 @@ extern void device_resume(void); extern int device_suspend(pm_message_t state); extern int device_prepare_suspend(pm_message_t state); -#define device_set_wakeup_enable(dev,val) \ - ((dev)->power.should_wakeup = !!(val)) -#define device_may_wakeup(dev) \ - (device_can_wakeup(dev) && (dev)->power.should_wakeup) - extern void __suspend_report_result(const char *function, void *fn, int ret); #define suspend_report_result(fn, ret) \ @@ -210,6 +205,35 @@ extern void __suspend_report_result(cons __suspend_report_result(__FUNCTION__, fn, ret); \ } while (0) +#else /* !CONFIG_PM_SLEEP */ + +static inline int device_suspend(pm_message_t state) +{ + return 0; +} + +#define suspend_report_result(fn, ret) do {} while (0) + +#endif /* !CONFIG_PM_SLEEP */ + +#ifdef CONFIG_PM + +/* changes to device_may_wakeup take effect on the next pm state change. + * by default, devices should wakeup if they can. + */ +#define device_can_wakeup(dev) \ + ((dev)->power.can_wakeup) +#define device_init_wakeup(dev,val) \ + do { \ + device_can_wakeup(dev) = !!(val); \ + device_set_wakeup_enable(dev,val); \ + } while(0) + +#define device_set_wakeup_enable(dev,val) \ + ((dev)->power.should_wakeup = !!(val)) +#define device_may_wakeup(dev) \ + (device_can_wakeup(dev) && (dev)->power.should_wakeup) + /* * Platform hook to activate device wakeup capability, if that's not already * handled by enable_irq_wake() etc. @@ -224,35 +248,19 @@ static inline int call_platform_enable_w return 0; } -#else /* !CONFIG_PM_SLEEP */ - -static inline int device_suspend(pm_message_t state) -{ - return 0; -} - -#define device_set_wakeup_enable(dev,val) do{}while(0) -#define device_may_wakeup(dev) (0) +#else /* !CONFIG_PM */ -#define suspend_report_result(fn, ret) do { } while (0) +#define device_can_wakeup(dev) 0 +#define device_init_wakeup(dev,val) do {} while (0) +#define device_set_wakeup_enable(dev,val) do {} while (0) +#define device_may_wakeup(dev) 0 static inline int call_platform_enable_wakeup(struct device *dev, int is_on) { return 0; } -#endif /* !CONFIG_PM_SLEEP */ - -/* changes to device_may_wakeup take effect on the next pm state change. - * by default, devices should wakeup if they can. - */ -#define device_can_wakeup(dev) \ - ((dev)->power.can_wakeup) -#define device_init_wakeup(dev,val) \ - do { \ - device_can_wakeup(dev) = !!(val); \ - device_set_wakeup_enable(dev,val); \ - } while(0) +#endif /* !CONFIG_PM */ /* * Global Power Management flags Patches currently in gregkh-2.6 which might be from stern@rowland.harvard.edu are usb/usb-convert-usb.h-struct-usb_device-to-kernel-doc.patch usb/usb-make-usb_storage_onetouch-available-with-pm.patch usb/usb-usb-ohci-sm501-driver-use-the-conventional-convention-for-suspend-and-resume.patch usb/usb-reorganize-code-in-hub.c.patch usb/usb-ehci-carry-out-port-handover-during-each-root-hub-resume.patch usb/usb-new-quirk-flag-to-avoid-set-interface.patch usb/drivers-usb-core-devio.c-suppress-warning-with-64k-page_size.patch usb/usb-make-usb-persist-work-after-every-system-sleep.patch usb/usb-remove-config_usb_persist-setting.patch usb/usb-check-serial-number-string-after-device-reset.patch usb/usb-enable-usb-persist-by-default.patch usb/usb-remove-dev-power.power_state.patch driver-core/pm-handle-device-registrations-during-suspend-resume.patch driver-core/pm-make-wakeup-flags-available-whenever-config_pm-is-set.patch driver-core/driver-core-call-device_pm_add-after-bus_add_device-in-device_add.patch ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2008-03-13 20:55 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2008-03-11 23:55 [PATCH 0/3] PM core fixes Rafael J. Wysocki 2008-03-11 23:57 ` [PATCH 1/3] PM: Handle device registrations during suspend/resume Rafael J. Wysocki 2008-03-13 8:37 ` Pavel Machek 2008-03-13 20:54 ` patch pm-handle-device-registrations-during-suspend-resume.patch added to gregkh-2.6 tree gregkh 2008-03-11 23:59 ` [PATCH 2/3] Driver core: Call device_pm_add() after bus_add_device() in device_add() Rafael J. Wysocki 2008-03-13 9:30 ` Pavel Machek 2008-03-13 20:54 ` patch driver-core-call-device_pm_add-after-bus_add_device-in-device_add.patch added to gregkh-2.6 tree gregkh 2008-03-12 0:01 ` [PATCH 3/3] PM: make wakeup flags available whenever CONFIG_PM is set Rafael J. Wysocki 2008-03-13 9:31 ` Pavel Machek 2008-03-13 20:54 ` patch pm-make-wakeup-flags-available-whenever-config_pm-is-set.patch added to gregkh-2.6 tree gregkh
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).