Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 139000
b: refs/heads/master
c: 2ed8d2b
h: refs/heads/master
v: v3
  • Loading branch information
Rafael J. Wysocki committed Mar 30, 2009
1 parent eae1bed commit 2e441ff
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 41 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0a0c5168df270a50e3518e4f12bddb31f8f5f38f
refs/heads/master: 2ed8d2b3a81bdbb0418301628ccdb008ac9f40b7
15 changes: 11 additions & 4 deletions trunk/arch/x86/kernel/apm_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -1190,8 +1190,10 @@ static int suspend(int vetoable)
struct apm_user *as;

device_suspend(PMSG_SUSPEND);
local_irq_disable();

device_power_down(PMSG_SUSPEND);

local_irq_disable();
sysdev_suspend(PMSG_SUSPEND);

local_irq_enable();
Expand All @@ -1209,9 +1211,12 @@ static int suspend(int vetoable)
if (err != APM_SUCCESS)
apm_error("suspend", err);
err = (err == APM_SUCCESS) ? 0 : -EIO;

sysdev_resume();
device_power_up(PMSG_RESUME);
local_irq_enable();

device_power_up(PMSG_RESUME);

device_resume(PMSG_RESUME);
queue_event(APM_NORMAL_RESUME, NULL);
spin_lock(&user_list_lock);
Expand All @@ -1228,8 +1233,9 @@ static void standby(void)
{
int err;

local_irq_disable();
device_power_down(PMSG_SUSPEND);

local_irq_disable();
sysdev_suspend(PMSG_SUSPEND);
local_irq_enable();

Expand All @@ -1239,8 +1245,9 @@ static void standby(void)

local_irq_disable();
sysdev_resume();
device_power_up(PMSG_RESUME);
local_irq_enable();

device_power_up(PMSG_RESUME);
}

static apm_event_t get_event(void)
Expand Down
20 changes: 11 additions & 9 deletions trunk/drivers/base/power/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <linux/pm.h>
#include <linux/resume-trace.h>
#include <linux/rwsem.h>
#include <linux/interrupt.h>

#include "../base.h"
#include "power.h"
Expand Down Expand Up @@ -349,7 +350,8 @@ static int resume_device_noirq(struct device *dev, pm_message_t state)
* Execute the appropriate "noirq resume" callback for all devices marked
* as DPM_OFF_IRQ.
*
* Must be called with interrupts disabled and only one CPU running.
* 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)
{
Expand All @@ -370,14 +372,13 @@ static void dpm_power_up(pm_message_t state)
* device_power_up - Turn on all devices that need special attention.
* @state: PM transition of the system being carried out.
*
* Power on system devices, then devices that required we shut them down
* with interrupts disabled.
*
* Must be called with interrupts disabled.
* 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);

