[demo patch/RFC] sleepy linux

2008-02-26 Thread Pavel Machek


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

Signed-off-by: Pavel Machek <[EMAIL PROTECTED]>

diff --git a/Documentation/power/sleepy.txt b/Documentation/power/sleepy.txt
new file mode 100644
index 000..a9caf05
--- /dev/null
+++ b/Documentation/power/sleepy.txt
@@ -0,0 +1,55 @@
+   Sleepy Linux
+   
+
+Copyright 2007 Pavel Machek <[EMAIL PROTECTED]>
+ 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
+something like 10% of power needed for idle system. Starting suspend
+manually is not too convinient; it is not an option on multiuser
+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
+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
+   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)
+
+How to use it
+~
+
+First, make sure your config is tiny enough that cpu sleeps at least
+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
+echo auto > 
/sys/devices/pci:00/:00:1f.2/host0/target0:0:0/0:0:0:0/power/level
+echo 3 > 
/sys/devices/pci:00/: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/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index a7d50a5..4c25613 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -187,6 +187,7 @@ void cpu_idle(void)
/* endless idle loop with no priority at all */
while (1) {
tick_nohz_stop_sched_tick();
+   detect_idle();
while (!need_resched()) {
void (*idle)(void);
 
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
@@ -32,6 +32,7 @@
  *
  */
 
+#define DEBUG
 #include 
 #include 
 #include 
@@ -259,8 +260,8 @@ static void ahci_fill_cmd_slot(struct ah
   u32 opts);
 #ifdef CONFIG_PM
 static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
-static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
-static int ahci_pci_device_resume(struct pci_dev *pdev);
+int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
+int ahci_pci_device_resume(struct pci_dev *pdev);
 #endif
 
 static struct class_device_attribute *ahci_shost_attrs[] = {
@@ -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");
+   ahci_pci_device_suspend(my_pdev, PMSG_SUSPEND);
+   enable_auto_sleep(&ahci_active);
+   return 0;
+   } 
+   printk("ahci: autosuspend disabled\n");
+   return -EINVAL;
+}
+
+/* The host needs to be autoresumed */
+static int autoresume(struct Scsi_Host *host)
+{
+   if (my_pdev && autosuspend_enabled) {
+   printk("ahci: should autoresume\n");
+   disable_auto_sleep(&ahci_active);
+   ahci_pci_device_resume(my_pdev);
+   return 0;
+   }
+   printk("ahci: autoresume disabled\n");
+   return -EINVAL;
+}
+
+
+
 static struct scsi_host_template ahci_sht = {
.module = THIS_MODULE,
.name   = DRV_NAME,
@@ -286,6 +322,8 @@ static struct scsi_host_template ahci_sh
.slave_destroy  = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
.shost_attrs= ahci_shost_attrs,
+   .autosuspend= autosuspend,
+   .autoresume 

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

2008-02-26 Thread Randy Dunlap
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 <[EMAIL PROTECTED]>
> 
> diff --git a/Documentation/power/sleepy.txt b/Documentation/power/sleepy.txt
> new file mode 100644
> index 000..a9caf05
> --- /dev/null
> +++ b/Documentation/power/sleepy.txt
> @@ -0,0 +1,55 @@
> + Sleepy Linux
> + 
> +
> +Copyright 2007 Pavel Machek <[EMAIL PROTECTED]>
> +   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/pci:00/:00:1f.2/host0/target0:0:0/0:0:0:0/power/level
> +echo 3 > 
> /sys/devices/pci:00/: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