diff -ruN linux-2.4.21-pre7-acpi20030328/arch/i386/config.in 1922/arch/i386/config.in --- linux-2.4.21-pre7-acpi20030328/arch/i386/config.in 2003-04-23 09:41:27.000000000 +1200 +++ 1922/arch/i386/config.in 2003-04-23 09:44:40.000000000 +1200 @@ -328,6 +328,10 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then dep_bool 'Software Suspend' CONFIG_SOFTWARE_SUSPEND $CONFIG_PM + if [ "$CONFIG_SOFTWARE_SUSPEND" = "y" ]; then + bool ' Compile in debugging output' CONFIG_SOFTWARE_SUSPEND_DEBUG + bool ' Compress image' CONFIG_SOFTWARE_SUSPEND_COMPRESSION + fi fi dep_tristate ' Advanced Power Management BIOS support' CONFIG_APM $CONFIG_PM diff -ruN linux-2.4.21-pre7-acpi20030328/drivers/ide/ide-disk.c 1922/drivers/ide/ide-disk.c --- linux-2.4.21-pre7-acpi20030328/drivers/ide/ide-disk.c 2003-04-23 09:41:27.000000000 +1200 +++ 1922/drivers/ide/ide-disk.c 2003-04-19 15:10:14.000000000 +1200 @@ -60,6 +60,7 @@ #include #include #include +#include #define _IDE_DISK @@ -1897,13 +1898,35 @@ void ide_disk_suspend(void) { - int i; + int i, drivenum = 0; + ide_drive_t *drive; + + if (driver_blocked) + return; i=1; while (ide_disks_busy(i++)) { schedule(); i &= (unsigned int)((1<<21)-1); /* CBD: we print a warning only after a great number of errors, no need to frighten the newbie ;-) */ } + /* Ensure caches are purged too (derived from module unload) - Nigel Cunningham */ + PRINTK(SUSPEND_VERBOSE, "Flushing writeback caches.\n"); + while ((drive = ide_scan_devices(ide_disk, idedisk_driver.name, + &idedisk_driver, drivenum)) != NULL) { + PRINTK(SUSPEND_VERBOSE, "Drive %s: (%d, %d)", + drive->name, + (drive->id->command_set_1 & 0x20), + drive->id->cfs_enable_1 & 0x20); + if ((drive->id->command_set_1 & 0x20) && drive->id->cfs_enable_1 & 0x20) { + PRINTK(SUSPEND_VERBOSE, "Flushing write cache."); + if (do_idedisk_flushcache(drive)) + printk(KERN_ERR "Failed!"); + } + PRINTK(SUSPEND_VERBOSE, "\n"); + drivenum++; + } + PRINTK(SUSPEND_VERBOSE, "Done.\n"); + for (i=0; iaddress1))+loop2) = - *(((char *)(PAGEDIR_ENTRY(pagedir_nosave,loop)->address3))+loop2); + for (loop2=0; loop2 < (PAGE_SIZE / sizeof(unsigned long)); loop2++) { + *(((unsigned long *)(page_address(pbe->origaddress)))+loop2) = + *(((unsigned long *)(page_address(pbe->address)))+loop2); __flush_tlb(); } + if ((loop + 1)%PBES_PER_PAGE) { + pbe++; + } else + pbe = ((struct pbelink *) ((unsigned long) pbe & PAGE_MASK))->next; } - restore_processor_context(); /* Ahah, we now run with our old stack, and with registers copied from suspend time */ + swsusp_state[1] = state1; + do_magic_resume_2(); } #endif diff -ruN linux-2.4.21-pre7-acpi20030328/include/linux/mm.h 1922/include/linux/mm.h --- linux-2.4.21-pre7-acpi20030328/include/linux/mm.h 2003-04-23 09:41:28.000000000 +1200 +++ 1922/include/linux/mm.h 2003-04-23 09:44:43.000000000 +1200 @@ -299,10 +299,6 @@ #define PG_launder 15 /* written out by VM pressure.. */ #define PG_fs_1 16 /* Filesystem specific */ #define PG_nosave 17 /* swsusp - used to be 16!! */ -#define PG_free 18 /* swsusp - page is unused - dont rely on outside swsusp! */ -#define PG_knowshared 19 -#define PG_dontcopy 20 -#define PG_collides 18 /* Reuse during start of resume */ /* Make it prettier to test the above... */ #define UnlockPage(page) unlock_page(page) @@ -323,18 +319,6 @@ #define PageNosave(page) test_bit(PG_nosave, &(page)->flags) #define SetPageNosave(page) set_bit(PG_nosave, &(page)->flags) #define ClearPageNosave(page) clear_bit(PG_nosave, &(page)->flags) -#define PageFree(page) test_bit(PG_free, &(page)->flags) -#define SetPageFree(page) set_bit(PG_free, &(page)->flags) -#define ClearPageFree(page) clear_bit(PG_free, &(page)->flags) -#define PageKnowshared(page) test_bit(PG_knowshared, &(page)->flags) -#define SetPageKnowshared(page) set_bit(PG_knowshared, &(page)->flags) -#define ClearPageKnowshared(page) clear_bit(PG_knowshared, &(page)->flags) -#define PageDontcopy(page) test_bit(PG_dontcopy, &(page)->flags) -#define SetPageDontcopy(page) set_bit(PG_dontcopy, &(page)->flags) -#define ClearPageDontcopy(page) clear_bit(PG_dontcopy, &(page)->flags) -#define PageCollides(page) test_bit(PG_collides, &(page)->flags) -#define SetPageCollides(page) set_bit(PG_collides, &(page)->flags) -#define ClearPageCollides(page) clear_bit(PG_collides, &(page)->flags) /* * The zone field is never updated after free_area_init_core() diff -ruN linux-2.4.21-pre7-acpi20030328/include/linux/suspend-debug.h 1922/include/linux/suspend-debug.h --- linux-2.4.21-pre7-acpi20030328/include/linux/suspend-debug.h 1970-01-01 12:00:00.000000000 +1200 +++ 1922/include/linux/suspend-debug.h 2003-04-23 09:24:35.000000000 +1200 @@ -0,0 +1,59 @@ + +#ifndef _LINUX_SWSUSP_DEBUG_H +#define _LINUX_SWSUSP_DEBUG_H + +#include + +#define name_suspend "Suspend Machine: " +#define name_resume "Resume Machine: " +#define swsusp_version "beta 19-22" +#define name_swsusp "Swsusp " swsusp_version ": " +#define console_suspend " S U S P E N D T O D I S K " /* Same length to ensure one overwrites the other */ +#define console_resume "R E S U M E F R O M D I S K" +/* + * Debug + */ +/* first status register */ +#define SUSPEND_PENDING (swsusp_state[0] & 0x1) +#define SUSPEND_ABORTING (swsusp_state[0] & 0x2) +/* second status register */ +#define SUSPEND_REBOOT (swsusp_state[1] & 0x1) +#define SUSPEND_FREEMEM (swsusp_state[1] & 0x2) +#define SUSPEND_PAUSE (swsusp_state[1] & 0x4) +#define SUSPEND_NOPAGESET2 (swsusp_state[1] & 0x8) +#define SUSPEND_NOPAGESET2INACTIVE (swsusp_state[1] & 0x10) +#define SUSPEND_NOPAGESET2ACTIVE (swsusp_state[1] & 0x20) +#define SUSPEND_LOGALL (swsusp_state[1] & 0x40) +/* third status register */ +#define SUSPEND_DEBUG 0x1 +#define SUSPEND_PROGRESS 0x2 +#define SUSPEND_VERBOSE 0x4 +#define SUSPEND_SLOW 0x8 +#define SUSPEND_BEEP 0x10 +/* fourth status register */ +#define STAGE_FREEZER 0x1 +#define STAGE_EAT_MEMORY 0x2 +#define STAGE_MARK_PAGESET2 0x4 +#define STAGE_WRITE_PAGESETS 0x8 +#define STAGE_FREE_PAGES 0x10 + +extern void printnolog(int restartline, const char *fmt, ...); + +#if defined(CONFIG_SOFTWARE_SUSPEND_DEBUG) +# define PRINTTHRESH 3 /* Number of lines at the start/end of pagesets to show */ +extern int currentstage; /* Current stage (STAGEPRINT macro) */ +# define STAGEPRINT ((currentstage == 0) || (swsusp_state[3] & currentstage)) +# define PRINTK(mask, f, a...) ((((mask) & swsusp_state[2]) && STAGEPRINT) ? printk(f, ## a):0) +# define PRINTNOLOG(mask, restartline, f, a...) ((((mask) & swsusp_state[2]) && STAGEPRINT) ? \ + printnolog(restartline, f, ## a) :0) +# define MDELAY(a) if (swsusp_state[2] & SUSPEND_SLOW) mdelay(a); else +# define beepOK if (swsusp_state[2] & SUSPEND_BEEP) { currentbeep += 200; kd_mksound(currentbeep,HZ/8); mdelay(150);} else +# define beepERR if (swsusp_state[2] & SUSPEND_BEEP) { kd_mksound(300,HZ/4); mdelay(300); } else +#else +# define PRINTK(f, a...) do { } while (0) +# define PRINTNOLOG(mask, restartline, f, a...) do { } while (0) +# define MDELAY(a) do { } while (0) +# define beepOK do { } while (0) +# define beepERR do { } while (0) +#endif +#endif diff -ruN linux-2.4.21-pre7-acpi20030328/include/linux/suspend.h 1922/include/linux/suspend.h --- linux-2.4.21-pre7-acpi20030328/include/linux/suspend.h 2003-04-23 09:41:28.000000000 +1200 +++ 1922/include/linux/suspend.h 2003-04-23 09:24:21.000000000 +1200 @@ -7,6 +7,7 @@ #include #include #include +#include extern unsigned char software_suspend_enabled; @@ -18,15 +19,22 @@ /* page backup entry */ typedef struct pbe { - unsigned long address1; /* original address of pageset1 entry */ - unsigned long address2; /* original address of pageset2 entry */ - unsigned long address3; /* copy back address */ - swp_entry_t swap_address1; - swp_entry_t swap_address2; - swp_entry_t dummy[3]; /* we need at least one sizeof(long) scratch space at + struct page * origaddress; /* original address of pageset entry */ + struct page * address; /* address of copy of pageset entry (pageset1 only) */ + swp_entry_t swap_address; + swp_entry_t dummy; /* we need at least one sizeof(long) scratch space at * end of page (see link, diskpage) and * sizeof(struct pbe) must be multiple of 4*sizeof(long) */ +} suspend_pbe_t; + +typedef struct pagedir { + int pageset_size; + int pagedir_size; + int alloc_from; + struct pbe *data; + struct pbe *first_allocated; /* Shortcut to first pbe in pageset 2 where extra pages + were allocated */ } suspend_pagedir_t; #define SWAP_FILENAME_MAXLENGTH 32 @@ -42,23 +50,27 @@ unsigned long swapforimage; unsigned int expected_size1; unsigned int expected_size2; - suspend_pagedir_t **suspend_pagedir; - unsigned int pageset1_size; - unsigned int pageset2_size; - unsigned int pagedir_size; + struct pagedir pagedir; int param0; int param1; int param2; int param3; int param4; + int progress0; + int progress1; + int progress2; + int progress3; + int progress4; + kdev_t kdevs[MAX_SWAPFILES]; struct swap_location { char filename[SWAP_FILENAME_MAXLENGTH]; } swap_location[MAX_SWAPFILES]; }; -#define SUSPEND_PD_PAGES(x) (((x)*sizeof(struct pbe))/PAGE_SIZE+1) -#define PAGEDIR_CAPACITY(x) (((x)*PAGE_SIZE/sizeof(struct pbe))) -#define PAGEDIR_ENTRY(pagedir, i) (pagedir[i/PAGEDIR_CAPACITY(1)] + (i%PAGEDIR_CAPACITY(1))) +#define PBES_PER_PAGE (PAGE_SIZE/sizeof(struct pbe)) +#define SUSPEND_PD_PAGES(x) (((x)+PBES_PER_PAGE-1)/PBES_PER_PAGE) +#define PAGEDIR_CAPACITY(x) (((x)*PBES_PER_PAGE)) +//#define PAGEDIR_ENTRY(pagedir, i) ((pagedir)->data[((i)/PBES_PER_PAGE)] + ((i)%PBES_PER_PAGE)) extern struct tq_struct suspend_tq; diff -ruN linux-2.4.21-pre7-acpi20030328/kernel/suspend.c 1922/kernel/suspend.c --- linux-2.4.21-pre7-acpi20030328/kernel/suspend.c 2003-04-23 09:41:28.000000000 +1200 +++ 1922/kernel/suspend.c 2003-04-23 09:23:58.000000000 +1200 @@ -49,7 +49,12 @@ #include #include #include +#if defined(CONFIG_FBCON_SPLASHSCREEN) +#include +#include