swsusp for 2.5.10
Subsystems (19)
Hi!
Changes: ported to 2.5.10, incorporated suggestions by
A.Morton. Please apply (if you prefer, I can split it to 3 pieces like I did before),
Pavel
CREDITS +15 -1
@@ -503,6 +503,14 @@ S: Fremont, California 94539 S: USA +N: Florent Chabaud +E: [email protected] +D: software suspend +S: SGDN/DCSSI +S: 58, Bd Latour-Maubourg +S: 75700 Paris 07 SP +S: France + N: Gordon Chaffee E: [email protected] W: http://bmrc.berkeley.edu/people/chaffee/
@@ -1707,6 +1715,11 @@ S: D-91080 Uttenreuth S: Germany +N: Gabor Kuti +E: [email protected] +E: [email protected] +D: Author and Maintainer for Software Suspend + N: Jaroslav Kysela E: [email protected] W: http://www.perex.cz
@@ -1884,7 +1897,8 @@ E: [email protected] E: [email protected] D: Softcursor for vga, hypertech cdrom support, vcsa bugfix, nbd -D: sun4/330 port, capabilities for elf, speedup for rm on ext2, USB +D: sun4/330 port, capabilities for elf, speedup for rm on ext2, USB, +D: x86-64 port, software suspend S: Volkova 1131 S: 198 00 Praha 9 S: Czech Republic
Documentation/swsusp.txt +159 -0
159 lines not on this page · raw message
MAINTAINERS +8 -0
@@ -1421,6 +1421,14 @@ L: [email protected] S: Maintained +SOFTWARE SUSPEND: +P: Gabor Kuti +M: [email protected] +M: [email protected] +L: http://lister.fornax.hu/mailman/listinfo/swsusp +W: http://falcon.sch.bme.hu/~seasons/linux +S: Maintained + SONIC NETWORK DRIVER P: Thomas Bogendoerfer M: [email protected]
arch/i386/Config.help +25 -0
@@ -936,3 +936,28 @@ CONFIG_DEBUG_OBSOLETE Say Y here if you want to reduce the chances of the tree compiling, and are prepared to dig into driver internals to fix compile errors. + +Software Suspend +CONFIG_SOFTWARE_SUSPEND + Enable the possibilty of suspendig machine. It doesn't need APM. + You may suspend your machine by either pressing Sysrq-d or with + 'swsusp' or 'shutdown -z <time>' (patch for sysvinit needed). It + creates an image which is saved in your active swaps. By the next + booting the kernel detects the saved image, restores the memory from + it and then it continues to run as before you've suspended. + If you don't want the previous state to continue use the 'noresume' + kernel option. However note that your partitions will be fsck'd and + you must re-mkswap your swap partitions/files. + + Right now you may boot without resuming and then later resume but + in meantime you cannot use those swap partitions/files which were + involved in suspending. Also in this case there is a risk that buffers + on disk won't match with saved ones. + + SMP is supported ``as-is''. There's a code for it but doesn't work. + There have been problems reported relating SCSI. + + This option is about getting stable. However there is still some + absence of features. + + For more information take a look at Documentation/swsusp.txt.
Only in linux-swsusp/arch/i386/boot: bbootsect Only in linux-swsusp/arch/i386/boot: bsetup
Only in linux-swsusp/arch/i386/boot: bzImage
Only in linux-swsusp/arch/i386/boot/compressed: bvmlinux Only in linux-swsusp/arch/i386/boot/compressed: bvmlinux.out
arch/i386/config.in +3 -0
@@ -396,6 +396,9 @@ mainmenu_option next_comment comment 'Kernel hacking' +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + dep_bool 'Software Suspend' CONFIG_SOFTWARE_SUSPEND $CONFIG_PM +fi bool 'Kernel debugging' CONFIG_DEBUG_KERNEL if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
arch/i386/defconfig +1 -0
@@ -118,6 +118,7 @@ CONFIG_BINFMT_MISC=y CONFIG_PM=y # CONFIG_APM is not set +# CONFIG_SOFTWARE_SUSPEND is not set # # Memory Technology Devices (MTD)
arch/i386/kernel/apm.c +1 -0
@@ -1667,6 +1667,7 @@daemonize ();strcpy (current->comm,"kapmd" ); + current->flags |=PF_IOTHREAD ;sigfillset (¤t->blocked);if (apm_info.connection_version ==0 ) {
arch/i386/kernel/signal.c +7 -0
@@ -21,6 +21,7 @@#include <linux/tty.h> #include <linux/personality.h> #include <linux/binfmts.h> +#include <linux/suspend.h> #include <asm/ucontext.h> #include <asm/uaccess.h> #include <asm/i387.h>
@@ -594,6 +595,11 @@if ((regs->xcs &3 ) !=3 )return 1 ; +if (current->flags &PF_FREEZE ) { +refrigerator (0 ); + goto no_signal; + } +if (!oldset) oldset = ¤t->blocked;
@@ -701,6 +707,7 @@return 1 ; } + no_signal:/* Did we come from a system call? */ if (regs->orig_eax >=0 ) {/* Restart the system call - no handlers present */
arch/i386/vmlinux.lds +6 -0
@@ -65,6 +65,12 @@ __init_end = .; . = ALIGN(4096); + __nosave_begin = .; + .data_nosave : { *(.data.nosave) } + . = ALIGN(4096); + __nosave_end = .; + + . = ALIGN(4096); .data.page_aligned : { *(.data.idt) } . = ALIGN(32);
drivers/acpi/acpi_system.c +12 -0
@@ -700,8 +700,16 @@if (!system->states[state])return_VALUE (-ENODEV ); + +#ifdef CONFIG_SOFTWARE_SUSPEND +if (state ==4 ) { +software_suspend (); +return_VALUE (count); + } +#endif status =acpi_suspend (state); +if (ACPI_FAILURE (status))return_VALUE (-ENODEV );
@@ -1180,6 +1188,10 @@ } }printk (")\n" ); +#ifdef CONFIG_SOFTWARE_SUSPEND +printk (KERN_INFO "Software suspend => we can do S4." ); + system->states[4 ] =1 ; +#endif #ifdef CONFIG_PM /* Install the soft-off (S5) handler. */
drivers/block/loop.c +3 -3
@@ -71,11 +71,11 @@#include <linux/smp_lock.h> #include <linux/swap.h> #include <linux/slab.h> +#include <linux/loop.h> +#include <linux/suspend.h> #include <asm/uaccess.h> -#include <linux/loop.h> -#define MAJOR_NR LOOP_MAJORstatic int max_loop =8 ;
@@ -550,7 +550,7 @@atomic_inc (&lo->lo_pending);spin_unlock_irq (&lo->lo_lock); - current->flags |=PF_NOIO ; + current->flags |=PF_NOIO |PF_IOTHREAD ;/* * up sem, we are running
Only in linux-swsusp/drivers/char: consolemap_deftbl.c
drivers/char/sysrq.c +21 -0
@@ -27,6 +27,7 @@#include <linux/quotaops.h> #include <linux/smp_lock.h> #include <linux/module.h> +#include <linux/suspend.h> #include <linux/spinlock.h>
@@ -317,6 +318,22 @@ action_msg: "Kill All Tasks", }; +#ifdef CONFIG_SOFTWARE_SUSPEND +static void sysrq_handle_swsusp (int key,struct pt_regs *pt_regs, +struct kbd_struct *kbd,struct tty_struct *tty) { +if (!software_suspend_enabled) { +printk ("Software Suspend is not possible now\n" ); +return ; + } +software_suspend (); +} +static struct sysrq_key_op sysrq_swsusp_op = { + handler: sysrq_handle_swsusp, + help_msg:"suspenD" , + action_msg:"Software suspend\n" , +}; +#endif +/* END SIGNAL SYSRQ HANDLERS BLOCK */
@@ -339,7 +356,11 @@and will never arive */ /* b */ &sysrq_reboot_op,/* c */ NULL , +#ifdef CONFIG_SOFTWARE_SUSPEND +/* d */ &sysrq_swsusp_op, +#else/* d */ NULL , +#endif/* e */ &sysrq_term_op,/* f */ NULL , /* g */ NULL,
drivers/ide/ide-disk.c +1 -0
@@ -26,6 +26,7 @@#include <linux/slab.h> #include <linux/delay.h> #include <linux/ide.h> +#include <linux/suspend.h> #include <asm/byteorder.h> #include <asm/irq.h>
drivers/pci/pci.c +2 -2
@@ -1651,7 +1651,7 @@return error; } -static int pci_pm_suspend (u32 state) +int pci_pm_suspend (u32 state) {struct list_head *list;struct pci_bus *bus;
@@ -1664,7 +1664,7 @@return 0 ; } -static int pci_pm_resume (void ) +int pci_pm_resume (void ) {struct list_head *list;struct pci_bus *bus;
drivers/usb/storage/usb.c +1 -0
@@ -319,6 +319,7 @@/* avoid getting signals */ spin_lock_irq (¤t->sigmask_lock);flush_signals (current); + current->flags |=PF_IOTHREAD ;sigfillset (¤t->blocked);recalc_sigpending ();spin_unlock_irq (¤t->sigmask_lock);
fs/buffer.c +6 -0
@@ -47,6 +47,7 @@#include <linux/highmem.h> #include <linux/module.h> #include <linux/compiler.h> +#include <linux/suspend.h> #include <asm/uaccess.h> #include <asm/io.h>
@@ -129,6 +130,8 @@wake_up (&bh->b_wait); } +DECLARE_TASK_QUEUE (tq_bdflush); +/* * Rewrote the wait-routines to use the "new" wait-queue functionality, * and getting rid of the cli-sti pairs. The wait-queue routines still
@@ -2618,6 +2621,9 @@for (;;) {struct buffer_head *bh; +#ifdef CONFIG_SOFTWARE_SUSPEND +run_task_queue (&tq_bdflush); +#endif spin_lock (&lru_list_lock); bh = lru_list[BUF_DIRTY ];if (!bh ||time_before (jiffies, bh->b_flushtime))
fs/jbd/journal.c +11 -1
@@ -33,6 +33,7 @@#include <linux/init.h> #include <linux/mm.h> #include <linux/slab.h> +#include <linux/suspend.h> #include <asm/uaccess.h> #include <linux/proc_fs.h>
@@ -225,6 +226,7 @@ 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 )
@@ -245,7 +247,15 @@ }wake_up (&journal->j_wait_done_commit); -interruptible_sleep_on (&journal->j_wait_commit); +if (current->flags &PF_FREEZE ) {/* The simpler the better. Flushing journal isn't a +good idea, because that depends on threads that +may be already stopped. */ +jbd_debug (1 ,"Now suspending kjournald\n" ); +refrigerator (PF_IOTHREAD ); +jbd_debug (1 ,"Resuming kjournald\n" ); + }else /* we assume on resume that commits are already there, +so we don't sleep */ +interruptible_sleep_on (&journal->j_wait_commit);jbd_debug (1 ,"kjournald wakes\n" );
fs/reiserfs/journal.c +8 -1
@@ -58,6 +58,7 @@#include <linux/stat.h> #include <linux/string.h> #include <linux/smp_lock.h> +#include <linux/suspend.h> /* the number of mounted filesystems. This is used to decide when to ** start and kill the commit thread
@@ -1887,6 +1888,7 @@spin_unlock_irq (¤t->sigmask_lock);sprintf (current->comm,"kreiserfsd" ) ; + current->flags |=PF_KERNTHREAD ;lock_kernel () ;while (1 ) {
@@ -1900,7 +1902,12 @@break ; }wake_up (&reiserfs_commit_thread_done) ; -interruptible_sleep_on_timeout (&reiserfs_commit_thread_wait,5 *HZ ) ; +#ifdef CONFIG_SOFTWARE_SUSPEND +if (current->flags &PF_FREEZE ) { +refrigerator (PF_IOTHREAD ); + } else +#endif +interruptible_sleep_on_timeout (&reiserfs_commit_thread_wait,5 *HZ ) ; }unlock_kernel () ;wake_up (&reiserfs_commit_thread_done) ;
include/asm-generic/bitops.h +6 -0
@@ -51,6 +51,12 @@return ((mask & *addr) !=0 ); } +/* +* fls: find last bit set. +*/ + +#define fls (x) generic_fls(x) +#ifdef __KERNEL__/*
include/asm-i386/bitops.h +6 -0
@@ -414,6 +414,12 @@return word; } +/* +* fls: find last bit set. +*/ + +#define fls (x) generic_fls(x) +#ifdef __KERNEL__/*
include/asm-i386/suspend.h +305 -0
305 lines not on this page · raw message
Only in linux-swsusp/include: config
include/linux/bitops.h +42 -1
54 lines not on this page · raw message
include/linux/init.h +3 -0
@@ -169,6 +169,9 @@#endif +/* Data marked not to be saved by software_suspend() */ +#define __nosavedata __attribute__ ((__section__ (".data.nosave"))) +#ifdef CONFIG_HOTPLUG #define __devinit#define __devinitdata
include/linux/mm.h +9 -0
@@ -291,6 +291,9 @@#define PG_arch_1 13#define PG_reserved 14#define PG_launder 15/* written out by VM pressure.. */ +#define PG_nosave 17 +/* Don't you dare to use high bits, they seem to be used for something else! */ +#define PG_private 16/* Has something at ->private */
@@ -404,6 +407,12 @@#define SetPageReserved (page) set_bit(PG_reserved, &(page)->flags)#define ClearPageReserved (page) clear_bit(PG_reserved, &(page)->flags) + +#define PageNosave (page) test_bit(PG_nosave, &(page)->flags) +#define SetPageNosave (page) set_bit(PG_nosave, &(page)->flags) +#define TestSetPageNosave (page) test_and_set_bit(PG_nosave, &(page)->flags) +#define ClearPageNosave (page) clear_bit(PG_nosave, &(page)->flags) +#define TestClearPageNosave (page) test_and_clear_bit(PG_nosave, &(page)->flags)/* * Error return values for the *_nopage functions
Only in linux-swsusp/include/linux: modules
Only in linux-swsusp/include/linux: modversions.h
include/linux/reboot.h +9 -0
@@ -20,6 +20,7 @@* CAD_OFF Ctrl-Alt-Del sequence sends SIGINT to init task. * POWER_OFF Stop OS and remove all power from system, if possible. * RESTART2 Restart system using given command string. +* SW_SUSPEND Suspend system using Software Suspend if compiled in */ #define LINUX_REBOOT_CMD_RESTART 0x01234567
@@ -28,6 +29,7 @@#define LINUX_REBOOT_CMD_CAD_OFF 0x00000000#define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC#define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4 +#define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2#ifdef __KERNEL__
@@ -45,6 +47,13 @@extern void machine_restart (char *cmd);extern void machine_halt (void );extern void machine_power_off (void ); + +/* +* Architecture-independent suspend facility +*/ + +extern void software_suspend (void ); +extern unsigned char software_suspend_enabled;#endif
include/linux/sched.h +4 -0
@@ -370,6 +370,10 @@#define PF_FREE_PAGES 0x00002000/* per process page freeing */ #define PF_NOIO 0x00004000/* avoid generating further I/O */ #define PF_FLUSHER 0x00008000/* responsible for disk writeback */ +#define PF_FREEZE 0x00010000/* this task should be frozen for suspend */ +#define PF_IOTHREAD 0x00020000/* this thread is needed for doing I/O to swap */ +#define PF_KERNTHREAD 0x00040000/* this thread is a kernel thread that cannot be sent signals to */ +#define PF_FROZEN 0x00080000/* frozen for system suspend */ /* * Ptrace flags
include/linux/suspend.h +65 -0
65 lines not on this page · raw message
include/linux/tqueue.h +1 -1
@@ -66,7 +66,7 @@#define DECLARE_TASK_QUEUE (q) LIST_HEAD(q)#define TQ_ACTIVE (q) (!list_empty(&q)) -extern task_queue tq_timer, tq_immediate, tq_disk; +extern task_queue tq_timer, tq_immediate, tq_disk, tq_bdflush;/* * To implement your own list of active bottom halfs, use the following
init/main.c +7 -2
@@ -28,6 +28,7 @@#include <linux/bootmem.h> #include <linux/tty.h> #include <linux/percpu.h> +#include <linux/suspend.h> #include <asm/io.h> #include <asm/bugs.h>
@@ -271,9 +272,7 @@#else #define smp_init () do { } while (0)#endif -static inline void setup_per_cpu_areas (void ) { } -#else #ifdef __GENERIC_PER_CPU
@@ -342,7 +341,9 @@lock_kernel ();printk (linux_banner);setup_arch (&command_line); +#ifdef CONFIG_SMP setup_per_cpu_areas (); +#endif printk ("Kernel command line: %s\n" , saved_command_line);parse_options (command_line);trap_init ();
@@ -484,6 +485,10 @@start_context_thread ();do_initcalls (); + +/* This has to be before mounting root, because even readonly mount of reiserfs would replay +log corrupting stuff */ +software_resume (); }extern void prepare_namespace (void );
kernel/Makefile +2 -1
@@ -10,7 +10,7 @@ O_TARGET := kernel.o export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \ - printk.o platform.o + printk.o platform.o suspend.o obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o \ module.o exit.o itimer.o info.o time.o softirq.o resource.o \
@@ -21,6 +21,7 @@ obj-$(CONFIG_MODULES) += ksyms.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o +obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o ifneq ($(CONFIG_IA64),y) # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
kernel/context.c +1 -0
@@ -72,6 +72,7 @@daemonize ();strcpy (curtask->comm,"keventd" ); + current->flags |=PF_IOTHREAD ; keventd_running =1 ; keventd_task = curtask;
kernel/signal.c +1 -1
@@ -493,7 +493,7 @@* No need to set need_resched since signal event passing * goes through ->blocked */ -static inline void signal_wake_up (struct task_struct *t) +inline void signal_wake_up (struct task_struct *t) {set_tsk_thread_flag (t,TIF_SIGPENDING );
kernel/softirq.c +1 -0
@@ -365,6 +365,7 @@daemonize ();set_user_nice (current,19 ); + current->flags |=PF_IOTHREAD ;sigfillset (¤t->blocked);/* Migrate to the right CPU */
kernel/suspend.c +1343 -0
1,343 lines not on this page · raw message
kernel/sys.c +11 -0
@@ -4,6 +4,7 @@* Copyright (C) 1991, 1992 Linus Torvalds */ +#include <linux/config.h> #include <linux/module.h> #include <linux/mm.h> #include <linux/utsname.h>
@@ -346,6 +347,16 @@printk (KERN_EMERG "Restarting system with command '%s'.\n" , buffer);machine_restart (buffer);break ; + +#ifdef CONFIG_SOFTWARE_SUSPEND +case LINUX_REBOOT_CMD_SW_SUSPEND : +if (!software_suspend_enabled) +return -EAGAIN ; + +software_suspend (); +do_exit (0 ); +break ; +#endif default :unlock_kernel ();
mm/page_alloc.c +41 -0
53 lines not on this page · raw message
mm/page_io.c +4 -0
@@ -86,11 +86,15 @@* - it's marked as being swap-cache * - it's associated with the swap inode */ +extern long suspend_device;void rw_swap_page (int rw,struct page *page) {swp_entry_t entry; entry.val = page->index; + +if (suspend_device) +panic ("I refuse to corrupt memory/swap." );if (!PageLocked (page))PAGE_BUG (page);
mm/pdflush.c +6 -2
@@ -96,7 +96,7 @@recalc_sigpending ();spin_unlock_irq (¤t->sigmask_lock); - current->flags |=PF_FLUSHER ; + current->flags |=PF_FLUSHER |PF_KERNTHREAD ; my_work->fn =NULL ; my_work->who = current;
@@ -111,10 +111,13 @@set_current_state (TASK_INTERRUPTIBLE );spin_unlock_irq (&pdflush_lock); +if (current->flags &PF_FREEZE ) +refrigerator (PF_IOTHREAD );schedule ();preempt_enable (); - (*my_work->fn)(my_work->arg0); +if (my_work->fn) + (*my_work->fn)(my_work->arg0);preempt_disable ();/*
@@ -145,6 +148,7 @@ pdf->when_i_went_to_sleep = jiffies;/* Limit exit rate */ break ;/* exeunt */ } + my_work->fn =NULL ; } nr_pdflush_threads--;spin_unlock_irq (&pdflush_lock);
mm/vmscan.c +7 -2
@@ -22,6 +22,7 @@#include <linux/highmem.h> #include <linux/file.h> #include <linux/compiler.h> +#include <linux/suspend.h> #include <asm/pgalloc.h> #include <asm/tlbflush.h>
@@ -760,18 +761,22 @@* 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 ; + tsk->flags |=PF_MEMALLOC |PF_KERNTHREAD ;/* * Kswapd main loop. */ for (;;) { +if (current->flags &PF_FREEZE ) +refrigerator (PF_IOTHREAD );__set_current_state (TASK_INTERRUPTIBLE );add_wait_queue (&kswapd_wait, &wait);mb (); -if (kswapd_can_sleep ()) +if (kswapd_can_sleep ()) {schedule (); + } +__set_current_state (TASK_RUNNING );remove_wait_queue (&kswapd_wait, &wait);
Only in linux-swsusp/scripts: mkdep
Only in linux-swsusp/scripts: split-include
Signature · 2 lines
(about SSSCA) "I don't say this lightly. However, I really think that the U.S. no longer is classifiable as a democracy, but rather as a plutocracy." --hpa