This is a note to let you know that I've just added the patch titled
Subject: PM: Acquire device locks on suspend
to my gregkh-2.6 tree. Its filename is
pm-acquire-device-locks-on-suspend.patch
This tree can be found at
http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/
From [EMAIL PROTECTED] Fri Jan 18 16:29:07 2008
From: Rafael J. Wysocki [EMAIL PROTECTED]
Date: Sat, 12 Jan 2008 20:40:46 +0100
Subject: PM: Acquire device locks on suspend
To: Greg KH [EMAIL PROTECTED]
Cc: Alan Stern [EMAIL PROTECTED], Len Brown [EMAIL PROTECTED], Ingo Molnar
[EMAIL PROTECTED], ACPI Devel Maling List linux-acpi@vger.kernel.org, pm
list [EMAIL PROTECTED], LKML [EMAIL PROTECTED], Johannes Berg [EMAIL
PROTECTED], Andrew Morton [EMAIL PROTECTED]
Message-ID: [EMAIL PROTECTED]
Content-Disposition: inline
From: Rafael J. Wysocki [EMAIL PROTECTED]
This patch reorganizes the way suspend and resume notifications are
sent to drivers. The major changes are that now the PM core acquires
every device semaphore before calling the methods, and calls to
device_add() during suspends will fail, while calls to device_del()
during suspends will block.
It also provides a way to safely remove a suspended device with the
help of the PM core, by using the device_pm_schedule_removal() callback
introduced specifically for this purpose, and updates two drivers (msr
and cpuid) that need to use it.
Signed-off-by: Alan Stern [EMAIL PROTECTED]
Signed-off-by: Rafael J. Wysocki [EMAIL PROTECTED]
Signed-off-by: Greg Kroah-Hartman [EMAIL PROTECTED]
---
arch/x86/kernel/cpuid.c|6
arch/x86/kernel/msr.c |6
drivers/base/core.c| 65 +
drivers/base/power/main.c | 504 +
drivers/base/power/power.h | 12 +
include/linux/device.h |8
6 files changed, 414 insertions(+), 187 deletions(-)
--- a/arch/x86/kernel/cpuid.c
+++ b/arch/x86/kernel/cpuid.c
@@ -157,15 +157,15 @@ static int __cpuinit cpuid_class_cpu_cal
switch (action) {
case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
err = cpuid_device_create(cpu);
break;
case CPU_UP_CANCELED:
- case CPU_UP_CANCELED_FROZEN:
case CPU_DEAD:
- case CPU_DEAD_FROZEN:
cpuid_device_destroy(cpu);
break;
+ case CPU_UP_CANCELED_FROZEN:
+ destroy_suspended_device(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
+ break;
}
return err ? NOTIFY_BAD : NOTIFY_OK;
}
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -155,15 +155,15 @@ static int __cpuinit msr_class_cpu_callb
switch (action) {
case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
err = msr_device_create(cpu);
break;
case CPU_UP_CANCELED:
- case CPU_UP_CANCELED_FROZEN:
case CPU_DEAD:
- case CPU_DEAD_FROZEN:
msr_device_destroy(cpu);
break;
+ case CPU_UP_CANCELED_FROZEN:
+ destroy_suspended_device(msr_class, MKDEV(MSR_MAJOR, cpu));
+ break;
}
return err ? NOTIFY_BAD : NOTIFY_OK;
}
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -726,11 +726,20 @@ int device_add(struct device *dev)
{
struct device *parent = NULL;
struct class_interface *class_intf;
- int error = -EINVAL;
+ int error;
+
+ error = pm_sleep_lock();
+ if (error) {
+ dev_warn(dev, Suspicious %s during suspend\n, __FUNCTION__);
+ dump_stack();
+ return error;
+ }
dev = get_device(dev);
- if (!dev || !strlen(dev-bus_id))
+ if (!dev || !strlen(dev-bus_id)) {
+ error = -EINVAL;
goto Error;
+ }
pr_debug(DEV: registering device: ID = '%s'\n, dev-bus_id);
@@ -795,6 +804,7 @@ int device_add(struct device *dev)
}
Done:
put_device(dev);
+ pm_sleep_unlock();
return error;
BusError:
device_pm_remove(dev);
@@ -905,6 +915,7 @@ void device_del(struct device * dev)
struct device * parent = dev-parent;
struct class_interface *class_intf;
+ device_pm_remove(dev);
if (parent)
klist_del(dev-knode_parent);
if (MAJOR(dev-devt))
@@ -981,7 +992,6 @@ void device_del(struct device * dev)
if (dev-bus)
blocking_notifier_call_chain(dev-bus-bus_notifier,
BUS_NOTIFY_DEL_DEVICE, dev);
- device_pm_remove(dev);
kobject_uevent(dev-kobj, KOBJ_REMOVE);
kobject_del(dev-kobj);
if (parent)
@@ -1156,14 +1166,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