Commit c0f4364d authored by Russell King's avatar Russell King

[ARM] Make ARM use Pat's generic PM suspend to RAM support

Hook the PXA and SA11x0 platform core power into the generic PM core.
Add support for freezing userspace processes.  Make our apm emulation
call the generic PM suspend to memory infrastructure.
parent d40c6174
......@@ -179,13 +179,10 @@ static void queue_event(apm_event_t event, struct apm_user *sender)
wake_up_interruptible(&apm_waitqueue);
}
/* defined in pm.c */
extern int suspend(void);
static int apm_suspend(void)
{
struct list_head *l;
int err = suspend();
int err = pm_suspend(PM_SUSPEND_MEM);
/*
* Anyone on the APM queues will think we're still suspended.
......
......@@ -9,63 +9,18 @@
* sleep.
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/sysctl.h>
#include <linux/pm.h>
#include <linux/device.h>
#include <linux/sysdev.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <asm/system.h>
/*
* Tell the linker that pm_do_suspend may not be present.
*/
extern int pm_do_suspend(void) __attribute__((weak));
int suspend(void)
{
int ret;
if (!pm_do_suspend)
return -ENOSYS;
/*
* Suspend "legacy" devices.
*/
ret = pm_send_all(PM_SUSPEND, (void *)3);
if (ret != 0)
goto out;
ret = device_suspend(3);
if (ret)
goto resume_legacy;
local_irq_disable();
sysdev_suspend(3);
ret = pm_do_suspend();
sysdev_resume();
local_irq_enable();
device_resume();
resume_legacy:
pm_send_all(PM_RESUME, (void *)0);
out:
return ret;
}
#ifdef CONFIG_SYSCTL
/*
* We really want this to die. It's a disgusting hack using unallocated
* sysctl numbers. We should be using a real interface.
*/
#include <linux/init.h>
#include <linux/sysctl.h>
static int
pm_sysctl_proc_handler(ctl_table *ctl, int write, struct file *filp,
void *buffer, size_t *lenp)
......@@ -74,7 +29,7 @@ pm_sysctl_proc_handler(ctl_table *ctl, int write, struct file *filp,
printk("PM: task %s (pid %d) uses deprecated sysctl PM interface\n",
current->comm, current->pid);
if (write)
ret = suspend();
ret = pm_suspend(PM_SUSPEND_MEM);
return ret;
}
......
......@@ -21,6 +21,7 @@
#include <linux/tty.h>
#include <linux/binfmts.h>
#include <linux/elf.h>
#include <linux/suspend.h>
#include <asm/pgalloc.h>
#include <asm/ucontext.h>
......@@ -539,6 +540,11 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
if (!user_mode(regs))
return 0;
if (current->flags & PF_FREEZE) {
refrigerator(0);
goto no_signal;
}
if (current->ptrace & PT_SINGLESTEP)
ptrace_cancel_bpt(current);
......@@ -550,6 +556,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
return 1;
}
no_signal:
/*
* No signal to deliver to the process - restart the syscall.
*/
......
......@@ -11,13 +11,14 @@
* modify it under the terms of the GNU General Public License.
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/suspend.h>
#include <linux/errno.h>
#include <linux/time.h>
#include <asm/hardware.h>
#include <asm/memory.h>
#include <asm/system.h>
#include <asm/leds.h>
/*
......@@ -60,13 +61,16 @@ enum { SLEEP_SAVE_START = 0,
};
int pm_do_suspend(void)
static int pxa_pm_enter(u32 state)
{
unsigned long sleep_save[SLEEP_SAVE_SIZE];
unsigned long checksum = 0;
unsigned long delta;
int i;
if (state != PM_SUSPEND_MEM)
return -EINVAL;
/* preserve current time */
delta = xtime.tv_sec - RCNR;
......@@ -194,3 +198,37 @@ unsigned long sleep_phys_sp(void *sp)
{
return virt_to_phys(sp);
}
/*
* Called after processes are frozen, but before we shut down devices.
*/
static int pxa_pm_prepare(u32 state)
{
return 0;
}
/*
* Called after devices are re-setup, but before processes are thawed.
*/
static int pxa_pm_finish(u32 state)
{
return 0;
}
/*
* Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
*/
static struct pm_ops pxa_pm_ops = {
.pm_disk_mode = PM_DISK_FIRMWARE,
.prepare = pxa_pm_prepare,
.enter = pxa_pm_enter,
.finish = pxa_pm_finish,
};
static int __init pxa_pm_init(void)
{
pm_set_ops(&pxa_pm_ops);
return 0;
}
late_initcall(pxa_pm_init);
......@@ -22,6 +22,8 @@
* 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array.
* Storage is local on the stack now.
*/
#include <linux/init.h>
#include <linux/suspend.h>
#include <linux/errno.h>
#include <linux/time.h>
......@@ -54,11 +56,14 @@ enum { SLEEP_SAVE_SP = 0,
};
int pm_do_suspend(void)
static int sa11x0_pm_enter(u32 state)
{
unsigned long sleep_save[SLEEP_SAVE_SIZE];
unsigned long delta, gpio;
if (state != PM_SUSPEND_MEM)
return -EINVAL;
/* preserve current time */
delta = xtime.tv_sec - RCNR;
gpio = GPLR;
......@@ -139,3 +144,37 @@ unsigned long sleep_phys_sp(void *sp)
{
return virt_to_phys(sp);
}
/*
* Called after processes are frozen, but before we shut down devices.
*/
static int sa11x0_pm_prepare(u32 state)
{
return 0;
}
/*
* Called after devices are re-setup, but before processes are thawed.
*/
static int sa11x0_pm_finish(u32 state)
{
return 0;
}
/*
* Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
*/
static struct pm_ops sa11x0_pm_ops = {
.pm_disk_mode = PM_DISK_FIRMWARE,
.prepare = sa11x0_pm_prepare,
.enter = sa11x0_pm_enter,
.finish = sa11x0_pm_finish,
};
static int __init sa11x0_pm_init(void)
{
pm_set_ops(&sa11x0_pm_ops);
return 0;
}
late_initcall(sa11x0_pm_init);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment