Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a2d5b70 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Linus Torvalds
Browse files

PM: Introduce PM_EVENT_HIBERNATE callback state

During the last step of hibernation in the "platform" mode (with the
help of ACPI) we use the suspend code, including the devices'
->suspend() methods, to prepare the system for entering the ACPI S4
system sleep state.

But at least for some devices the operations performed by the
->suspend() callback in that case must be different from its operations
during regular suspend.

For this reason, introduce the new PM event type PM_EVENT_HIBERNATE and
pass it to the device drivers' ->suspend() methods during the last phase
of hibernation, so that they can distinguish this case and handle it as
appropriate.  Modify the drivers that handle PM_EVENT_SUSPEND in a
special way and need to handle PM_EVENT_HIBERNATE in the same way.

These changes are necessary to fix a hibernation regression related
to the i915 driver (ref. http://lkml.org/lkml/2008/2/22/488

).

Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Acked-by: default avatarPavel Machek <pavel@ucw.cz>
Tested-by: default avatarJeff Chua <jeff.chua.linux@gmail.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 39273b58
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -310,9 +310,12 @@ used with suspend-to-disk:
    PM_EVENT_SUSPEND -- quiesce the driver and put hardware into a low-power
	state.  When used with system sleep states like "suspend-to-RAM" or
	"standby", the upcoming resume() call will often be able to rely on
	state kept in hardware, or issue system wakeup events.  When used
	instead with suspend-to-disk, few devices support this capability;
	most are completely powered off.
	state kept in hardware, or issue system wakeup events.

    PM_EVENT_HIBERNATE -- Put hardware into a low-power state and enable wakeup
	events as appropriate.  It is only used with hibernation
	(suspend-to-disk) and few devices are able to wake up the system from
	this state; most are completely powered off.

    PM_EVENT_FREEZE -- quiesce the driver, but don't necessarily change into
	any low power mode.  A system snapshot is about to be taken, often
@@ -329,8 +332,8 @@ used with suspend-to-disk:
	wakeup events nor DMA are allowed.

To enter "standby" (ACPI S1) or "Suspend to RAM" (STR, ACPI S3) states, or
the similarly named APM states, only PM_EVENT_SUSPEND is used; for "Suspend
to Disk" (STD, hibernate, ACPI S4), all of those event codes are used.
the similarly named APM states, only PM_EVENT_SUSPEND is used; the other event
codes are used for hibernation ("Suspend to Disk", STD, ACPI S4).

There's also PM_EVENT_ON, a value which never appears as a suspend event
but is sometimes used to record the "not suspended" device state.
+1 −1
Original line number Diff line number Diff line
@@ -1932,7 +1932,7 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
	u32 ctl;

	if (mesg.event == PM_EVENT_SUSPEND) {
	if (mesg.event & PM_EVENT_SLEEP) {
		/* AHCI spec rev1.1 section 8.3.3:
		 * Software must disable interrupts prior to requesting a
		 * transition of the HBA to D3 state.
+1 −1
Original line number Diff line number Diff line
@@ -1339,7 +1339,7 @@ static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
	 * cycles and power trying to do something to the sleeping
	 * beauty.
	 */
	if (piix_broken_suspend() && mesg.event == PM_EVENT_SUSPEND) {
	if (piix_broken_suspend() && (mesg.event & PM_EVENT_SLEEP)) {
		pci_save_state(pdev);

		/* mark its power state as "unknown", since we don't
+1 −1
Original line number Diff line number Diff line
@@ -7368,7 +7368,7 @@ void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg)
	pci_save_state(pdev);
	pci_disable_device(pdev);

	if (mesg.event == PM_EVENT_SUSPEND)
	if (mesg.event & PM_EVENT_SLEEP)
		pci_set_power_state(pdev, PCI_D3hot);
}

+2 −2
Original line number Diff line number Diff line
@@ -1254,7 +1254,7 @@ pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t mesg)
	int		rc = 0;

	if (mesg.event != mdev->ofdev.dev.power.power_state.event
			&& mesg.event == PM_EVENT_SUSPEND) {
			&& (mesg.event & PM_EVENT_SLEEP)) {
		rc = pmac_ide_do_suspend(hwif);
		if (rc == 0)
			mdev->ofdev.dev.power.power_state = mesg;
@@ -1364,7 +1364,7 @@ pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
	int		rc = 0;
	
	if (mesg.event != pdev->dev.power.power_state.event
			&& mesg.event == PM_EVENT_SUSPEND) {
			&& (mesg.event & PM_EVENT_SLEEP)) {
		rc = pmac_ide_do_suspend(hwif);
		if (rc == 0)
			pdev->dev.power.power_state = mesg;
Loading