bitkeeper revision 1.1159.17.21 (411baa1dkWXzaVHGnr6yk4SeGTJAHA)

Merge 2.4/2.6 shutdown/suspend control message handling code.
This commit is contained in:
cl349@freefall.cl.cam.ac.uk committed 2004-08-12 17:34:21 +00:00
1 parent 34948bea5a
commit fa6b5eb32b
4 files changed
+222 -174

No files matched your search

@@ -1184,173 +1184,3 @@ void __init cpu_init (void)
current->used_math = 0;
stts();
}
/******************************************************************************
* Stop/pickle callback handling.
*/
#include <asm/suspend.h>
/* Ignore multiple shutdown requests. */
static int shutting_down = -1;
static void __do_suspend(void)
{
int i,j;
/* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */
extern void blkdev_suspend(void);
extern void blkdev_resume(void);
extern void netif_suspend(void);
extern void netif_resume(void);
extern void time_suspend(void);
extern void time_resume(void);
suspend_record_t *suspend_record = NULL;
if ( (suspend_record = (suspend_record_t *)__get_free_page(GFP_KERNEL))
== NULL )
goto out;
suspend_record->nr_pfns = max_pfn; /* final number of pfns */
__cli();
netif_suspend();
blkdev_suspend();
time_suspend();
ctrl_if_suspend();
irq_suspend();
HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
clear_fixmap(FIX_SHARED_INFO);
memcpy(&suspend_record->resume_info, &start_info, sizeof(start_info));
HYPERVISOR_suspend(virt_to_machine(suspend_record) >> PAGE_SHIFT);
shutting_down = -1;
memcpy(&start_info, &suspend_record->resume_info, sizeof(start_info));
set_fixmap(FIX_SHARED_INFO, start_info.shared_info);
HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
memset(empty_zero_page, 0, PAGE_SIZE);
for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ )
{
pfn_to_mfn_frame_list[j] =
virt_to_machine(&phys_to_machine_mapping[i]) >> PAGE_SHIFT;
}
HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list =
virt_to_machine(pfn_to_mfn_frame_list) >> PAGE_SHIFT;
irq_resume();
ctrl_if_resume();
time_resume();
blkdev_resume();
netif_resume();
__sti();
out:
if ( suspend_record != NULL )
free_page((unsigned long)suspend_record);
}
static int shutdown_process(void *__unused)
{
static char *envp[] = { "HOME=/", "TERM=linux",
"PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
static char *restart_argv[] = { "/sbin/shutdown", "-r", "now", NULL };
static char *poweroff_argv[] = { "/sbin/halt", "-p", NULL };
extern asmlinkage long sys_reboot(int magic1, int magic2,
unsigned int cmd, void *arg);
daemonize();
switch ( shutting_down )
{
case CMSG_SHUTDOWN_POWEROFF:
if ( execve("/sbin/halt", poweroff_argv, envp) < 0 )
{
sys_reboot(LINUX_REBOOT_MAGIC1,
LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_POWER_OFF,
NULL);
}
break;
case CMSG_SHUTDOWN_REBOOT:
if ( execve("/sbin/shutdown", restart_argv, envp) < 0 )
{
sys_reboot(LINUX_REBOOT_MAGIC1,
LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_RESTART,
NULL);
}
break;
}
return 0;
}
static void __shutdown_handler(void *unused)
{
int err;
if ( shutting_down != CMSG_SHUTDOWN_SUSPEND )
{
err = kernel_thread(shutdown_process, NULL, CLONE_FS | CLONE_FILES);
if ( err < 0 )
printk(KERN_ALERT "Error creating shutdown process!\n");
else
shutting_down = -1; /* could try again */
}
else
{
__do_suspend();
}
}
static void shutdown_handler(ctrl_msg_t *msg, unsigned long id)
{
static struct tq_struct shutdown_tq;
if ( (shutting_down == -1) &&
((msg->subtype == CMSG_SHUTDOWN_POWEROFF) ||
(msg->subtype == CMSG_SHUTDOWN_REBOOT) ||
(msg->subtype == CMSG_SHUTDOWN_SUSPEND)) )
{
shutting_down = msg->subtype;
shutdown_tq.routine = __shutdown_handler;
schedule_task(&shutdown_tq);
}
else
{
printk("Ignore spurious shutdown request\n");
}
ctrl_if_send_response(msg);
}
static int __init setup_shutdown_event(void)
{
ctrl_if_register_receiver(CMSG_SHUTDOWN, shutdown_handler, 0);
return 0;
}
__initcall(setup_shutdown_event);
@@ -510,7 +510,7 @@ unsigned long get_cmos_time(void)
static long clock_cmos_diff;
static int time_suspend(struct sys_device *dev, u32 state)
static int __time_suspend(struct sys_device *dev, u32 state)
{
/*
* Estimate time zone so that set_time can update the clock
@@ -520,7 +520,7 @@ static int time_suspend(struct sys_device *dev, u32 state)
return 0;
}
static int time_resume(struct sys_device *dev)
static int __time_resume(struct sys_device *dev)
{
unsigned long sec = get_cmos_time() + clock_cmos_diff;
write_seqlock_irq(&xtime_lock);
@@ -531,8 +531,8 @@ static int time_resume(struct sys_device *dev)
}
static struct sysdev_class pit_sysclass = {
.resume = time_resume,
.suspend = time_suspend,
.resume = __time_resume,
.suspend = __time_suspend,
set_kset_name("pit"),
};
@@ -647,6 +647,25 @@ int set_timeout_timer(void)
return ret;
}
void time_suspend(void)
{
}
void time_resume(void)
{
unsigned long flags;
write_lock_irqsave(&xtime_lock, flags);
/* Get timebases for new environment. */
__get_time_values_from_xen();
/* Reset our own concept of passage of system time. */
processed_system_time = shadow_system_time;
/* Accept a warp in UTC (wall-clock) time. */
last_seen_tv.tv_sec = 0;
/* Make sure we resync UTC time with Xen on next timer interrupt. */
last_update_from_xen = 0;
write_unlock_irqrestore(&xtime_lock, flags);
}
/*
* /proc/sys/xen: This really belongs in another file. It can stay here for
* now however.
@@ -1,8 +1,19 @@
#define __KERNEL_SYSCALLS__
static int errno;
#include <linux/errno.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/unistd.h>
#include <linux/module.h>
#include <linux/reboot.h>
#include <asm/irq.h>
#include <asm/mmu_context.h>
#include <asm-xen/ctrl_if.h>
#include <asm-xen/hypervisor.h>
#include <asm-xen/hypervisor-ifs/dom0_ops.h>
#include <asm-xen/suspend.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
int reboot_thru_bios = 0; /* for dmi_scan.c */
@@ -40,3 +51,188 @@ void machine_power_off(void)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
EXPORT_SYMBOL(machine_power_off);
#endif
/******************************************************************************
* Stop/pickle callback handling.
*/
#include <asm/suspend.h>
/* Ignore multiple shutdown requests. */
static int shutting_down = -1;
static void __do_suspend(void)
{
int i,j;
/* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */
extern void blkdev_suspend(void);
extern void blkdev_resume(void);
extern void netif_suspend(void);
extern void netif_resume(void);
extern void time_suspend(void);
extern void time_resume(void);
extern unsigned long max_pfn;
extern unsigned long *pfn_to_mfn_frame_list;
suspend_record_t *suspend_record = NULL;
if ( (suspend_record = (suspend_record_t *)__get_free_page(GFP_KERNEL))
== NULL )
goto out;
suspend_record->nr_pfns = max_pfn; /* final number of pfns */
__cli();
netif_suspend();
blkdev_suspend();
time_suspend();
ctrl_if_suspend();
irq_suspend();
HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
clear_fixmap(FIX_SHARED_INFO);
memcpy(&suspend_record->resume_info, &start_info, sizeof(start_info));
HYPERVISOR_suspend(virt_to_machine(suspend_record) >> PAGE_SHIFT);
shutting_down = -1;
memcpy(&start_info, &suspend_record->resume_info, sizeof(start_info));
set_fixmap(FIX_SHARED_INFO, start_info.shared_info);
HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
memset(empty_zero_page, 0, PAGE_SIZE);
for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ )
{
pfn_to_mfn_frame_list[j] =
virt_to_machine(&phys_to_machine_mapping[i]) >> PAGE_SHIFT;
}
HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list =
virt_to_machine(pfn_to_mfn_frame_list) >> PAGE_SHIFT;
irq_resume();
ctrl_if_resume();
time_resume();
blkdev_resume();
netif_resume();
__sti();
out:
if ( suspend_record != NULL )
free_page((unsigned long)suspend_record);
}
static int shutdown_process(void *__unused)
{
static char *envp[] = { "HOME=/", "TERM=linux",
"PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
static char *restart_argv[] = { "/sbin/shutdown", "-r", "now", NULL };
static char *poweroff_argv[] = { "/sbin/halt", "-p", NULL };
extern asmlinkage long sys_reboot(int magic1, int magic2,
unsigned int cmd, void *arg);
daemonize(
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
"shutdown"
#endif
);
switch ( shutting_down )
{
case CMSG_SHUTDOWN_POWEROFF:
if ( execve("/sbin/halt", poweroff_argv, envp) < 0 )
{
sys_reboot(LINUX_REBOOT_MAGIC1,
LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_POWER_OFF,
NULL);
}
break;
case CMSG_SHUTDOWN_REBOOT:
if ( execve("/sbin/shutdown", restart_argv, envp) < 0 )
{
sys_reboot(LINUX_REBOOT_MAGIC1,
LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_RESTART,
NULL);
}
break;
}
shutting_down = -1; /* could try again */
return 0;
}
static void __shutdown_handler(void *unused)
{
int err;
if ( shutting_down != CMSG_SHUTDOWN_SUSPEND )
{
err = kernel_thread(shutdown_process, NULL, CLONE_FS | CLONE_FILES);
if ( err < 0 )
printk(KERN_ALERT "Error creating shutdown process!\n");
}
else
{
__do_suspend();
}
}
static void shutdown_handler(ctrl_msg_t *msg, unsigned long id)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
#else
static struct tq_struct shutdown_tq;
#endif
if ( (shutting_down == -1) &&
((msg->subtype == CMSG_SHUTDOWN_POWEROFF) ||
(msg->subtype == CMSG_SHUTDOWN_REBOOT) ||
(msg->subtype == CMSG_SHUTDOWN_SUSPEND)) )
{
shutting_down = msg->subtype;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
schedule_work(&shutdown_work);
#else
shutdown_tq.routine = __shutdown_handler;
schedule_task(&shutdown_tq);
#endif
}
else
{
printk("Ignore spurious shutdown request\n");
}
ctrl_if_send_response(msg);
}
static int __init setup_shutdown_event(void)
{
ctrl_if_register_receiver(CMSG_SHUTDOWN, shutdown_handler, 0);
return 0;
}
__initcall(setup_shutdown_event);
@@ -140,6 +140,9 @@ extern int bind_virq_to_irq(int virq);
extern void unbind_virq_from_irq(int virq);
extern int bind_evtchn_to_irq(int evtchn);
extern void unbind_evtchn_from_irq(int evtchn);
extern void irq_suspend(void);
extern void irq_resume(void);
#endif /* __ASSEMBLY__ */
#endif /* _ASM_IRQ_VECTORS_H */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.