OK
[--snip--]
Not exactly, because in that case we blocked all attempts to register devices,
while I think we can only block those regarding the children of a suspending
(or suspended) device.
I'm not really convinced that it'll happen. If we make the rule that
registering children from the device's own ->suspend() method is forbidden
(I don't really see why it should be allowed), something like this might work
(it seems to me):
Index: linux-2.6/include/linux/pm.h
===================================================================
--- linux-2.6.orig/include/linux/pm.h
+++ linux-2.6/include/linux/pm.h
@@ -186,6 +186,7 @@ struct dev_pm_info {
#ifdef CONFIG_PM_SLEEP
unsigned should_wakeup:1;
struct list_head entry;
+ struct mutex lock;
#endif
};
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
@@ -67,9 +67,14 @@ void device_pm_add(struct device *dev)
pr_debug("PM: Adding info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus",
kobject_name(&dev->kobj));
+ if (dev->parent)
+ mutex_lock(&dev->parent.power.lock);
mutex_lock(&dpm_list_mtx);
list_add_tail(&dev->power.entry, &dpm_active);
+ mutex_init(&dev->power.lock);
mutex_unlock(&dpm_list_mtx);
+ if (dev->parent)
+ mutex_unlock(&dev->parent.power.lock);
}
/**
@@ -249,6 +254,7 @@ static void dpm_resume(void)
list_move_tail(entry, &dpm_active);
mutex_unlock(&dpm_list_mtx);
resume_device(dev);
+ mutex_unlock(&dev->power.lock);
mutex_lock(&dpm_list_mtx);
}
mutex_unlock(&dpm_list_mtx);
@@ -427,6 +433,13 @@ static int dpm_suspend(pm_message_t stat
struct device *dev = to_device(entry);
mutex_unlock(&dpm_list_mtx);
+ mutex_lock(&dev->power.lock);
+ mutex_lock(&dpm_list_mtx);
+ if (dev != to_device(dpm_active.prev)) {
+ mutex_unlock(&dev->power.lock);
+ continue;
+ }
+ mutex_unlock(&dpm_list_mtx);
error = suspend_device(dev, state);
mutex_lock(&dpm_list_mtx);
if (error) {
@@ -437,6 +450,7 @@ static int dpm_suspend(pm_message_t stat
(error == -EAGAIN ?
" (please convert to suspend_late)" :
""));
+ mutex_unlock(&dev->power.lock);
break;
}
if (!list_empty(&dev->power.entry))
That doesn't buy us anything if drivers don't check whether the registration
succeeded. And they don't.
Not exactly. Just the children of suspended devices, which makes a difference
IMO. :-)
Well, my impression is that we do this thing to prepare for removing the
freezer in the future, so I'd rather solve issues in some other ways than just
by freezing threads that get in the way. ;-)
They may be handled in a different way, not by ->resume().
Still, it doesn't look very nice ...
Thanks,
Rafael
--