[demo patch/RFC] sleepy linux
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(_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(_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
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(_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
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 [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 = (1 0), /* recovered data error */ SERR_COMM_RECOVERED = (1 1), /* recovered comm failure */ diff --git a/kernel/power/main.c
[demo patch/RFC] sleepy linux
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 linux/kernel.h #include linux/module.h #include linux/pci.h @@ -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, +