Re: swsusp bigdiff [was Re: [PATCH] Software Suspend split to two stage V2.]

From: Nishanth Aravamudan (nacc_at_us.ibm.com)
Date: 12/20/04

  • Next message: Pavel Machek: "Re: swsusp bigdiff [was Re: [PATCH] Software Suspend split to two stage V2.]"
    Date:	Mon, 20 Dec 2004 13:44:43 -0800
    To: Pavel Machek <pavel@suse.cz>
    
    

    On Sat, Nov 20, 2004 at 01:30:10AM +0100, Pavel Machek wrote:
    > Hi!
    >
    > > This patch using pagemap for PageSet2 bitmap, It increase suspend
    > > speed, In my PowerPC suspend only need 5 secs, cool.
    > >
    > > Test passed in my ppc and x86 laptop.
    > >
    > > ppc swsusp patch for 2.6.9
    > > http://honk.physik.uni-konstanz.de/~agx/linux-ppc/kernel/
    > > Have fun.
    >
    > BTW here's my curent bigdiff. It already has some rather nice
    > swsusp speedups. Please try it on your machine; if it works for you,
    > try to send your patches relative to this one. I hope to merge these
    > changes during 2.6.11.
    >
    > Pavel
    >
    >
    > --- clean/Documentation/pm.txt 2001-12-19 22:38:12.000000000 +0100
    > +++ linux/Documentation/pm.txt 2004-10-26 12:44:23.000000000 +0200
    > @@ -36,8 +36,8 @@
    > apmd: http://worldvisions.ca/~apenwarr/apmd/
    > acpid: http://acpid.sf.net/
    >
    > -Driver Interface
    > -----------------
    > +Driver Interface -- OBSOLETE, DO NOT USE!
    > +----------------*************************
    > If you are writing a new driver or maintaining an old driver, it
    > should include power management support. Without power management
    > support, a single driver may prevent a system with power management
    > @@ -91,54 +91,6 @@
    > void pm_unregister_all(pm_callback cback);
    >
    > /*
    > - * Device idle/use detection
    > - *
    > - * In general, drivers for all devices should call "pm_access"
    > - * before accessing the hardware (ie. before reading or modifying
    > - * a hardware register). Request or packet-driven drivers should
    > - * additionally call "pm_dev_idle" when a device is not being used.
    > - *
    > - * Examples:
    > - * 1) A keyboard driver would call pm_access whenever a key is pressed
    > - * 2) A network driver would call pm_access before submitting
    > - * a packet for transmit or receive and pm_dev_idle when its
    > - * transfer and receive queues are empty.
    > - * 3) A VGA driver would call pm_access before it accesses any
    > - * of the video controller registers
    > - *
    > - * Ultimately, the PM policy manager uses the access and idle
    > - * information to decide when to suspend individual devices
    > - * or when to suspend the entire system
    > - */
    > -
    > -/*
    > - * Description: Update device access time and wake up device, if necessary
    > - *
    > - * Parameters:
    > - * dev - PM device previously returned from pm_register
    > - *
    > - * Details: If called from an interrupt handler pm_access updates
    > - * access time but should never need to wake up the device
    > - * (if device is generating interrupts, it should be awake
    > - * already) This is important as we can not wake up
    > - * devices from an interrupt handler.
    > - */
    > -void pm_access(struct pm_dev *dev);
    > -
    > -/*
    > - * Description: Identify device as currently being idle
    > - *
    > - * Parameters:
    > - * dev - PM device previously returned from pm_register
    > - *
    > - * Details: A call to pm_dev_idle might signal to the policy manager
    > - * to put a device to sleep. If a new device request arrives
    > - * between the call to pm_dev_idle and the pm_callback
    > - * callback, the driver should fail the pm_callback request.
    > - */
    > -void pm_dev_idle(struct pm_dev *dev);
    > -
    > -/*
    > * Power management request callback
    > *
    > * Parameters:
    > @@ -262,8 +214,8 @@
    >
    > ACPI Development mailing list: acpi-devel@lists.sourceforge.net
    >
    > -System Interface
    > -----------------
    > +System Interface -- OBSOLETE, DO NOT USE!
    > +----------------*************************
    > If you are providing new power management support to Linux (ie.
    > adding support for something like APM or ACPI), you should
    > communicate with drivers through the existing generic power
    > --- clean/Documentation/power/devices.txt 2004-11-03 01:23:03.000000000 +0100
    > +++ linux/Documentation/power/devices.txt 2004-11-03 02:16:40.000000000 +0100
    > @@ -141,3 +141,82 @@
    > The driver core will not call any extra functions when binding the
    > device to the driver.
    >
    > +pm_message_t meaning
    > +
    > +pm_message_t has two fields. event ("major"), and flags. If driver
    > +does not know event code, it aborts the request, returning error. Some
    > +drivers may need to deal with special cases based on the actual type
    > +of suspend operation being done at the system level. This is why
    > +there are flags.
    > +
    > +Event codes are:
    > +
    > +ON -- no need to do anything except special cases like broken
    > +HW.
    > +
    > +FREEZE -- stop DMA and interrupts, and be prepared to reinit HW from
    > +scratch. That probably means stop accepting upstream requests, the
    > +actual policy of what to do with them beeing specific to a given
    > +driver. It's acceptable for a network driver to just drop packets
    > +while a block driver is expected to block the queue so no request is
    > +lost. (Use IDE as an example on how to do that). FREEZE requires no
    > +power state change, and it's expected for drivers to be able to
    > +quickly transition back to operating state.
    > +
    > +SUSPEND -- like FREEZE, but also put hardware into low-power state. If
    > +there's need to distinguish several levels of sleep, additional flag
    > +is probably best way to do that.
    > +
    > +All events are:
    > +
    > +#Prepare for suspend -- userland is still running but we are going to
    > +#enter suspend state. This gives drivers chance to load firmware from
    > +#disk and store it in memory, or do other activities taht require
    > +#operating userland, ability to kmalloc GFP_KERNEL, etc... All of these
    > +#are forbiden once the suspend dance is started.. event = ON, flags =
    > +#PREPARE_TO_SUSPEND
    > +
    > +Apm standby -- prepare for APM event. Quiesce devices to make life
    > +easier for APM BIOS. event = FREEZE, flags = APM_STANDBY
    > +
    > +Apm suspend -- same as APM_STANDBY, but it we should probably avoid
    > +spinning down disks. event = FREEZE, flags = APM_SUSPEND
    > +
    > +System halt, reboot -- quiesce devices to make life easier for BIOS. event
    > += FREEZE, flags = SYSTEM_HALT or SYSTEM_REBOOT
    > +
    > +System shutdown -- at least disks need to be spun down, or data may be
    > +lost. Quiesce devices, just to make life easier for BIOS. event =
    > +FREEZE, flags = SYSTEM_SHUTDOWN
    > +
    > +Kexec -- turn off DMAs and put hardware into some state where new
    > +kernel can take over. event = FREEZE, flags = KEXEC
    > +
    > +Powerdown at end of swsusp -- very similar to SYSTEM_SHUTDOWN, except wake
    > +may need to be enabled on some devices. This actually has at least 3
    > +subtypes, system can reboot, enter S4 and enter S5 at the end of
    > +swsusp. event = FREEZE, flags = SWSUSP and one of SYSTEM_REBOOT,
    > +SYSTEM_SHUTDOWN, SYSTEM_S4
    > +
    > +Suspend to ram -- put devices into low power state. event = SUSPEND,
    > +flags = SUSPEND_TO_RAM
    > +
    > +Freeze for swsusp snapshot -- stop DMA and interrupts. No need to put
    > +devices into low power mode, but you must be able to reinitialize
    > +device from scratch in resume method. This has two flavors, its done
    > +once on suspending kernel, once on resuming kernel. event = FREEZE,
    > +flags = DURING_SUSPEND or DURING_RESUME
    > +
    > +Device detach requested from /sys -- deinitialize device; proably same as
    > +SYSTEM_SHUTDOWN, I do not understand this one too much. probably event
    > += FREEZE, flags = DEV_DETACH.
    > +
    > +#These are not really events sent:
    > +#
    > +#System fully on -- device is working normally; this is probably never
    > +#passed to suspend() method... event = ON, flags = 0
    > +#
    > +#Ready after resume -- userland is now running, again. Time to free any
    > +#memory you ate during prepare to suspend... event = ON, flags =
    > +#READY_AFTER_RESUME
    > +#
    > --- clean/Documentation/power/swsusp.txt 2004-10-01 00:29:56.000000000 +0200
    > +++ linux/Documentation/power/swsusp.txt 2004-11-14 23:36:46.000000000 +0100
    > @@ -15,10 +15,21 @@
    > * If you change kernel command line between suspend and resume...
    > * ...prepare for nasty fsck or worse.
    > *
    > - * (*) pm interface support is needed to make it safe.
    > + * If you change your hardware while system is suspended...
    > + * ...well, it was not good idea.
    > + *
    > + * (*) suspend/resume support is needed to make it safe.
    >
    > You need to append resume=/dev/your_swap_partition to kernel command
    > -line. Then you suspend by echo 4 > /proc/acpi/sleep.
    > +line. Then you suspend by
    > +
    > +echo shutdown > /sys/power/disk; echo disk > /sys/power/state
    > +
    > +. If you feel ACPI works pretty well on your system, you might try
    > +
    > +echo platform > /sys/power/disk; echo disk > /sys/power/state
    > +
    > +
    >
    > Article about goals and implementation of Software Suspend for Linux
    > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    > @@ -32,42 +43,24 @@
    > to standby mode. Later resuming the machine the saved state is loaded back to
    > ram and the machine can continue its work. It has two real benefits. First we
    > save ourselves the time machine goes down and later boots up, energy costs
    > -real high when running from batteries. The other gain is that we don't have to
    > +are real high when running from batteries. The other gain is that we don't have to
    > interrupt our programs so processes that are calculating something for a long
    > time shouldn't need to be written interruptible.
    >
    > -Using the code
    > -
    > -You have two ways to use this code. The first one is is with a patched
    > -SysVinit (my patch is against 2.76 and available at my home page). You
    > -might call 'swsusp' or 'shutdown -z <time>'. Next way is to echo 4 >
    > -/proc/acpi/sleep.
    > -
    > -Either way it saves the state of the machine into active swaps and then
    > -reboots. You must explicitly specify the swap partition to resume from with
    > +swsusp saves the state of the machine into active swaps and then reboots or
    > +powerdowns. You must explicitly specify the swap partition to resume from with
    > ``resume='' kernel option. If signature is found it loads and restores saved
    > state. If the option ``noresume'' is specified as a boot parameter, it skips
    > the resuming.
    >
    > -In the meantime while the system is suspended you should not touch any of the
    > -hardware!
    > -
    > -About the code
    > -
    > -Things to implement
    > -- We should only make a copy of data related to kernel segment, since any
    > - process data won't be changed.
    > -- Should make more sanity checks. Or are these enough?
    > -
    > -Not so important ideas for implementing
    > +In the meantime while the system is suspended you should not add/remove any
    > +of the hardware, write to the filesystems, etc.
    >
    > -- If a real time process is running then don't suspend the machine.
    > -- Support for adding/removing hardware while suspended?
    > -- We should not free pages at the beginning so aggressively, most of them
    > - go there anyway..
    > +Sleep states summary
    > +====================
    >
    > -Sleep states summary (thanx, Ducrot)
    > -====================================
    > +There are three different interfaces you can use, /proc/acpi should
    > +work like this:
    >
    > In a really perfect world:
    > echo 1 > /proc/acpi/sleep # for standby
    > @@ -79,7 +72,6 @@
    > and perhaps
    > echo 4b > /proc/acpi/sleep # for suspend to disk via s4bios
    >
    > -
    > Frequently Asked Questions
    > ==========================
    >
    > @@ -123,27 +115,13 @@
    >
    > Q: Does linux support ACPI S4?
    >
    > -A: No.
    > -
    > -When swsusp was created, ACPI was not too widespread, so we tried to
    > -avoid using ACPI-specific stuff. ACPI also is/was notoriously
    > -buggy. These days swsusp works on APM-only i386 machines and even
    > -without any power managment at all. Some versions also work on PPC.
    > -
    > -That means that machine does not enter S4 on suspend-to-disk, but
    > -simply enters S5. That has few advantages, you can for example boot
    > -windows on next boot, and return to your Linux session later. You
    > -could even have few different Linuxes on your box (not sharing any
    > -partitions), and switch between them.
    > -
    > -It also has disadvantages. On HP nx5000, if you unplug power cord
    > -while machine is suspended-to-disk, Linux will fail to notice that.
    > +A: Yes. That's what echo platform > /sys/power/disk does.
    >
    > Q: My machine doesn't work with ACPI. How can I use swsusp than ?
    >
    > A: Do a reboot() syscall with right parameters. Warning: glibc gets in
    > its way, so check with strace:
    > -
    > +
    > reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, 0xd000fce2)
    >
    > (Thanks to Peter Osterlund:)
    > @@ -162,6 +140,8 @@
    > return 0;
    > }
    >
    > +Also /sys/ interface should be still present.
    > +
    > Q: What is 'suspend2'?
    >
    > A: suspend2 is 'Software Suspend 2', a forked implementation of
    > @@ -175,17 +155,22 @@
    > website, and not to the Linux Kernel Mailing List. We are working
    > toward merging suspend2 into the mainline kernel.
    >
    > -Q: Kernel thread must voluntarily freeze itself (call 'refrigerator'). But
    > -I found some kernel threads don't do it, and they don't freeze, and
    > +Q: A kernel thread must voluntarily freeze itself (call 'refrigerator').
    > +I found some kernel threads that don't do it, and they don't freeze
    > so the system can't sleep. Is this a known behavior?
    >
    > -A: All such kernel threads need to be fixed, one by one. Select place
    > -where it is safe to be frozen (no kernel semaphores should be held at
    > -that point and it must be safe to sleep there), and add:
    > +A: All such kernel threads need to be fixed, one by one. Select the
    > +place where the thread is safe to be frozen (no kernel semaphores
    > +should be held at that point and it must be safe to sleep there), and
    > +add:
    >
    > if (current->flags & PF_FREEZE)
    > refrigerator(PF_FREEZE);
    >
    > +If the thread is needed for writing the image to storage, you should
    > +instead set the PF_NOFREEZE process flag when creating the thread.
    > +
    > +
    > Q: What is the difference between between "platform", "shutdown" and
    > "firmware" in /sys/power/disk?
    >
    > @@ -201,3 +186,42 @@
    >
    > "platform" is actually right thing to do, but "shutdown" is most
    > reliable.
    > +
    > +Q: I do not understand why you have such strong objections to idea of
    > +selective suspend.
    > +
    > +A: Do selective suspend during runtime power managment, that's okay. But
    > +its useless for suspend-to-disk. (And I do not see how you could use
    > +it for suspend-to-ram, I hope you do not want that).
    > +
    > +Lets see, so you suggest to
    > +
    > +* SUSPEND all but swap device and parents
    > +* Snapshot
    > +* Write image to disk
    > +* SUSPEND swap device and parents
    > +* Powerdown
    > +
    > +Oh no, that does not work, if swap device or its parents uses DMA,
    > +you've corrupted data. You'd have to do
    > +
    > +* SUSPEND all but swap device and parents
    > +* FREEZE swap device and parents
    > +* Snapshot
    > +* UNFREEZE swap device and parents
    > +* Write
    > +* SUSPEND swap device and parents
    > +
    > +Which means that you still need that FREEZE state, and you get more
    > +complicated code. (And I have not yet introduce details like system
    > +devices).
    > +
    > +Q: There don't seem to be any generally useful behavioral
    > +distinctions between SUSPEND and FREEZE.
    > +
    > +A: Doing SUSPEND when you are asked to do FREEZE is always correct,
    > +but it may be unneccessarily slow. If you want USB to stay simple,
    > +slowness may not matter to you. It can always be fixed later.
    > +
    > +For devices like disk it does matter, you do not want to spindown for
    > +FREEZE.
    > --- clean/Documentation/power/video.txt 2004-08-15 19:14:52.000000000 +0200
    > +++ linux/Documentation/power/video.txt 2004-10-29 11:56:46.000000000 +0200
    > @@ -17,15 +17,18 @@
    >
    > * systems where video state is preserved over S3. (Athlon HP Omnibook xe3s)
    >
    > -* systems that initialize video card into vga text mode and where BIOS
    > - works well enough to be able to set video mode. Use
    > - acpi_sleep=s3_mode on these. (Toshiba 4030cdt)
    > -
    > * systems where it is possible to call video bios during S3
    > resume. Unfortunately, it is not correct to call video BIOS at that
    > point, but it happens to work on some machines. Use
    > acpi_sleep=s3_bios (Athlon64 desktop system)
    >
    > +* systems that initialize video card into vga text mode and where BIOS
    > + works well enough to be able to set video mode. Use
    > + acpi_sleep=s3_mode on these. (Toshiba 4030cdt)
    > +
    > +* on some systems s3_bios kicks video into text mode, and
    > + acpi_sleep=s3_bios,s3_mode is needed (Toshiba Satellite P10-554)
    > +
    > * radeon systems, where X can soft-boot your video card. You'll need
    > patched X, and plain text console (no vesafb or radeonfb), see
    > http://www.doesi.gmxhome.de/linux/tm800s3/s3.html. (Acer TM 800)
    > --- clean/Documentation/sparse.txt 2004-10-16 23:48:08.000000000 +0200
    > +++ linux/Documentation/sparse.txt 2004-10-24 22:44:47.000000000 +0200
    > @@ -0,0 +1,72 @@
    > +Copyright 2004 Linus Torvalds
    > +Copyright 2004 Pavel Machek <pavel@suse.cz>
    > +
    > +Using sparse for typechecking
    > +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    > +
    > +"__bitwise" is a type attribute, so you have to do something like this:
    > +
    > + typedef int __bitwise pm_request_t;
    > +
    > + enum pm_request {
    > + PM_SUSPEND = (__force pm_request_t) 1,
    > + PM_RESUME = (__force pm_request_t) 2
    > + };
    > +
    > +which makes PM_SUSPEND and PM_RESUME "bitwise" integers (the "__force" is
    > +there because sparse will complain about casting to/from a bitwise type,
    > +but in this case we really _do_ want to force the conversion). And because
    > +the enum values are all the same type, now "enum pm_request" will be that
    > +type too.
    > +
    > +And with gcc, all the __bitwise/__force stuff goes away, and it all ends
    > +up looking just like integers to gcc.
    > +
    > +Quite frankly, you don't need the enum there. The above all really just
    > +boils down to one special "int __bitwise" type.
    > +
    > +So the simpler way is to just do
    > +
    > + typedef int __bitwise pm_request_t;
    > +
    > + #define PM_SUSPEND ((__force pm_request_t) 1)
    > + #define PM_RESUME ((__force pm_request_t) 2)
    > +
    > +and you now have all the infrastructure needed for strict typechecking.
    > +
    > +One small note: the constant integer "0" is special. You can use a
    > +constant zero as a bitwise integer type without sparse ever complaining.
    > +This is because "bitwise" (as the name implies) was designed for making
    > +sure that bitwise types don't get mixed up (little-endian vs big-endian
    > +vs cpu-endian vs whatever), and there the constant "0" really _is_
    > +special.
    > +
    > +Modify top-level Makefile to say
    > +
    > +CHECK = sparse -Wbitwise
    > +
    > +or you don't get any checking at all.
    > +
    > +
    > +Where to get sparse
    > +~~~~~~~~~~~~~~~~~~~
    > +
    > +With BK, you can just get it from
    > +
    > + bk://sparse.bkbits.net/sparse
    > +
    > +and DaveJ has tar-balls at
    > +
    > + http://www.codemonkey.org.uk/projects/bitkeeper/sparse/
    > +
    > +
    > +Once you have it, just do
    > +
    > + make
    > + make install
    > +
    > +as your regular user, and it will install sparse in your ~/bin directory.
    > +After that, doing a kernel make with "make C=1" will run sparse on all the
    > +C files that get recompiled, or with "make C=2" will run sparse on the
    > +files whether they need to be recompiled or not (ie the latter is fast way
    > +to check the whole tree if you have already built it).
    > --- clean/Makefile 2004-10-19 14:16:26.000000000 +0200
    > +++ linux/Makefile 2004-10-29 11:56:48.000000000 +0200
    > @@ -325,7 +325,7 @@
    > DEPMOD = /sbin/depmod
    > KALLSYMS = scripts/kallsyms
    > PERL = perl
    > -CHECK = sparse
    > +CHECK = sparse -Wbitwise
    > CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__
    > MODFLAGS = -DMODULE
    > CFLAGS_MODULE = $(MODFLAGS)
    > --- clean/arch/arm/mach-sa1100/pm.c 2004-10-19 14:16:27.000000000 +0200
    > +++ linux/arch/arm/mach-sa1100/pm.c 2004-10-26 00:27:12.000000000 +0200
    > @@ -57,7 +57,7 @@
    > };
    >
    >
    > -static int sa11x0_pm_enter(u32 state)
    > +static int sa11x0_pm_enter(suspend_state_t state)
    > {
    > unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE];
    > struct timespec delta, rtc;
    > @@ -153,7 +153,7 @@
    > /*
    > * Called after processes are frozen, but before we shut down devices.
    > */
    > -static int sa11x0_pm_prepare(u32 state)
    > +static int sa11x0_pm_prepare(suspend_state_t state)
    > {
    > return 0;
    > }
    > @@ -161,7 +161,7 @@
    > /*
    > * Called after devices are re-setup, but before processes are thawed.
    > */
    > -static int sa11x0_pm_finish(u32 state)
    > +static int sa11x0_pm_finish(suspend_state_t state)
    > {
    > return 0;
    > }
    > --- clean/arch/i386/kernel/apm.c 2004-10-01 00:29:59.000000000 +0200
    > +++ linux/arch/i386/kernel/apm.c 2004-11-14 23:36:46.000000000 +0100
    > @@ -1201,8 +1201,8 @@
    > printk(KERN_CRIT "apm: suspend was vetoed, but suspending anyway.\n");
    > }
    >
    > - device_suspend(3);
    > - device_power_down(3);
    > + device_suspend(PMSG_SUSPEND);
    > + device_power_down(PMSG_SUSPEND);
    >
    > /* serialize with the timer interrupt */
    > write_seqlock_irq(&xtime_lock);
    > @@ -1255,7 +1255,7 @@
    > {
    > int err;
    >
    > - device_power_down(3);
    > + device_power_down(PMSG_SUSPEND);
    > /* serialize with the timer interrupt */
    > write_seqlock_irq(&xtime_lock);
    > /* If needed, notify drivers here */
    > --- clean/arch/i386/kernel/signal.c 2004-10-01 00:29:59.000000000 +0200
    > +++ linux/arch/i386/kernel/signal.c 2004-10-29 11:56:46.000000000 +0200
    > @@ -587,7 +587,8 @@
    >
    > if (current->flags & PF_FREEZE) {
    > refrigerator(0);
    > - goto no_signal;
    > + if (!signal_pending(current))
    > + goto no_signal;
    > }
    >
    > if (!oldset)
    > --- clean/arch/i386/mm/fault.c 2004-10-19 14:16:27.000000000 +0200
    > +++ linux/arch/i386/mm/fault.c 2004-10-29 11:56:48.000000000 +0200
    > @@ -21,6 +21,7 @@
    > #include <linux/vt_kern.h> /* For unblank_screen() */
    > #include <linux/highmem.h>
    > #include <linux/module.h>
    > +#include <linux/delay.h>
    >
    > #include <asm/system.h>
    > #include <asm/uaccess.h>
    > @@ -451,6 +452,7 @@
    > asm("movl %%cr3,%0":"=r" (page));
    > page = ((unsigned long *) __va(page))[address >> 22];
    > printk(KERN_ALERT "*pde = %08lx\n", page);
    > + mdelay(10000);
    > /*
    > * We must not directly access the pte in the highpte
    > * case, the page table might be allocated in highmem.
    > --- clean/arch/i386/power/cpu.c 2004-10-01 00:29:59.000000000 +0200
    > +++ linux/arch/i386/power/cpu.c 2004-10-29 11:56:46.000000000 +0200
    > @@ -148,6 +148,6 @@
    > __restore_processor_state(&saved_context);
    > }
    >
    > -
    > +/* Needed by apm.c */
    > EXPORT_SYMBOL(save_processor_state);
    > EXPORT_SYMBOL(restore_processor_state);
    > --- clean/drivers/acpi/sleep/main.c 2004-10-01 00:30:09.000000000 +0200
    > +++ linux/drivers/acpi/sleep/main.c 2004-11-04 00:18:36.000000000 +0100
    > @@ -42,7 +42,7 @@
    > * wakeup code to the waking vector.
    > */
    >
    > -static int acpi_pm_prepare(u32 pm_state)
    > +static int acpi_pm_prepare(suspend_state_t pm_state)
    > {
    > u32 acpi_state = acpi_suspend_states[pm_state];
    >
    > @@ -74,7 +74,7 @@
    > * It's unfortunate, but it works. Please fix if you're feeling frisky.
    > */
    >
    > -static int acpi_pm_enter(u32 pm_state)
    > +static int acpi_pm_enter(suspend_state_t pm_state)
    > {
    > acpi_status status = AE_OK;
    > unsigned long flags = 0;
    > @@ -136,7 +136,7 @@
    > * failed).
    > */
    >
    > -static int acpi_pm_finish(u32 pm_state)
    > +static int acpi_pm_finish(suspend_state_t pm_state)
    > {
    > u32 acpi_state = acpi_suspend_states[pm_state];
    >
    > @@ -156,7 +156,7 @@
    >
    > int acpi_suspend(u32 acpi_state)
    > {
    > - u32 states[] = {
    > + suspend_state_t states[] = {
    > [1] = PM_SUSPEND_STANDBY,
    > [3] = PM_SUSPEND_MEM,
    > [4] = PM_SUSPEND_DISK,
    > --- clean/drivers/base/platform.c 2004-08-15 19:14:55.000000000 +0200
    > +++ linux/drivers/base/platform.c 2004-11-04 00:31:33.000000000 +0100
    > @@ -238,7 +238,7 @@
    > return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
    > }
    >
    > -static int platform_suspend(struct device * dev, u32 state)
    > +static int platform_suspend(struct device * dev, pm_message_t state)
    > {
    > int ret = 0;
    >
    > --- clean/drivers/base/power/power.h 2004-08-15 19:14:55.000000000 +0200
    > +++ linux/drivers/base/power/power.h 2004-11-14 23:36:46.000000000 +0100
    > @@ -66,14 +66,14 @@
    > /*
    > * suspend.c
    > */
    > -extern int suspend_device(struct device *, u32);
    > +extern int suspend_device(struct device *, pm_message_t);
    >
    >
    > /*
    > * runtime.c
    > */
    >
    > -extern int dpm_runtime_suspend(struct device *, u32);
    > +extern int dpm_runtime_suspend(struct device *, pm_message_t);
    > extern void dpm_runtime_resume(struct device *);
    >
    > #else /* CONFIG_PM */
    > @@ -88,7 +88,7 @@
    >
    > }
    >
    > -static inline int dpm_runtime_suspend(struct device * dev, u32 state)
    > +static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state)
    > {
    > return 0;
    > }
    > --- clean/drivers/base/power/resume.c 2004-08-15 19:14:55.000000000 +0200
    > +++ linux/drivers/base/power/resume.c 2004-11-14 23:36:46.000000000 +0100
    > @@ -36,7 +36,7 @@
    > struct device * dev = to_device(entry);
    > list_del_init(entry);
    >
    > - if (!dev->power.prev_state)
    > + if (dev->power.prev_state == PMSG_ON)
    > resume_device(dev);
    >
    > list_add_tail(entry, &dpm_active);
    > --- clean/drivers/base/power/runtime.c 2004-08-15 19:14:55.000000000 +0200
    > +++ linux/drivers/base/power/runtime.c 2004-11-14 23:36:46.000000000 +0100
    > @@ -13,10 +13,10 @@
    > static void runtime_resume(struct device * dev)
    > {
    > dev_dbg(dev, "resuming\n");
    > - if (!dev->power.power_state)
    > + if (dev->power.power_state == PMSG_ON)
    > return;
    > if (!resume_device(dev))
    > - dev->power.power_state = 0;
    > + dev->power.power_state = PMSG_ON;
    > }
    >
    >
    > @@ -44,7 +44,7 @@
    > * @state: State to enter.
    > */
    >
    > -int dpm_runtime_suspend(struct device * dev, u32 state)
    > +int dpm_runtime_suspend(struct device * dev, pm_message_t state)
    > {
    > int error = 0;
    >
    > @@ -52,7 +52,7 @@
    > if (dev->power.power_state == state)
    > goto Done;
    >
    > - if (dev->power.power_state)
    > + if (dev->power.power_state != PMSG_ON)
    > runtime_resume(dev);
    >
    > if (!(error = suspend_device(dev, state)))
    > @@ -73,7 +73,7 @@
    > * always be able to tell, but we need accurate information to
    > * work reliably.
    > */
    > -void dpm_set_power_state(struct device * dev, u32 state)
    > +void dpm_set_power_state(struct device * dev, pm_message_t state)
    > {
    > down(&dpm_sem);
    > dev->power.power_state = state;
    > --- clean/drivers/base/power/shutdown.c 2004-08-15 19:14:55.000000000 +0200
    > +++ linux/drivers/base/power/shutdown.c 2004-11-14 23:36:46.000000000 +0100
    > @@ -29,7 +29,8 @@
    > dev->driver->shutdown(dev);
    > return 0;
    > }
    > - return dpm_runtime_suspend(dev, dev->detach_state);
    > + /* FIXME */
    > + return dpm_runtime_suspend(dev, PMSG_FREEZE);
    > }
    >
    >
    > --- clean/drivers/base/power/suspend.c 2004-08-15 19:14:55.000000000 +0200
    > +++ linux/drivers/base/power/suspend.c 2004-11-14 23:36:46.000000000 +0100
    > @@ -11,7 +11,7 @@
    > #include <linux/device.h>
    > #include "power.h"
    >
    > -extern int sysdev_suspend(u32 state);
    > +extern int sysdev_suspend(pm_message_t state);
    >
    > /*
    > * The entries in the dpm_active list are in a depth first order, simply
    > @@ -35,7 +35,7 @@
    > * @state: Power state device is entering.
    > */
    >
    > -int suspend_device(struct device * dev, u32 state)
    > +int suspend_device(struct device * dev, pm_message_t state)
    > {
    > int error = 0;
    >
    > @@ -43,7 +43,7 @@
    >
    > dev->power.prev_state = dev->power.power_state;
    >
    > - if (dev->bus && dev->bus->suspend && !dev->power.power_state)
    > + if (dev->bus && dev->bus->suspend && (dev->power.power_state == PMSG_ON))
    > error = dev->bus->suspend(dev, state);
    >
    > return error;
    > @@ -70,7 +70,7 @@
    > *
    > */
    >
    > -int device_suspend(u32 state)
    > +int device_suspend(pm_message_t state)
    > {
    > int error = 0;
    >
    > @@ -112,7 +112,7 @@
    > * done, power down system devices.
    > */
    >
    > -int device_power_down(u32 state)
    > +int device_power_down(pm_message_t state)
    > {
    > int error = 0;
    > struct device * dev;
    > --- clean/drivers/char/vt.c 2004-10-01 00:30:12.000000000 +0200
    > +++ linux/drivers/char/vt.c 2004-10-26 00:14:17.000000000 +0200
    > @@ -2186,8 +2186,6 @@
    > if (!printable || test_and_set_bit(0, &printing))
    > return;
    >
    > - pm_access(pm_con);
    > -
    > if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
    > currcons = kmsg_redirect - 1;
    >
    > @@ -2387,7 +2385,6 @@
    > {
    > int retval;
    >
    > - pm_access(pm_con);
    > retval = do_con_write(tty, from_user, buf, count);
    > con_flush_chars(tty);
    >
    > @@ -2398,7 +2395,6 @@
    > {
    > if (in_interrupt())
    > return; /* n_r3964 calls put_char() from interrupt context */
    > - pm_access(pm_con);
    > do_con_write(tty, 0, &ch, 1);
    > }
    >
    > @@ -2467,8 +2463,6 @@
    > if (in_interrupt()) /* from flush_to_ldisc */
    > return;
    >
    > - pm_access(pm_con);
    > -
    > /* if we race with con_close(), vt may be null */
    > acquire_console_sem();
    > vt = tty->driver_data;
    > --- clean/drivers/ide/ide-disk.c 2004-10-01 00:30:12.000000000 +0200
    > +++ linux/drivers/ide/ide-disk.c 2004-10-29 11:56:48.000000000 +0200
    > @@ -1419,9 +1419,12 @@
    > {
    > switch (rq->pm->pm_step) {
    > case idedisk_pm_flush_cache: /* Suspend step 1 (flush cache) complete */
    > - if (rq->pm->pm_state == 4)
    > +#if 0
    > + /* FIXME!! */
    > + if (system_state == SYSTEM_SNAPSHOT)
    > rq->pm->pm_step = ide_pm_state_completed;
    > else
    > +#endif
    > rq->pm->pm_step = idedisk_pm_standby;
    > break;
    > case idedisk_pm_standby: /* Suspend step 2 (standby) complete */
    > @@ -1702,7 +1705,6 @@
    > return;
    > }
    >
    > - printk("Shutdown: %s\n", drive->name);
    > dev->bus->suspend(dev, PM_SUSPEND_STANDBY);
    > }
    >
    > --- clean/drivers/ide/ide.c 2004-10-01 00:30:12.000000000 +0200
    > +++ linux/drivers/ide/ide.c 2004-11-04 00:32:27.000000000 +0100
    > @@ -1499,7 +1499,7 @@
    > return 1;
    > }
    >
    > -static int generic_ide_suspend(struct device *dev, u32 state)
    > +static int generic_ide_suspend(struct device *dev, pm_message_t state)
    > {
    > ide_drive_t *drive = dev->driver_data;
    > struct request rq;
    > --- clean/drivers/ieee1394/ieee1394_core.c 2004-06-22 12:36:07.000000000 +0200
    > +++ linux/drivers/ieee1394/ieee1394_core.c 2004-10-29 11:56:46.000000000 +0200
    > @@ -1039,6 +1039,11 @@
    > continue;
    > }
    >
    > + if (current->flags & PF_FREEZE) {
    > + refrigerator(0);
    > + continue;
    > + }
    > +
    > while ((skb = skb_dequeue(&hpsbpkt_queue)) != NULL) {
    > packet = (struct hpsb_packet *)skb->data;
    >
    > --- clean/drivers/input/input.c 2004-08-15 19:14:56.000000000 +0200
    > +++ linux/drivers/input/input.c 2004-10-25 23:54:57.000000000 +0200
    > @@ -67,9 +67,6 @@
    > {
    > struct input_handle *handle;
    >
    > - if (dev->pm_dev)
    > - pm_access(dev->pm_dev);
    > -
    > if (type > EV_MAX || !test_bit(type, dev->evbit))
    > return;
    >
    > @@ -230,8 +227,6 @@
    >
    > int input_open_device(struct input_handle *handle)
    > {
    > - if (handle->dev->pm_dev)
    > - pm_access(handle->dev->pm_dev);
    > handle->open++;
    > if (handle->dev->open)
    > return handle->dev->open(handle->dev);
    > @@ -249,8 +244,6 @@
    > void input_close_device(struct input_handle *handle)
    > {
    > input_release_device(handle);
    > - if (handle->dev->pm_dev)
    > - pm_dev_idle(handle->dev->pm_dev);
    > if (handle->dev->close)
    > handle->dev->close(handle->dev);
    > handle->open--;
    > --- clean/drivers/pci/pci-driver.c 2004-10-01 00:30:16.000000000 +0200
    > +++ linux/drivers/pci/pci-driver.c 2004-11-04 00:26:44.000000000 +0100
    > @@ -295,7 +295,7 @@
    > return 0;
    > }
    >
    > -static int pci_device_suspend(struct device * dev, u32 state)
    > +static int pci_device_suspend(struct device * dev, pm_message_t state)
    > {
    > struct pci_dev * pci_dev = to_pci_dev(dev);
    > struct pci_driver * drv = pci_dev->driver;
    > --- clean/drivers/pci/pci.c 2004-10-01 00:30:16.000000000 +0200
    > +++ linux/drivers/pci/pci.c 2004-11-14 23:36:46.000000000 +0100
    > @@ -229,7 +229,7 @@
    > /**
    > * pci_set_power_state - Set the power state of a PCI device
    > * @dev: PCI device to be suspended
    > - * @state: Power state we're entering
    > + * @state: PCI power state (D0, D1, D2, D3hot, D3cold) we're entering
    > *
    > * Transition a device to a new power state, using the Power Management
    > * Capabilities in the device's config space.
    > @@ -242,7 +242,7 @@
    > */
    >
    > int
    > -pci_set_power_state(struct pci_dev *dev, int state)
    > +pci_set_power_state(struct pci_dev *dev, pci_power_t state)
    > {
    > int pm;
    > u16 pmcsr;
    > @@ -300,6 +300,30 @@
    > }
    >
    > /**
    > + * pci_choose_state - Choose the power state of a PCI device
    > + * @dev: PCI device to be suspended
    > + * @state: target sleep state for the whole system
    > + *
    > + * Returns PCI power state suitable for given device and given system
    > + * message.
    > + */
    > +
    > +pci_power_t pci_choose_state(struct pci_dev *dev, u32 state)
    > +{
    > + if (!pci_find_capability(dev, PCI_CAP_ID_PM))
    > + return PCI_D0;
    > +
    > + switch (state) {
    > + case 0: return PCI_D0;
    > + case 2: return PCI_D2;
    > + case 3: return PCI_D3hot;
    > + default: BUG();
    > + }
    > +}
    > +
    > +EXPORT_SYMBOL(pci_choose_state);
    > +
    > +/**
    > * pci_save_state - save the PCI configuration space of a device before suspending
    > * @dev: - PCI device that we're dealing with
    > * @buffer: - buffer to hold config space context
    > @@ -365,7 +389,7 @@
    > {
    > int err;
    >
    > - pci_set_power_state(dev, 0);
    > + pci_set_power_state(dev, PCI_D0);
    > if ((err = pcibios_enable_device(dev, bars)) < 0)
    > return err;
    > return 0;
    > @@ -422,7 +446,7 @@
    > * 0 if operation is successful.
    > *
    > */
    > -int pci_enable_wake(struct pci_dev *dev, u32 state, int enable)
    > +int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable)
    > {
    > int pm;
    > u16 value;
    > --- clean/drivers/usb/core/hcd-pci.c 2004-10-01 00:30:19.000000000 +0200
    > +++ linux/drivers/usb/core/hcd-pci.c 2004-11-14 23:36:46.000000000 +0100
    > @@ -355,8 +355,8 @@
    > hcd->state = USB_STATE_RESUMING;
    >
    > if (has_pci_pm)
    > - pci_set_power_state (dev, 0);
    > - dev->dev.power.power_state = 0;
    > + pci_set_power_state (dev, PCI_D0);
    > + dev->dev.power.power_state = PMSG_ON;
    > retval = request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ,
    > hcd->description, hcd);
    > if (retval < 0) {
    > --- clean/drivers/usb/host/ohci-hub.c 2004-10-19 14:16:28.000000000 +0200
    > +++ linux/drivers/usb/host/ohci-hub.c 2004-11-14 23:36:46.000000000 +0100
    > @@ -76,7 +76,7 @@
    > struct usb_device *root = hcd_to_bus (&ohci->hcd)->root_hub;
    > int status = 0;
    >
    > - if (root->dev.power.power_state != 0)
    > + if (root->dev.power.power_state != PMSG_ON)
    > return 0;
    > if (time_before (jiffies, ohci->next_statechange))
    > return -EAGAIN;
    > --- clean/include/asm-i386/suspend.h 2004-08-15 19:15:04.000000000 +0200
    > +++ linux/include/asm-i386/suspend.h 2004-10-29 11:56:46.000000000 +0200
    > @@ -9,6 +9,9 @@
    > static inline int
    > arch_prepare_suspend(void)
    > {
    > + /* If you want to make non-PSE machine work, turn off paging
    > + in do_magic. swsusp_pg_dir should have identity mapping, so
    > + it could work... */
    > if (!cpu_has_pse)
    > return -EPERM;
    > return 0;
    > --- clean/include/linux/device.h 2004-10-01 00:30:29.000000000 +0200
    > +++ linux/include/linux/device.h 2004-11-04 00:25:52.000000000 +0100
    > @@ -61,7 +61,7 @@
    > int (*match)(struct device * dev, struct device_driver * drv);
    > int (*hotplug) (struct device *dev, char **envp,
    > int num_envp, char *buffer, int buffer_size);
    > - int (*suspend)(struct device * dev, u32 state);
    > + int (*suspend)(struct device * dev, pm_message_t state);
    > int (*resume)(struct device * dev);
    > };
    >
    > --- clean/include/linux/page-flags.h 2004-10-01 00:30:30.000000000 +0200
    > +++ linux/include/linux/page-flags.h 2004-10-19 16:38:18.000000000 +0200
    > @@ -74,7 +74,7 @@
    > #define PG_swapcache 16 /* Swap page: swp_entry_t in private */
    > #define PG_mappedtodisk 17 /* Has blocks allocated on-disk */
    > #define PG_reclaim 18 /* To be reclaimed asap */
    > -
    > +#define PG_nosave_free 19 /* Page is free and should not be written */
    >
    > /*
    > * Global page accounting. One instance per CPU. Only unsigned longs are
    > @@ -277,6 +277,10 @@
    > #define ClearPageNosave(page) clear_bit(PG_nosave, &(page)->flags)
    > #define TestClearPageNosave(page) test_and_clear_bit(PG_nosave, &(page)->flags)
    >
    > +#define PageNosaveFree(page) test_bit(PG_nosave_free, &(page)->flags)
    > +#define SetPageNosaveFree(page) set_bit(PG_nosave_free, &(page)->flags)
    > +#define ClearPageNosaveFree(page) clear_bit(PG_nosave_free, &(page)->flags)
    > +
    > #define PageMappedToDisk(page) test_bit(PG_mappedtodisk, &(page)->flags)
    > #define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags)
    > #define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags)
    > --- clean/include/linux/pci.h 2004-10-01 00:30:30.000000000 +0200
    > +++ linux/include/linux/pci.h 2004-11-14 23:36:46.000000000 +0100
    > @@ -480,6 +480,14 @@
    > #define DEVICE_COUNT_COMPATIBLE 4
    > #define DEVICE_COUNT_RESOURCE 12
    >
    > +typedef int __bitwise pci_power_t;
    > +
    > +#define PCI_D0 ((pci_power_t __force) 0)
    > +#define PCI_D1 ((pci_power_t __force) 1)
    > +#define PCI_D2 ((pci_power_t __force) 2)
    > +#define PCI_D3hot ((pci_power_t __force) 3)
    > +#define PCI_D3cold ((pci_power_t __force) 4)
    > +
    > /*
    > * The pci_dev structure is used to describe PCI devices.
    > */
    > @@ -508,7 +516,7 @@
    > this if your device has broken DMA
    > or supports 64-bit transfers. */
    >
    > - u32 current_state; /* Current operating state. In ACPI-speak,
    > + pci_power_t current_state; /* Current operating state. In ACPI-speak,
    > this is D0-D3, D0 being fully functional,
    > and D3 being off. */
    >
    > @@ -645,7 +653,7 @@
    > struct pci_dynids dynids;
    > };
    >
    > -#define to_pci_driver(drv) container_of(drv,struct pci_driver, driver)
    > +#define to_pci_driver(drv) container_of(drv, struct pci_driver, driver)
    >
    > /**
    > * PCI_DEVICE - macro used to describe a specific pci device
    > @@ -781,8 +789,8 @@
    > /* Power management related routines */
    > int pci_save_state(struct pci_dev *dev, u32 *buffer);
    > int pci_restore_state(struct pci_dev *dev, u32 *buffer);
    > -int pci_set_power_state(struct pci_dev *dev, int state);
    > -int pci_enable_wake(struct pci_dev *dev, u32 state, int enable);
    > +int pci_set_power_state(struct pci_dev *dev, pci_power_t state);
    > +int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable);
    >
    > /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
    > void pci_bus_assign_resources(struct pci_bus *bus);
    > --- clean/include/linux/pm.h 2004-10-01 00:30:30.000000000 +0200
    > +++ linux/include/linux/pm.h 2004-11-14 23:36:46.000000000 +0100
    > @@ -28,44 +28,28 @@
    > #include <asm/atomic.h>
    >
    > /*
    > - * Power management requests
    > + * Power management requests... these are passed to pm_send_all() and friends.
    > + *
    > + * these functions are old and deprecated, see below.
    > */
    > -enum
    > -{
    > - PM_SUSPEND, /* enter D1-D3 */
    > - PM_RESUME, /* enter D0 */
    > -
    > - PM_SAVE_STATE, /* save device's state */
    > +typedef int __bitwise pm_request_t;
    >
    > - /* enable wake-on */
    > - PM_SET_WAKEUP,
    > -
    > - /* bus resource management */
    > - PM_GET_RESOURCES,
    > - PM_SET_RESOURCES,
    > -
    > - /* base station management */
    > - PM_EJECT,
    > - PM_LOCK,
    > -};
    > +#define PM_SUSPEND ((__force pm_request_t) 1) /* enter D1-D3 */
    > +#define PM_RESUME ((__force pm_request_t) 2) /* enter D0 */
    >
    > -typedef int pm_request_t;
    >
    > /*
    > - * Device types
    > + * Device types... these are passed to pm_register
    > */
    > -enum
    > -{
    > - PM_UNKNOWN_DEV = 0, /* generic */
    > - PM_SYS_DEV, /* system device (fan, KB controller, ...) */
    > - PM_PCI_DEV, /* PCI device */
    > - PM_USB_DEV, /* USB device */
    > - PM_SCSI_DEV, /* SCSI device */
    > - PM_ISA_DEV, /* ISA device */
    > - PM_MTD_DEV, /* Memory Technology Device */
    > -};
    > +typedef int __bitwise pm_dev_t;
    >
    > -typedef int pm_dev_t;
    > +#define PM_UNKNOWN_DEV ((__force pm_request_t) 0) /* generic */
    > +#define PM_SYS_DEV ((__force pm_request_t) 1) /* system device (fan, KB controller, ...) */
    > +#define PM_PCI_DEV ((__force pm_request_t) 2) /* PCI device */
    > +#define PM_USB_DEV ((__force pm_request_t) 3) /* USB device */
    > +#define PM_SCSI_DEV ((__force pm_request_t) 4) /* SCSI device */
    > +#define PM_ISA_DEV ((__force pm_request_t) 5) /* ISA device */
    > +#define PM_MTD_DEV ((__force pm_request_t) 6) /* Memory Technology Device */
    >
    > /*
    > * System device hardware ID (PnP) values
    > @@ -119,37 +103,27 @@
    > /*
    > * Register a device with power management
    > */
    > -struct pm_dev *pm_register(pm_dev_t type,
    > - unsigned long id,
    > - pm_callback callback);
    > +struct pm_dev __deprecated *pm_register(pm_dev_t type, unsigned long id, pm_callback callback);
    >
    > /*
    > * Unregister a device with power management
    > */
    > -void pm_unregister(struct pm_dev *dev);
    > +void __deprecated pm_unregister(struct pm_dev *dev);
    >
    > /*
    > * Unregister all devices with matching callback
    > */
    > -void pm_unregister_all(pm_callback callback);
    > +void __deprecated pm_unregister_all(pm_callback callback);
    >
    > /*
    > * Send a request to a single device
    > */
    > -int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data);
    > +int __deprecated pm_send(struct pm_dev *dev, pm_request_t rqst, void *data);
    >
    > /*
    > * Send a request to all devices
    > */
    > -int pm_send_all(pm_request_t rqst, void *data);
    > -
    > -/*
    > - * Find a device
    > - */
    > -struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from);
    > -
    > -static inline void pm_access(struct pm_dev *dev) {}
    > -static inline void pm_dev_idle(struct pm_dev *dev) {}
    > +int __deprecated pm_send_all(pm_request_t rqst, void *data);
    >
    > #else /* CONFIG_PM */
    >
    > @@ -176,16 +150,10 @@
    > return 0;
    > }
    >
    > -static inline struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from)
    > -{
    > - return 0;
    > -}
    > -
    > -static inline void pm_access(struct pm_dev *dev) {}
    > -static inline void pm_dev_idle(struct pm_dev *dev) {}
    > -
    > #endif /* CONFIG_PM */
    >
    > +/* Functions above this comment are list-based old-style power
    > + * managment. Please avoid using them. */
    >
    > /*
    > * Callbacks for platform drivers to implement.
    > @@ -193,34 +161,32 @@
    > extern void (*pm_idle)(void);
    > extern void (*pm_power_off)(void);
    >
    > -enum {
    > - PM_SUSPEND_ON = 0,
    > - PM_SUSPEND_STANDBY = 1,
    > - /* NOTE: PM_SUSPEND_MEM == PCI_D3hot */
    > - PM_SUSPEND_MEM = 3,
    > - PM_SUSPEND_DISK = 4,
    > - PM_SUSPEND_MAX = 5,
    > -};
    > -
    > -enum {
    > - PM_DISK_FIRMWARE = 1,
    > - PM_DISK_PLATFORM,
    > - PM_DISK_SHUTDOWN,
    > - PM_DISK_REBOOT,
    > - PM_DISK_MAX,
    > -};
    > +typedef int __bitwise suspend_state_t;
    >
    > +#define PM_SUSPEND_ON ((__force suspend_state_t) 0)
    > +#define PM_SUSPEND_STANDBY ((__force suspend_state_t) 1)
    > +#define PM_SUSPEND_MEM ((__force suspend_state_t) 3)
    > +#define PM_SUSPEND_DISK ((__force suspend_state_t) 4)
    > +#define PM_SUSPEND_MAX ((__force suspend_state_t) 5)
    > +
    > +typedef int __bitwise suspend_disk_method_t;
    > +
    > +#define PM_DISK_FIRMWARE ((__force suspend_disk_method_t) 1)
    > +#define PM_DISK_PLATFORM ((__force suspend_disk_method_t) 2)
    > +#define PM_DISK_SHUTDOWN ((__force suspend_disk_method_t) 3)
    > +#define PM_DISK_REBOOT ((__force suspend_disk_method_t) 4)
    > +#define PM_DISK_MAX ((__force suspend_disk_method_t) 5)
    >
    > struct pm_ops {
    > - u32 pm_disk_mode;
    > - int (*prepare)(u32 state);
    > - int (*enter)(u32 state);
    > - int (*finish)(u32 state);
    > + suspend_disk_method_t pm_disk_mode;
    > + int (*prepare)(suspend_state_t state);
    > + int (*enter)(suspend_state_t state);
    > + int (*finish)(suspend_state_t state);
    > };
    >
    > extern void pm_set_ops(struct pm_ops *);
    >
    > -extern int pm_suspend(u32 state);
    > +extern int pm_suspend(suspend_state_t state);
    >
    >
    > /*
    > @@ -229,10 +195,34 @@
    >
    > struct device;
    >
    > +typedef u32 __bitwise pm_message_t;
    > +
    > +/*
    > + * There are 4 important states driver can be in:
    > + * ON -- driver is working
    > + * FREEZE -- stop operations and apply whatever policy is applicable to a suspended driver
    > + * of that class, freeze queues for block like IDE does, drop packets for
    > + * ethernet, etc... stop DMA engine too etc... so a consistent image can be
    > + * saved; but do not power any hardware down.
    > + * SUSPEND - like FREEZE, but hardware is doing as much powersaving as possible. Roughly
    > + * pci D3.
    > + *
    > + * Unfortunately, current drivers only recognize numeric values 0 (ON) and 3 (SUSPEND).
    > + * We'll need to fix the drivers. So yes, putting 3 to all diferent defines is intentional,
    > + * and will go away as soon as drivers are fixed. Also note that typedef is neccessary,
    > + * we'll probably want to switch to
    > + * typedef struct pm_message_t { int event; int flags; } pm_message_t
    > + * or something similar soon.
    > + */
    > +
    > +#define PMSG_FREEZE ((__force pm_message_t) 3)
    > +#define PMSG_SUSPEND ((__force pm_message_t) 3)
    > +#define PMSG_ON ((__force pm_message_t) 0)
    > +
    > struct dev_pm_info {
    > - u32 power_state;
    > + pm_message_t power_state;
    > #ifdef CONFIG_PM
    > - u32 prev_state;
    > + pm_message_t prev_state;
    > u8 * saved_state;
    > atomic_t pm_users;
    > struct device * pm_parent;
    > @@ -242,8 +232,8 @@
    >
    > extern void device_pm_set_parent(struct device * dev, struct device * parent);
    >
    > -extern int device_suspend(u32 state);
    > -extern int device_power_down(u32 state);
    > +extern int device_suspend(pm_message_t state);
    > +extern int device_power_down(pm_message_t state);
    > extern void device_power_up(void);
    > extern void device_resume(void);
    >
    > --- clean/include/linux/suspend.h 2004-10-01 00:30:31.000000000 +0200
    > +++ linux/include/linux/suspend.h 2004-10-29 11:56:46.000000000 +0200
    > @@ -31,6 +31,7 @@
    >
    > /* mm/page_alloc.c */
    > extern void drain_local_pages(void);
    > +extern void mark_free_pages(struct zone *zone);
    >
    > /* kernel/power/swsusp.c */
    > extern int software_suspend(void);
    > @@ -54,6 +55,8 @@
    >
    > #else
    > static inline void refrigerator(unsigned long flag) {}
    > +static inline int freeze_processes(void) { BUG(); }
    > +static inline void thaw_processes(void) {}
    > #endif /* CONFIG_PM */
    >
    > #ifdef CONFIG_SMP
    > --- clean/kernel/power/disk.c 2004-10-01 00:30:32.000000000 +0200
    > +++ linux/kernel/power/disk.c 2004-11-16 13:14:09.000000000 +0100
    > @@ -3,6 +3,7 @@
    > *
    > * Copyright (c) 2003 Patrick Mochel
    > * Copyright (c) 2003 Open Source Development Lab
    > + * Copyright (c) 2004 Pavel Machek <pavel@suse.cz>
    > *
    > * This file is released under the GPLv2.
    > *
    > @@ -15,10 +16,11 @@
    > #include <linux/device.h>
    > #include <linux/delay.h>
    > #include <linux/fs.h>
    > +#include <linux/device.h>
    > #include "power.h"
    >
    >
    > -extern u32 pm_disk_mode;
    > +extern suspend_disk_method_t pm_disk_mode;
    > extern struct pm_ops * pm_ops;
    >
    > extern int swsusp_suspend(void);
    > @@ -41,7 +43,7 @@
    > * there ain't no turning back.
    > */
    >
    > -static int power_down(u32 mode)
    > +static void power_down(suspend_disk_method_t mode)
    > {
    > unsigned long flags;
    > int error = 0;
    > @@ -49,7 +51,7 @@
    > local_irq_save(flags);
    > switch(mode) {
    > case PM_DISK_PLATFORM:
    > - device_power_down(PM_SUSPEND_DISK);
    > + device_power_down(PMSG_SUSPEND);
    > error = pm_ops->enter(PM_SUSPEND_DISK);
    > break;
    > case PM_DISK_SHUTDOWN:
    > @@ -67,7 +69,6 @@
    > after resume. */
    > printk(KERN_CRIT "Please power me down manually\n");
    > while(1);
    > - return 0;
    > }
    >
    >
    > @@ -85,13 +86,26 @@
    >
    > static void free_some_memory(void)
    > {
    > - printk("Freeing memory: ");
    > - while (shrink_all_memory(10000))
    > - printk(".");
    > - printk("|\n");
    > + int i;
    > + for (i=0; i<5; i++) {
    > + int i = 0, tmp;
    > + long pages = 0;
    > + char *p = "-\\|/";
    > +
    > + printk("Freeing memory... ");
    > + while ((tmp = shrink_all_memory(10000))) {
    > + pages += tmp;
    > + printk("\b%c", p[i]);
    > + i++;
    > + if (i > 3)
    > + i = 0;
    > + }
    > + printk("\bdone (%li pages freed)\n", pages);
    > + current->state = TASK_INTERRUPTIBLE;
    > + schedule_timeout(HZ/5);

    This should be msleep_interruptible() [I do not see any wait-queue events around
    this code].

    -Nish
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/


  • Next message: Pavel Machek: "Re: swsusp bigdiff [was Re: [PATCH] Software Suspend split to two stage V2.]"

    Relevant Pages