Expand Down Expand Up @@ -602,16 +603,17 @@ static int suspend_device_noirq(struct device *dev, pm_message_t state)
* device_power_down - Shut down special devices.
* @state: PM transition of the system being carried out.
*
* Power down devices that require interrupts to be disabled.
* Then power down system devices.
* Prevent device drivers from receiving interrupts and call the "late"
* suspend handlers.
*
* Must be called with interrupts disabled and only one CPU running.
* Must be called under dpm_list_mtx.
*/
int device_power_down(pm_message_t state)
{
struct device *dev;
int error = 0;

suspend_device_irqs();
list_for_each_entry_reverse(dev, &dpm_list, power.entry) {
error = suspend_device_noirq(dev, state);
if (error) {
Expand All @@ -621,7 +623,7 @@ int device_power_down(pm_message_t state)
dev->power.status = DPM_OFF_IRQ;
}
if (error)
dpm_power_up(resume_event(state));
device_power_up(resume_event(state));
return error;
}
EXPORT_SYMBOL_GPL(device_power_down);
Expand Down
8 changes: 8 additions & 0 deletions trunk/drivers/base/sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <linux/pm.h>
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/interrupt.h>

#include "base.h"

Expand Down Expand Up @@ -369,6 +370,13 @@ int sysdev_suspend(pm_message_t state)
struct sysdev_driver *drv, *err_drv;
int ret;

pr_debug("Checking wake-up interrupts\n");

/* Return error code if there are any wake-up interrupts pending */
ret = check_wakeup_irqs();
if (ret)
return ret;

pr_debug("Suspending System Devices\n");

list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) {
Expand Down
16 changes: 9 additions & 7 deletions trunk/drivers/xen/manage.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,6 @@ static int xen_suspend(void *data)

BUG_ON(!irqs_disabled());

err = device_power_down(PMSG_SUSPEND);
if (err) {
printk(KERN_ERR "xen_suspend: device_power_down failed: %d\n",
err);
return err;
}
err = sysdev_suspend(PMSG_SUSPEND);
if (err) {
printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n",
Expand All @@ -69,7 +63,6 @@ static int xen_suspend(void *data)
xen_mm_unpin_all();

sysdev_resume();
device_power_up(PMSG_RESUME);

if (!*cancelled) {
xen_irq_resume();
Expand Down Expand Up @@ -108,6 +101,12 @@ static void do_suspend(void)
/* XXX use normal device tree? */
xenbus_suspend();

err = device_power_down(PMSG_SUSPEND);
if (err) {
printk(KERN_ERR "device_power_down failed: %d\n", err);
goto resume_devices;
}

err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
if (err) {
printk(KERN_ERR "failed to start xen_suspend: %d\n", err);
Expand All @@ -120,6 +119,9 @@ static void do_suspend(void)
} else
xenbus_suspend_cancel();

device_power_up(PMSG_RESUME);

resume_devices:
device_resume(PMSG_RESUME);

/* Make sure timer events get retriggered on all CPUs */
Expand Down
8 changes: 4 additions & 4 deletions trunk/kernel/kexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,6 @@ int kernel_kexec(void)
if (error)
goto Resume_devices;
device_pm_lock();
local_irq_disable();
/* At this point, device_suspend() has been called,
* but *not* device_power_down(). We *must*
* device_power_down() now. Otherwise, drivers for
Expand All @@ -1464,8 +1463,9 @@ int kernel_kexec(void)
*/
error = device_power_down(PMSG_FREEZE);
if (error)
goto Enable_irqs;
goto Unlock_pm;

local_irq_disable();
/* Suspend system devices */
error = sysdev_suspend(PMSG_FREEZE);
if (error)
Expand All @@ -1484,9 +1484,9 @@ int kernel_kexec(void)
if (kexec_image->preserve_context) {
sysdev_resume();
Power_up_devices:
device_power_up(PMSG_RESTORE);
Enable_irqs:
local_irq_enable();
device_power_up(PMSG_RESTORE);
Unlock_pm:
device_pm_unlock();
enable_nonboot_cpus();
Resume_devices:
Expand Down
39 changes: 29 additions & 10 deletions trunk/kernel/power/disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ static int create_image(int platform_mode)
return error;

device_pm_lock();
local_irq_disable();

/* At this point, device_suspend() has been called, but *not*
* device_power_down(). We *must* call device_power_down() now.
* Otherwise, drivers for some devices (e.g. interrupt controllers)
Expand All @@ -225,8 +225,11 @@ static int create_image(int platform_mode)
if (error) {
printk(KERN_ERR "PM: Some devices failed to power down, "
"aborting hibernation\n");
goto Enable_irqs;
goto Unlock;
}

local_irq_disable();

sysdev_suspend(PMSG_FREEZE);
if (error) {
printk(KERN_ERR "PM: Some devices failed to power down, "
Expand All @@ -252,12 +255,16 @@ static int create_image(int platform_mode)
/* NOTE: device_power_up() is just a resume() for devices
* that suspended with irqs off ... no overall powerup.
*/

Power_up_devices:
local_irq_enable();

device_power_up(in_suspend ?
(error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
Enable_irqs:
local_irq_enable();

Unlock:
device_pm_unlock();

return error;
}

Expand Down Expand Up @@ -336,13 +343,16 @@ static int resume_target_kernel(void)
int error;

device_pm_lock();
local_irq_disable();

error = device_power_down(PMSG_QUIESCE);
if (error) {
printk(KERN_ERR "PM: Some devices failed to power down, "
"aborting resume\n");
goto Enable_irqs;
goto Unlock;
}

local_irq_disable();

sysdev_suspend(PMSG_QUIESCE);
/* We'll ignore saved state, but this gets preempt count (etc) right */
save_processor_state();
Expand All @@ -366,11 +376,16 @@ static int resume_target_kernel(void)
swsusp_free();
restore_processor_state();
touch_softlockup_watchdog();

sysdev_resume();
device_power_up(PMSG_RECOVER);
Enable_irqs:

local_irq_enable();

device_power_up(PMSG_RECOVER);

Unlock:
device_pm_unlock();

return error;
}

Expand Down Expand Up @@ -447,15 +462,16 @@ int hibernation_platform_enter(void)
goto Finish;

device_pm_lock();
local_irq_disable();

error = device_power_down(PMSG_HIBERNATE);
if (!error) {
local_irq_disable();
sysdev_suspend(PMSG_HIBERNATE);
hibernation_ops->enter();
/* We should never get here */
while (1);
}
local_irq_enable();

device_pm_unlock();

/*
Expand All @@ -464,12 +480,15 @@ int hibernation_platform_enter(void)
*/
Finish:
hibernation_ops->finish();

Resume_devices:
entering_platform_hibernation = false;
device_resume(PMSG_RESTORE);
resume_console();

Close:
hibernation_ops->end();

return error;
}

Expand Down
17 changes: 11 additions & 6 deletions trunk/kernel/power/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,29 +287,34 @@ void __attribute__ ((weak)) arch_suspend_enable_irqs(void)
*/
static int suspend_enter(suspend_state_t state)
{
int error = 0;
int error;

device_pm_lock();
arch_suspend_disable_irqs();
BUG_ON(!irqs_disabled());

if ((error = device_power_down(PMSG_SUSPEND))) {
error = device_power_down(PMSG_SUSPEND);
if (error) {
printk(KERN_ERR "PM: Some devices failed to power down\n");
goto Done;
}

arch_suspend_disable_irqs();
BUG_ON(!irqs_disabled());

error = sysdev_suspend(PMSG_SUSPEND);
if (!error) {
if (!suspend_test(TEST_CORE))
error = suspend_ops->enter(state);
sysdev_resume();
}

device_power_up(PMSG_RESUME);
Done:
arch_suspend_enable_irqs();
BUG_ON(irqs_disabled());

device_power_up(PMSG_RESUME);

Done:
device_pm_unlock();

return error;
}

Expand Down

0 comments on commit 2e441ff

Please sign in to comment.