On Wednesday, 20 of February 2008, Alan Stern wrote:As I said before (but that doesn't seem to reach the list, so I'm repeating), this is to protect other tasks from reading an inconsistent value of suspending_task in case they attempt to remove a device concurrently with respect to us. While this is not likely to happen right now, because of the freezer, it may very well happen when the freezer is finally removed. Something like the patch below, perhaps? Again, untested, but compiled this time. :-) Thanks, Rafael --- drivers/base/core.c | 5 +++++ drivers/base/power/main.c | 22 ++++++++++++++++++++++ drivers/base/power/power.h | 5 +++++ 3 files changed, 32 insertions(+) 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 @@ -59,6 +59,26 @@ static DECLARE_RWSEM(pm_sleep_rwsem); int (*platform_enable_wakeup)(struct device *dev, int is_on); +static struct task_struct *suspending_task; +static DEFINE_MUTEX(suspending_task_mtx); + +bool in_suspend_context(void) +{ + bool result; + + mutex_lock(&suspending_task_mtx); + result = (suspending_task == current); + mutex_unlock(&suspending_task_mtx); + return result; +} + +static void set_suspending_task(struct task_struct *task) +{ + mutex_lock(&suspending_task_mtx); + suspending_task = task; + mutex_unlock(&suspending_task_mtx); +} + /** * device_pm_add - add a device to the list of active devices * @dev: Device to be added to the list @@ -272,6 +292,7 @@ static void dpm_resume(void) mutex_lock(&dpm_list_mtx); } mutex_unlock(&dpm_list_mtx); + set_suspending_task(NULL); } /** @@ -460,6 +481,7 @@ static int dpm_suspend(pm_message_t stat { int error = 0; + set_suspending_task(current); mutex_lock(&dpm_list_mtx); while (!list_empty(&dpm_locked)) { struct list_head *entry = dpm_locked.prev; Index: linux-2.6/drivers/base/core.c =================================================================== --- linux-2.6.orig/drivers/base/core.c +++ linux-2.6/drivers/base/core.c @@ -929,6 +929,11 @@ void device_del(struct device *dev) struct device *parent = dev->parent; struct class_interface *class_intf; + if (in_suspend_context()) { + get_device(dev); + device_pm_schedule_removal(dev); + return; + } device_pm_remove(dev); if (parent) klist_del(&dev->knode_parent); 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,6 +11,7 @@ static inline struct device *to_device(s return container_of(entry, struct device, power.entry); } +extern bool in_suspend_context(void); extern void device_pm_add(struct device *); extern void device_pm_remove(struct device *); extern int pm_sleep_lock(void); @@ -18,6 +19,10 @@ extern void pm_sleep_unlock(void); #else /* CONFIG_PM_SLEEP */ +static inline bool in_suspend_context(void) +{ + return false; +} static inline void device_pm_add(struct device *dev) { --
| Jan Engelhardt | intel iommu (Re: -mm merge plans for 2.6.23) |
| Tarkan Erimer | Re: Dual-Licensing Linux Kernel with GPL V2 and GPL V3 |
| Rafael J. Wysocki | Re: Linux 2.6.27-rc5: System boot regression caused by commit a2bd7274b47124d2fc4d... |
git: | |
| Gerrit Renker | [PATCH 0/37] dccp: Feature negotiation - last call for comments |
| David Miller | [GIT]: Networking |
| Jarek Poplawski | [PATCH] pkt_sched: Destroy gen estimators under rtnl_lock(). |
