Re: [linux-pm] [demo patch/RFC] sleepy linux



On Tue, 26 Feb 2008 11:26:53 +0100 Pavel Machek wrote:


Hi Pavel,

Is this limited to UP and only one disk?

[comments below]


Sleepy linux support, demo version, but it works on my thinkpad x60 ;-).

Signed-off-by: Pavel Machek <pavel@xxxxxxx>

diff --git a/Documentation/power/sleepy.txt b/Documentation/power/sleepy.txt
new file mode 100644
index 0000000..a9caf05
--- /dev/null
+++ b/Documentation/power/sleepy.txt
@@ -0,0 +1,55 @@
+ Sleepy Linux
+ ~~~~~~~~~~~~
+
+Copyright 2007 Pavel Machek <pavel@xxxxxxx>
+ GPLv2
+
+Current Linux versions can enter suspend-to-RAM just fine, but only
+can do it on explicit request. But suspend-to-RAM is important, eating

Usually "can only do it" AFAIK.

+something like 10% of power needed for idle system. Starting suspend
+manually is not too convinient; it is not an option on multiuser

convenient;

+machine, and even on single user machine, some things are not easy:
+
+1) Download this big chunk in mozilla, then go to sleep
+
+2) Compile this, then go to sleep
+
+3) You can sleep now, but wake me up in 8:30 with mp3 player
+
+Todays hardware is mostly capable of doing better: with correctly set

Today's

+up wakeups, machine can sleep and successfully pretend it is not
+sleeping -- by waking up whenever something interesting happens. Of
+course, it is easier on machines not connected to the network, and on
+notebook computers.
+
+Requirements:
+
+0) Working suspend-to-RAM, with kernel being able to bring video back.
+
+1) RTC clock that can wake up system
+
+2) Lid that can wake up a system,
+ or keyboard that can wake up system and does not loose keypress

lose

+ or special screensaver setup
+
+3) Network card that is either down
+ or can wake up system on any packet (and not loose too many packets)

lose

+
+How to use it
+~~~~~~~~~~~~~
+
+First, make sure your config is tiny enough that cpu sleeps at least

CPU (please)

+five or so seconds between wakeups. You'll probably need to disable
+USB, make some kernel timers way longer than default and boot with
+init=/bin/bash.
+
+Then, enable SCSI powersave by something like:
+
+mount /sys

Isn't /sys auto-mounted by kernel?

+echo auto > /sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/power/level
+echo 3 > /sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/power/autosuspend
+echo adisk > /sys/power/state
+mount / -oremount,commit=900
+
+Then, echo auto > /sys/power/state should enable sleepy support. Do it
+twice, and it will ignore open lid and sleep anyway.

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 29e71bd..0197b1f 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -268,6 +269,41 @@ static struct class_device_attribute *ah
NULL
};

