From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id ; Tue, 21 May 2002 18:31:28 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id ; Tue, 21 May 2002 18:31:27 -0400 Received: from [195.39.17.254] ([195.39.17.254]:19098 "EHLO Elf.ucw.cz") by vger.kernel.org with ESMTP id ; Tue, 21 May 2002 18:31:03 -0400 Date: Wed, 22 May 2002 00:28:59 +0200 From: Pavel Machek To: kernel list , torvalds@transmeta.com, ACPI mailing list Subject: suspend-to-{RAM,disk} for 2.5.17 Message-ID: <20020521222858.GA14737@elf.ucw.cz> Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit User-Agent: Mutt/1.3.28i X-Warning: Reading this can be dangerous to your mental health. Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Hi! Here's suspend-to-{RAM,disk} combined patch for 2.5.17. Suspend-to-disk is pretty stable and was tested in 2.4-ac. Suspend-to-RAM is little more experimental, but works for me, and is certainly better than disk-eating version currently in kernel. Major parts are: process stopper, S3 specific code, S4 specific code. What can I do to make this applied? Pavel --- clean/Documentation/driver-model.txt Sun Mar 10 20:06:28 2002 +++ linux-swsusp/Documentation/driver-model.txt Fri May 3 00:08:35 2002 @@ -52,7 +52,8 @@ Each bus layer should implement the callbacks for these drivers. It then forwards the calls on to the device-specific callbacks. This means that device-specific drivers must still implement callbacks for each operation. -But, they are not called from the top level driver layer. +But, they are not called from the top level driver layer. [So for example +PCI devices will not call device_register but pci_device_register.] This does add another layer of indirection for calling one of these functions, but there are benefits that are believed to outweigh this slowdown. @@ -60,7 +61,7 @@ First, it prevents device-specific drivers from having to know about the global device layer. This speeds up integration time incredibly. It also allows drivers to be more portable across kernel versions. Note that the -former was intentional, the latter is an added bonus. +former was intentional, the latter is an added bonus. Second, this added indirection allows the bus to perform any additional logic necessary for its child devices. A bus layer may add additional information to @@ -225,7 +226,6 @@ It also allows the platform driver (e.g. ACPI) to a driver without the driver having to have explicit knowledge of (atrocities like) ACPI. - current_state: Current power state of the device. For PCI and other modern devices, this is 0-3, though it's not necessarily limited to those values. @@ -251,18 +251,24 @@ } probe: - Check for device existence and associate driver with it. + Check for device existence and associate driver with it. In case of device + insertion, *all* drivers are called. Struct device has parent and bus_id + valid at this point. probe() may only be called from process context. Returns + 0 if it handles that device, -ESRCH if this driver does not know how to handle + this device, valid error otherwise. remove: Dissociate driver with device. Releases device so that it could be used by another driver. Also, if it is a hotplug device (hotplug PCI, Cardbus), an - ejection event could take place here. + ejection event could take place here. remove() can be called from interrupt + context. [Fixme: Is that good?] Returns 0 on success. [Can we recover from + failed remove or should I define that remove() never fails?] suspend: - Perform one step of the device suspend process. + Perform one step of the device suspend process. Returns 0 on success. resume: - Perform one step of the device resume process. + Perform one step of the device resume process. Returns 0 on success. The probe() and remove() callbacks are intended to be much simpler than the current PCI correspondents. @@ -275,7 +281,7 @@ Some device initialisation was done in probe(). This should not be the case anymore. All initialisation should take place in the open() call for the -device. +device. [FIXME: How do you "open" uhci?] Breaking initialisation code out must also be done for the resume() callback, as most devices will have to be completely reinitialised when coming back from @@ -324,6 +330,7 @@ enum{ SUSPEND_NOTIFY, + SUSPEND_DISABLE, SUSPEND_SAVE_STATE, SUSPEND_POWER_DOWN, }; @@ -331,6 +338,7 @@ enum { RESUME_POWER_ON, RESUME_RESTORE_STATE, + RESUME_ENABLE, }; @@ -352,9 +360,9 @@ Instead, the walking of the device tree has been moved to userspace. When a user requests the system to suspend, it will walk the device tree, as exported via driverfs, and tell each device to go to sleep. It will do this multiple -times based on what the system policy is. - -[ FIXME: URL pointer to the corresponding utility is missing here! ] +times based on what the system policy is. [Not possible. Take ACPI enabled +system, with battery critically low. In such state, you want to suspend-to-disk, +*fast*. User maybe is not even running powerd (think system startup)!] Device resume should happen in the same manner when the system awakens. @@ -366,22 +374,25 @@ cannot resume the hardware from the requested level, or it feels that it is too important to be put to sleep, it should return an error from this function. -It does not have to stop I/O requests or actually save state at this point. +It does not have to stop I/O requests or actually save state at this point. Called +from process context. SUSPEND_DISABLE: The driver should stop taking I/O requests at this stage. Because the save state stage happens afterwards, the driver may not want to physically disable -the device; only mark itself unavailable if possible. +the device; only mark itself unavailable if possible. Called from process +context. SUSPEND_SAVE_STATE: The driver should allocate memory and save any device state that is relevant -for the state it is going to enter. +for the state it is going to enter. Called from process context. SUSPEND_POWER_DOWN: -The driver should place the device in the power state requested. +The driver should place the device in the power state requested. May be called +from interrupt context. For resume, the stages are defined as follows: @@ -389,25 +400,27 @@ RESUME_POWER_ON: Devices should be powered on and reinitialised to some known working state. +Called from process context. RESUME_RESTORE_STATE: The driver should restore device state to its pre-suspend state and free any -memory allocated for its saved state. +memory allocated for its saved state. Called from process context. RESUME_ENABLE: -The device should start taking I/O requests again. +The device should start taking I/O requests again. Called from process context. Each driver does not have to implement each stage. But, it if it does -implemente a stage, it should do what is described above. It should not assume +implement a stage, it should do what is described above. It should not assume that it performed any stage previously, or that it will perform any stage -later. +later. [Really? It makes sense to support SAVE_STATE only after DISABLE]. It is quite possible that a driver can fail during the suspend process, for whatever reason. In this event, the calling process must gracefully recover -and restore everything to their states before the suspend transition began. +and restore everything to their states before the suspend transition began. +[Suspend may not fail, think battery low.] If a driver knows that it cannot suspend or resume properly, it should fail during the notify stage. Properly implemented power management schemes should --- clean/Documentation/swsusp.txt Sat Jan 5 21:39:47 2002 +++ linux-swsusp/Documentation/swsusp.txt Fri May 3 00:08:35 2002 @@ -0,0 +1,159 @@ +From kernel/suspend.c: + + * BIG FAT WARNING ********************************************************* + * + * If you have unsupported (*) devices using DMA... + * ...say goodbye to your data. + * + * If you touch anything on disk between suspend and resume... + * ...kiss your data goodbye. + * + * If your disk driver does not support suspend... (IDE does) + * ...you'd better find out how to get along + * without your data. + * + * (*) pm interface 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. + +[Notice. Rest docs is pretty outdated (see date!) It should be safe to +use swsusp on ext3/reiserfs these days.] + + +Article about goals and implementation of Software Suspend for Linux +Author: G‚ábor Kuti +Last revised: 2002-04-08 + +Idea and goals to achieve + +Nowadays it is common in several laptops that they have a suspend button. It +saves the state of the machine to a filesystem or to a partition and switches +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 +interrupt our programs so processes that are calculating something for a long +time shouldn't need to be written interruptible. + +On desk machines the power saving function isn't as important as it is in +laptops but we really may benefit from the second one. Nowadays the number of +desk machines supporting suspend function in their APM is going up but there +are (and there will still be for a long time) machines that don't even support +APM of any kind. On the other hand it is reported that using APM's suspend +some irqs (e.g. ATA disk irq) is lost and it is annoying for the user until +the Linux kernel resets the device. + +So I started thinking about implementing Software Suspend which doesn't need +any APM support and - since it uses pretty near only high-level routines - is +supposed to be architecture independent code. + +Using the code + +The code is experimental right now - testers, extra eyes are welcome. To +compile this support into the kernel, you need CONFIG_EXPERIMENTAL, +and then CONFIG_SOFTWARE_SUSPEND in menu General Setup to be enabled. It +cannot be used as a module and I don't think it will ever be needed. + +You have two ways to use this code. The first one is if you've compiled in +sysrq support then you may press Sysrq-D to request suspend. The other way +is with a patched SysVinit (my patch is against 2.76 and available at my +home page). You might call 'swsusp' or 'shutdown -z