Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6:
  PM: Add empty suspend/resume device irq functions
  PM/Hibernate: Move NVS routines into a seperate file (v2).
  PM/Hibernate: Rename disk.c to hibernate.c
  PM: Separate suspend to RAM functionality from core
  Driver Core: Rework platform suspend/resume, print warning
  PM: Remove device_type suspend()/resume()
  PM/Hibernate: Move memory shrinking to snapshot.c (rev. 2)
  PM/Suspend: Do not shrink memory before suspend
  PM: Remove bus_type suspend_late()/resume_early() V2
  PM core: rename suspend and resume functions
  PM: Rename device_power_down/up()
  PM: Remove unused asm/suspend.h
  x86: unify power/cpu_(32|64).c
  x86: unify power/cpu_(32|64) copyright notes
  x86: unify power/cpu_(32|64) regarding restoring processor state
  x86: unify power/cpu_(32|64) regarding saving processor state
  x86: unify power/cpu_(32|64) global variables
  x86: unify power/cpu_(32|64) headers
  PM: Warn if interrupts are enabled during suspend-resume of sysdevs
  PM/ACPI/x86: Fix sparse warning in arch/x86/kernel/acpi/sleep.c
This commit is contained in:
Linus Torvalds
2009-06-12 13:17:27 -07:00
33 changed files with 984 additions and 1122 deletions
+12 -24
View File
@@ -469,22 +469,6 @@ static void platform_drv_shutdown(struct device *_dev)
drv->shutdown(dev);
}
static int platform_drv_suspend(struct device *_dev, pm_message_t state)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
struct platform_device *dev = to_platform_device(_dev);
return drv->suspend(dev, state);
}
static int platform_drv_resume(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
struct platform_device *dev = to_platform_device(_dev);
return drv->resume(dev);
}
/**
* platform_driver_register
* @drv: platform driver structure
@@ -498,10 +482,10 @@ int platform_driver_register(struct platform_driver *drv)
drv->driver.remove = platform_drv_remove;
if (drv->shutdown)
drv->driver.shutdown = platform_drv_shutdown;
if (drv->suspend)
drv->driver.suspend = platform_drv_suspend;
if (drv->resume)
drv->driver.resume = platform_drv_resume;
if (drv->suspend || drv->resume)
pr_warning("Platform driver '%s' needs updating - please use "
"dev_pm_ops\n", drv->driver.name);
return driver_register(&drv->driver);
}
EXPORT_SYMBOL_GPL(platform_driver_register);
@@ -633,10 +617,12 @@ static int platform_match(struct device *dev, struct device_driver *drv)
static int platform_legacy_suspend(struct device *dev, pm_message_t mesg)
{
struct platform_driver *pdrv = to_platform_driver(dev->driver);
struct platform_device *pdev = to_platform_device(dev);
int ret = 0;
if (dev->driver && dev->driver->suspend)
ret = dev->driver->suspend(dev, mesg);
if (dev->driver && pdrv->suspend)
ret = pdrv->suspend(pdev, mesg);
return ret;
}
@@ -667,10 +653,12 @@ static int platform_legacy_resume_early(struct device *dev)
static int platform_legacy_resume(struct device *dev)
{
struct platform_driver *pdrv = to_platform_driver(dev->driver);
struct platform_device *pdev = to_platform_device(dev);
int ret = 0;
if (dev->driver && dev->driver->resume)
ret = dev->driver->resume(dev);
if (dev->driver && pdrv->resume)
ret = pdrv->resume(pdev);
return ret;
}
+34 -60
View File
@@ -315,13 +315,13 @@ static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
/*------------------------- Resume routines -------------------------*/
/**
* resume_device_noirq - Power on one device (early resume).
* device_resume_noirq - Power on one device (early resume).
* @dev: Device.
* @state: PM transition of the system being carried out.
*
* Must be called with interrupts disabled.
*/
static int resume_device_noirq(struct device *dev, pm_message_t state)
static int device_resume_noirq(struct device *dev, pm_message_t state)
{
int error = 0;
@@ -334,9 +334,6 @@ static int resume_device_noirq(struct device *dev, pm_message_t state)
if (dev->bus->pm) {
pm_dev_dbg(dev, state, "EARLY ");
error = pm_noirq_op(dev, dev->bus->pm, state);
} else if (dev->bus->resume_early) {
pm_dev_dbg(dev, state, "legacy EARLY ");
error = dev->bus->resume_early(dev);
}
End:
TRACE_RESUME(error);
@@ -344,16 +341,16 @@ static int resume_device_noirq(struct device *dev, pm_message_t state)
}
/**
* dpm_power_up - Power on all regular (non-sysdev) devices.
* dpm_resume_noirq - Power on all regular (non-sysdev) devices.
* @state: PM transition of the system being carried out.
*
* Execute the appropriate "noirq resume" callback for all devices marked
* as DPM_OFF_IRQ.
* Call the "noirq" resume handlers for all devices marked as
* DPM_OFF_IRQ and enable device drivers to receive interrupts.
*
* Must be called under dpm_list_mtx. Device drivers should not receive
* interrupts while it's being executed.
*/
static void dpm_power_up(pm_message_t state)
void dpm_resume_noirq(pm_message_t state)
{
struct device *dev;
@@ -363,33 +360,21 @@ static void dpm_power_up(pm_message_t state)
int error;
dev->power.status = DPM_OFF;
error = resume_device_noirq(dev, state);
error = device_resume_noirq(dev, state);
if (error)
pm_dev_err(dev, state, " early", error);
}
mutex_unlock(&dpm_list_mtx);
}
/**
* device_power_up - Turn on all devices that need special attention.
* @state: PM transition of the system being carried out.
*
* Call the "early" resume handlers and enable device drivers to receive
* interrupts.
*/
void device_power_up(pm_message_t state)
{
dpm_power_up(state);
resume_device_irqs();
}
EXPORT_SYMBOL_GPL(device_power_up);
EXPORT_SYMBOL_GPL(dpm_resume_noirq);
/**
* resume_device - Restore state for one device.
* device_resume - Restore state for one device.
* @dev: Device.
* @state: PM transition of the system being carried out.
*/
static int resume_device(struct device *dev, pm_message_t state)
static int device_resume(struct device *dev, pm_message_t state)
{
int error = 0;
@@ -414,9 +399,6 @@ static int resume_device(struct device *dev, pm_message_t state)
if (dev->type->pm) {
pm_dev_dbg(dev, state, "type ");
error = pm_op(dev, dev->type->pm, state);
} else if (dev->type->resume) {
pm_dev_dbg(dev, state, "legacy type ");
error = dev->type->resume(dev);
}
if (error)
goto End;
@@ -462,7 +444,7 @@ static void dpm_resume(pm_message_t state)
dev->power.status = DPM_RESUMING;
mutex_unlock(&dpm_list_mtx);
error = resume_device(dev, state);
error = device_resume(dev, state);
mutex_lock(&dpm_list_mtx);
if (error)
@@ -480,11 +462,11 @@ static void dpm_resume(pm_message_t state)
}
/**
* complete_device - Complete a PM transition for given device
* device_complete - Complete a PM transition for given device
* @dev: Device.
* @state: PM transition of the system being carried out.
*/
static void complete_device(struct device *dev, pm_message_t state)
static void device_complete(struct device *dev, pm_message_t state)
{
down(&dev->sem);
@@ -527,7 +509,7 @@ static void dpm_complete(pm_message_t state)
dev->power.status = DPM_ON;
mutex_unlock(&dpm_list_mtx);
complete_device(dev, state);
device_complete(dev, state);
mutex_lock(&dpm_list_mtx);
}
@@ -540,19 +522,19 @@ static void dpm_complete(pm_message_t state)
}
/**
* device_resume - Restore state of each device in system.
* dpm_resume_end - Restore state of each device in system.
* @state: PM transition of the system being carried out.
*
* Resume all the devices, unlock them all, and allow new
* devices to be registered once again.
*/
void device_resume(pm_message_t state)
void dpm_resume_end(pm_message_t state)
{
might_sleep();
dpm_resume(state);
dpm_complete(state);
}
EXPORT_SYMBOL_GPL(device_resume);
EXPORT_SYMBOL_GPL(dpm_resume_end);
/*------------------------- Suspend routines -------------------------*/
@@ -577,13 +559,13 @@ static pm_message_t resume_event(pm_message_t sleep_state)
}
/**
* suspend_device_noirq - Shut down one device (late suspend).
* device_suspend_noirq - Shut down one device (late suspend).
* @dev: Device.
* @state: PM transition of the system being carried out.
*
* This is called with interrupts off and only a single CPU running.
*/
static int suspend_device_noirq(struct device *dev, pm_message_t state)
static int device_suspend_noirq(struct device *dev, pm_message_t state)
{
int error = 0;
@@ -593,24 +575,20 @@ static int suspend_device_noirq(struct device *dev, pm_message_t state)
if (dev->bus->pm) {
pm_dev_dbg(dev, state, "LATE ");
error = pm_noirq_op(dev, dev->bus->pm, state);
} else if (dev->bus->suspend_late) {
pm_dev_dbg(dev, state, "legacy LATE ");
error = dev->bus->suspend_late(dev, state);
suspend_report_result(dev->bus->suspend_late, error);
}
return error;
}
/**
* device_power_down - Shut down special devices.
* dpm_suspend_noirq - Power down all regular (non-sysdev) devices.
* @state: PM transition of the system being carried out.
*
* Prevent device drivers from receiving interrupts and call the "late"
* Prevent device drivers from receiving interrupts and call the "noirq"
* suspend handlers.
*
* Must be called under dpm_list_mtx.
*/
int device_power_down(pm_message_t state)
int dpm_suspend_noirq(pm_message_t state)
{
struct device *dev;
int error = 0;
@@ -618,7 +596,7 @@ int device_power_down(pm_message_t state)
suspend_device_irqs();
mutex_lock(&dpm_list_mtx);
list_for_each_entry_reverse(dev, &dpm_list, power.entry) {
error = suspend_device_noirq(dev, state);
error = device_suspend_noirq(dev, state);
if (error) {
pm_dev_err(dev, state, " late", error);
break;
@@ -627,17 +605,17 @@ int device_power_down(pm_message_t state)
}
mutex_unlock(&dpm_list_mtx);
if (error)
device_power_up(resume_event(state));
dpm_resume_noirq(resume_event(state));
return error;
}
EXPORT_SYMBOL_GPL(device_power_down);
EXPORT_SYMBOL_GPL(dpm_suspend_noirq);
/**
* suspend_device - Save state of one device.
* device_suspend - Save state of one device.
* @dev: Device.
* @state: PM transition of the system being carried out.
*/
static int suspend_device(struct device *dev, pm_message_t state)
static int device_suspend(struct device *dev, pm_message_t state)
{
int error = 0;
@@ -660,10 +638,6 @@ static int suspend_device(struct device *dev, pm_message_t state)
if (dev->type->pm) {
pm_dev_dbg(dev, state, "type ");
error = pm_op(dev, dev->type->pm, state);
} else if (dev->type->suspend) {
pm_dev_dbg(dev, state, "legacy type ");
error = dev->type->suspend(dev, state);
suspend_report_result(dev->type->suspend, error);
}
if (error)
goto End;
@@ -704,7 +678,7 @@ static int dpm_suspend(pm_message_t state)
get_device(dev);
mutex_unlock(&dpm_list_mtx);
error = suspend_device(dev, state);
error = device_suspend(dev, state);
mutex_lock(&dpm_list_mtx);
if (error) {
@@ -723,11 +697,11 @@ static int dpm_suspend(pm_message_t state)
}
/**
* prepare_device - Execute the ->prepare() callback(s) for given device.
* device_prepare - Execute the ->prepare() callback(s) for given device.
* @dev: Device.
* @state: PM transition of the system being carried out.
*/
static int prepare_device(struct device *dev, pm_message_t state)
static int device_prepare(struct device *dev, pm_message_t state)
{
int error = 0;
@@ -781,7 +755,7 @@ static int dpm_prepare(pm_message_t state)
dev->power.status = DPM_PREPARING;
mutex_unlock(&dpm_list_mtx);
error = prepare_device(dev, state);
error = device_prepare(dev, state);
mutex_lock(&dpm_list_mtx);
if (error) {
@@ -807,12 +781,12 @@ static int dpm_prepare(pm_message_t state)
}
/**
* device_suspend - Save state and stop all devices in system.
* dpm_suspend_start - Save state and stop all devices in system.
* @state: PM transition of the system being carried out.
*
* Prepare and suspend all devices.
*/
int device_suspend(pm_message_t state)
int dpm_suspend_start(pm_message_t state)
{
int error;
@@ -822,7 +796,7 @@ int device_suspend(pm_message_t state)
error = dpm_suspend(state);
return error;
}
EXPORT_SYMBOL_GPL(device_suspend);
EXPORT_SYMBOL_GPL(dpm_suspend_start);
void __suspend_report_result(const char *function, void *fn, int ret)
{
+16
View File
@@ -343,11 +343,15 @@ static void __sysdev_resume(struct sys_device *dev)
/* First, call the class-specific one */
if (cls->resume)
cls->resume(dev);
WARN_ONCE(!irqs_disabled(),
"Interrupts enabled after %pF\n", cls->resume);
/* Call auxillary drivers next. */
list_for_each_entry(drv, &cls->drivers, entry) {
if (drv->resume)
drv->resume(dev);
WARN_ONCE(!irqs_disabled(),
"Interrupts enabled after %pF\n", drv->resume);
}
}
@@ -377,6 +381,9 @@ int sysdev_suspend(pm_message_t state)
if (ret)
return ret;
WARN_ONCE(!irqs_disabled(),
"Interrupts enabled while suspending system devices\n");
pr_debug("Suspending System Devices\n");
list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) {
@@ -393,6 +400,9 @@ int sysdev_suspend(pm_message_t state)
if (ret)
goto aux_driver;
}
WARN_ONCE(!irqs_disabled(),
"Interrupts enabled after %pF\n",
drv->suspend);
}
/* Now call the generic one */
@@ -400,6 +410,9 @@ int sysdev_suspend(pm_message_t state)
ret = cls->suspend(sysdev, state);
if (ret)
goto cls_driver;
WARN_ONCE(!irqs_disabled(),
"Interrupts enabled after %pF\n",
cls->suspend);
}
}
}
@@ -452,6 +465,9 @@ int sysdev_resume(void)
{
struct sysdev_class *cls;
WARN_ONCE(!irqs_disabled(),
"Interrupts enabled while resuming system devices\n");
pr_debug("Resuming System Devices\n");
list_for_each_entry(cls, &system_kset->list, kset.kobj.entry) {
+8 -8
View File
@@ -43,7 +43,7 @@ static int xen_suspend(void *data)
if (err) {
printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n",
err);
device_power_up(PMSG_RESUME);
dpm_resume_noirq(PMSG_RESUME);
return err;
}
@@ -69,7 +69,7 @@ static int xen_suspend(void *data)
}
sysdev_resume();
device_power_up(PMSG_RESUME);
dpm_resume_noirq(PMSG_RESUME);
return 0;
}
@@ -92,18 +92,18 @@ static void do_suspend(void)
}
#endif
err = device_suspend(PMSG_SUSPEND);
err = dpm_suspend_start(PMSG_SUSPEND);
if (err) {
printk(KERN_ERR "xen suspend: device_suspend %d\n", err);
printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err);
goto out;
}
printk(KERN_DEBUG "suspending xenstore...\n");
xs_suspend();
err = device_power_down(PMSG_SUSPEND);
err = dpm_suspend_noirq(PMSG_SUSPEND);
if (err) {
printk(KERN_ERR "device_power_down failed: %d\n", err);
printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err);
goto resume_devices;
}
@@ -119,10 +119,10 @@ static void do_suspend(void)
} else
xs_suspend_cancel();
device_power_up(PMSG_RESUME);
dpm_resume_noirq(PMSG_RESUME);
resume_devices:
device_resume(PMSG_RESUME);
dpm_resume_end(PMSG_RESUME);
/* Make sure timer events get retriggered on all CPUs */
clock_was_set();