SERIAL Serial support is enabled.
SMP The kernel is an SMP kernel.
SOUND Appropriate sound system support is enabled.
+ SWSUSP Software suspension is enabled.
V4L Video For Linux support is enabled.
VGA The VGA console has been enabled.
VT Virtual terminal support is enabled.
initial RAM disk.
nointroute [IA-64]
+
+ noresume [SWSUSP] Disables resume and restore original swap space.
no-scroll [VGA]
reserve= [KNL,BUGS] force the kernel to ignore some iomem area.
+ resume= [SWSUSP] specify the partition device for software suspension.
+
riscom8= [HW,SERIAL]
ro [KNL] Mount root device read-only on boot.
ENTRY(saved_magic) .long 0
ENTRY(saved_magic2) .long 0
-ENTRY(saved_videomode) .long 0
ALIGN
# saved registers
static int disable_x86_serial_nr __initdata = 1;
static int disable_x86_fxsr __initdata = 0;
+unsigned long saved_videomode;
+
extern unsigned long saved_videomode;
/*
drive_info = DRIVE_INFO;
screen_info = SCREEN_INFO;
apm_info.bios = APM_BIOS_INFO;
-#ifdef CONFIG_ACPI_SLEEP
saved_videomode = VIDEO_MODE;
printk("Video mode to be used for restore is %lx\n", saved_videomode);
-#endif
if( SYS_DESC_TABLE.length != 0 ) {
MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
machine_id = SYS_DESC_TABLE.table[0];
if (!system->states[state])
return_VALUE(-ENODEV);
-
#ifdef CONFIG_SOFTWARE_SUSPEND
if (state == 4) {
- /* We are working from process context, that's why we may call it directly. */
- do_software_suspend();
+ software_suspend();
return_VALUE(count);
}
#endif
static int have_no_fdc= -ENODEV;
-static struct device device_floppy;
+static struct device device_floppy = {
+ name: "floppy",
+ bus_id: "03?0",
+};
int __init floppy_init(void)
{
int i,unit,drive;
- strcpy(device_floppy.name, "floppy");
- strcpy(device_floppy.bus_id, "03?0");
register_sys_device(&device_floppy);
raw_cmd = NULL;
daemonize();
sprintf(current->comm, "loop%d", lo->lo_number);
- current->flags |= PF_IOTHREAD;
+ current->flags |= PF_IOTHREAD; /* loop can be used in an encrypted device
+ hence, it mustn't be stopped at all because it could
+ be indirectly used during suspension */
spin_lock_irq(¤t->sigmask_lock);
sigfillset(¤t->blocked);
#endif
#include <linux/usb.h>
#include <linux/usbdevice_fs.h>
+#include <linux/suspend.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
/* Send me a signal to get me die (for debugging) */
do {
usb_hub_events();
+ if (current->flags & PF_FREEZE)
+ refrigerator(PF_IOTHREAD);
wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list));
} while (!signal_pending(current));
wake_up_buffer(bh);
}
-DECLARE_TASK_QUEUE(tq_bdflush);
-
/*
* Block until a buffer comes unlocked. This doesn't stop it
* from becoming locked again - you have to lock it yourself
journal->j_commit_interval / HZ);
list_add(&journal->j_all_journals, &all_journals);
- current->flags |= PF_KERNTHREAD;
/* And now, wait forever for commit wakeup events. */
while (1) {
if (journal->j_flags & JFS_UNMOUNT)
spin_unlock_irq(¤t->sigmask_lock);
sprintf(current->comm, "kreiserfsd") ;
- current->flags |= PF_KERNTHREAD;
lock_kernel() ;
while(1) {
-#ifndef __ASM_I386_SUSPEND_H
-#define __ASM_I386_SUSPEND_H
-#endif
-
/*
* Copyright 2001-2002 Pavel Machek <pavel@suse.cz>
* Based on code
* Copyright 2001 Patrick Mochel <mochel@osdl.org>
*/
-#if defined(SUSPEND_C) || defined(ACPI_C)
#include <asm/desc.h>
#include <asm/i387.h>
do_fpu_end();
}
-#endif
#ifdef SUSPEND_C
/* Local variables for do_magic */
static int loop __nosavedata = 0;
#ifndef _LINUX_SWSUSP_H
#define _LINUX_SWSUSP_H
+#if defined(SUSPEND_C) || defined(ACPI_C)
#include <asm/suspend.h>
+#endif
#include <linux/swap.h>
#include <linux/notifier.h>
#include <linux/config.h>
#define DECLARE_TASK_QUEUE(q) LIST_HEAD(q)
#define TQ_ACTIVE(q) (!list_empty(&q))
-extern task_queue tq_timer, tq_immediate, tq_bdflush;
+extern task_queue tq_timer, tq_immediate;
/*
* To implement your own list of active bottom halfs, use the following
/*
- * linux/kernel/swsusp.c
+ * linux/kernel/suspend.c
*
* This file is to realize architecture-independent
* machine suspend feature using pretty near only high-level routines
* For TODOs,FIXMEs also look in Documentation/swsusp.txt
*/
-/*
- * TODO:
- *
- * - we should launch a kernel_thread to process suspend request, cleaning up
- * bdflush from this task. (check apm.c for something similar).
- */
-
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/swapctl.h>
#include <linux/swap.h>
#include <linux/pm.h>
#include <linux/device.h>
+#include <linux/buffer_head.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
we probably do not take enough locks for switching consoles, etc,
so bad things might happen.
*/
-#ifndef CONFIG_VT
+#if !defined(CONFIG_VT) || !defined(CONFIG_VT_CONSOLE)
#undef SUSPEND_CONSOLE
#endif
#define DEBUG_DEFAULT 1
#undef DEBUG_PROCESS
#undef DEBUG_SLOW
-#define TEST_SWSUSP 0 /* Set to 1 to reboot instead of halt machine after suspension */
+#define TEST_SWSUSP 1 /* Set to 1 to reboot instead of halt machine after suspension */
#ifdef DEBUG_DEFAULT
#define PRINTD(func, f, a...) \
machine_restart(NULL);
else
#endif
+ {
+ device_shutdown();
machine_power_off();
+ }
printk(KERN_EMERG "%sProbably not capable for powerdown. System halted.\n", name_suspend);
machine_halt();
/* NOTREACHED */
}
-/* forward decl */
-void do_software_suspend(void);
-
/*
* Magic happens here
*/
#ifdef SUSPEND_CONSOLE
update_screen(fg_console); /* Hmm, is this the problem? */
#endif
- suspend_tq.routine = (void *)do_software_suspend;
}
static void do_magic_suspend_1(void)
drivers_resume(RESUME_PHASE1);
spin_unlock_irq(&suspend_pagedir_lock);
mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
- suspend_tq.routine = (void *)do_software_suspend;
printk(KERN_WARNING "%sLeaving do_magic_suspend_2...\n", name_suspend);
}
#include <asm/suspend.h>
/*
- * This function is triggered using process bdflush. We try to swap out as
- * much as we can then make a copy of the occupied pages in memory so we can
- * make a copy of kernel state atomically, the I/O needed by saving won't
- * bother us anymore.
+ * We try to swap out as much as we can then make a copy of the
+ * occupied pages in memory so we can make a copy of kernel state
+ * atomically, the I/O needed by saving won't bother us anymore.
*/
void do_software_suspend(void)
{
arch_prepare_suspend();
- if (!prepare_suspend_console()) {
- if (!prepare_suspend_processes()) {
- free_some_memory();
-
- /* No need to invalidate any vfsmnt list -- they will be valid after resume, anyway.
- *
- * We sync here -- so you have consistent filesystem state when things go wrong.
- * -- so that noone writes to disk after we do atomic copy of data.
- */
- PRINTS("Syncing disks before copy\n");
- do_suspend_sync();
- if(drivers_suspend()==0)
- do_magic(0); /* This function returns after machine woken up from resume */
- PRINTR("Restarting processes...\n");
- thaw_processes();
- }
+ if (prepare_suspend_console())
+ printk( "Can't allocate a console... proceeding\n");
+ if (!prepare_suspend_processes()) {
+ free_some_memory();
+
+ /* No need to invalidate any vfsmnt list -- they will be valid after resume, anyway.
+ *
+ * We sync here -- so you have consistent filesystem state when things go wrong.
+ * -- so that noone writes to disk after we do atomic copy of data.
+ */
+ PRINTS("Syncing disks before copy\n");
+ do_suspend_sync();
+ if(drivers_suspend()==0)
+ do_magic(0); /* This function returns after machine woken up from resume */
+ PRINTR("Restarting processes...\n");
+ thaw_processes();
}
software_suspend_enabled = 1;
MDELAY(1000);
restore_console ();
}
-struct tq_struct suspend_tq =
- { routine: (void *)(void *)do_software_suspend,
- data: 0 };
-
/*
- * This is the trigger function, we must queue ourself since we
- * can be called from interrupt && bdflush context is needed
+ * This is main interface to the outside world. It needs to be
+ * called from process context.
*/
void software_suspend(void)
{
return;
software_suspend_enabled = 0;
- queue_task(&suspend_tq, &tq_bdflush);
- wakeup_bdflush();
+ BUG_ON(in_interrupt());
+ do_software_suspend();
}
/* More restore stuff */
pagedir_order = get_bitmask_order(nr_pgdir_pages);
error = -ENOMEM;
+ free_page((unsigned long) cur);
pagedir_nosave = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC, pagedir_order);
if(!pagedir_nosave)
goto resume_read_error;
}
#ifdef CONFIG_SOFTWARE_SUSPEND
-int is_head_of_free_region(struct page *p)
+int is_head_of_free_region(struct page *page)
{
- pg_data_t *pgdat = pgdat_list;
- unsigned type;
- unsigned long flags;
-
- for (type=0;type < MAX_NR_ZONES; type++) {
- zone_t *zone = pgdat->node_zones + type;
- int order = MAX_ORDER - 1;
- free_area_t *area;
- struct list_head *head, *curr;
- spin_lock_irqsave(&zone->lock, flags); /* Should not matter as we need quiescent system for suspend anyway, but... */
-
- do {
- area = zone->free_area + order;
- head = &area->free_list;
- curr = head;
+ zone_t *zone = page_zone(page);
+ unsigned long flags;
+ int order;
+ list_t *curr;
- for(;;) {
- if(!curr) {
-// printk("FIXME: this should not happen but it does!!!");
- break;
- }
- if(p != memlist_entry(curr, struct page, list)) {
- curr = memlist_next(curr);
- if (curr == head)
- break;
- continue;
- }
+ /*
+ * Should not matter as we need quiescent system for
+ * suspend anyway, but...
+ */
+ spin_lock_irqsave(&zone->lock, flags);
+ for (order = MAX_ORDER - 1; order >= 0; --order)
+ list_for_each(curr, &zone->free_area[order].free_list)
+ if (page == list_entry(curr, struct page, list)) {
+ spin_unlock_irqrestore(&zone->lock, flags);
return 1 << order;
}
- } while(order--);
- spin_unlock_irqrestore(&zone->lock, flags);
-
- }
- return 0;
+ spin_unlock_irqrestore(&zone->lock, flags);
+ return 0;
}
#endif /* CONFIG_SOFTWARE_SUSPEND */
recalc_sigpending();
spin_unlock_irq(¤t->sigmask_lock);
- current->flags |= PF_FLUSHER | PF_KERNTHREAD;
+ current->flags |= PF_FLUSHER;
my_work->fn = NULL;
my_work->who = current;
set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irq(&pdflush_lock);
-#ifdef CONFIG_SOFTWARE_SUSPEND
- run_task_queue(&tq_bdflush);
if (current->flags & PF_FREEZE)
refrigerator(PF_IOTHREAD);
-#endif
schedule();
if (my_work->fn)
* us from recursively trying to free more memory as we're
* trying to free the first piece of memory in the first place).
*/
- tsk->flags |= PF_MEMALLOC | PF_KERNTHREAD;
+ tsk->flags |= PF_MEMALLOC;
/*
* Kswapd main loop.