+struct pci_dev *my_pdev;
+int autosuspend_enabled;
+
+struct sleep_disabled_reason ahci_active = {
+ "ahci"
+};
+
+/* The host and its devices are all idle so we can autosuspend */
+static int autosuspend(struct Scsi_Host *host)
+{
+ if (my_pdev && autosuspend_enabled) {
+ printk("ahci: should autosuspend\n");

Use printk() KERN_* levels (multiple places).


+ ahci_pci_device_suspend(my_pdev, PMSG_SUSPEND);
+ enable_auto_sleep(&ahci_active);
+ return 0;
+ }
+ printk("ahci: autosuspend disabled\n");
+ return -EINVAL;
+}
+
...
+}
+
+
+
static struct scsi_host_template ahci_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
@@ -1820,6 +1858,10 @@ static void ahci_thaw(struct ata_port *a

static void ahci_error_handler(struct ata_port *ap)
{
+ struct ata_host *host = ap->host;
+ int rc;
+ extern int slept;

Eh?

+
if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
/* restart engine */
ahci_stop_engine(ap);

General comment: Lots of the comment fixes in libata should be part
of a standalone patch, not part of this patch.


diff --git a/include/linux/ata.h b/include/linux/ata.h
index 78bbaca..df2dd4f 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -298,6 +298,13 @@ enum {
SCR_ACTIVE = 3,
SCR_NOTIFICATION = 4,

+ /* SControl subfields, each field is 4 bit wide */

bits

+ ATA_SCTL_DET = 0, /* lsb */
+ ATA_SCTL_SPD = 1,
+ ATA_SCTL_IPM = 2,
+ ATA_SCTL_SPM = 3,
+ ATA_SCTL_PMP = 4,
+
/* SError bits */
SERR_DATA_RECOVERED = (1 << 0), /* recovered data error */
SERR_COMM_RECOVERED = (1 << 1), /* recovered comm failure */

diff --git a/kernel/power/main.c b/kernel/power/main.c
index a29da58..2470e94 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -3,6 +3,7 @@
*
* Copyright (c) 2003 Patrick Mochel
* Copyright (c) 2003 Open Source Development Lab
+ * Copyright (c) 2007 Pavel Machek <pavel@xxxxxxx>

It's 2008 now.

*
* This file is released under the GPLv2
*
@@ -22,7 +23,10 @@ #include <linux/freezer.h>
#include <linux/vmstat.h>
#include <linux/syscalls.h>

+#include <asm/percpu.h>
+
#include "power.h"
+#include "../../drivers/scsi/scsi_priv.h"

ugh.

DEFINE_MUTEX(pm_mutex);

@@ -426,6 +437,76 @@ static int enter_state(suspend_state_t s
return error;
}

+/* Returns how long it waited in ms */
+//extern long (*panic_blink)(long time);
+
+int slept;
+
+
+struct sleep_disabled_reason wakeup_tasks = {
+ "wakeup_tasks"
+};
+
+int device_suspend_fake(pm_message_t state);
+
+int
+do_auto_sleep(void)

All on one line.

+{
+ int error,i;

space after comma.

+ int state = PM_SUSPEND_MEM;
+
+ /* add baby "morning tasks" to the lists. BUG if it is not
+ the only baby */
+
+ if (slept)
+ return;
+ slept++;
+ disable_auto_sleep(&wakeup_tasks);
+// device_suspend_fake(PMSG_SUSPEND);
+ suspend_enter(state);
+
+ /* FIXME: run "morning tasks" in process context; drivers need to check why
+ machine was woken, and perhaps put themselves back to crying babies list
+ if lid was opened or something. */
+
+ enable_auto_sleep(&wakeup_tasks);
+
+#if 0
+ printk("finishing\n");
+ if (suspend_ops->finish)
+ suspend_ops->finish();
+#endif
+
+ return 0;
+}
+
+extern int set_alarm(int length);
+
+void
+enter_auto_sleep(int length)

All on one line.

+{
+ int error;
+
+ if (atomic_read(&cpu_needed))
+ return;
+
+ printk("Auto sleeping\n");
+ set_alarm(length);
+
+ error = do_auto_sleep();
+ if (error)
+ printk("enter auto sleep failed: %d\n", error);
+}

/**
* pm_suspend - Externally visible function for suspending system.
@@ -481,6 +562,12 @@ #endif
return (s - buf);
}

+extern struct pci_dev *my_pdev;
+extern int autosuspend_enabled;
+extern struct device *my_scsi_disk;
+extern int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
+extern int ahci_pci_device_resume(struct pci_dev *pdev);
+

Externs in header files, please.

static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t n)
{
...


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



Relevant Pages

  • [RFC] sleepy linux
    ... Download this big chunk in mozilla, then go to sleep ... but wake me up in 8:30 with mp3 player ... +void detect_idle; ... static int enter_state ...
    (Linux-Kernel)
  • Re: beginners question - sleep in joined threads
    ... Is there any sound reason that the sleep call does not wake up in this ... int main{ ...
    (comp.programming.threads)
  • beginners question - sleep in joined threads
    ... Is there any sound reason that the sleep call does not wake up in this ... int main{ ...
    (comp.programming.threads)
  • Re: Who needs AppleTV?
    ... I said "about one second" long before you started to drag up specs of unrelated hard drives. ... "Are you actually trying to claim that a Mac laptop won't wake ... from sleep in about a second?" ...     in a second. ...
    (comp.sys.mac.advocacy)
  • Re: Off switch blues
    ... "It" is the operating system. ... Here's what the Apple documentation says: "To wake your computer from ... sleep, press a key on the keyboard, or click the mouse. ... requires this), the problem is that it STAYS awake, even though the user ...
    (comp.sys.mac.system)