2007-12-25 23:09:36

by Pavel Machek

[permalink] [raw]
Subject: [RFC] sleepy linux

This is RFC. It does not even work for me... it sleeps but it will not
wake up, because SATA wakeup code is missing. Code attached for illustration.

I wonder if this is the right approach? What is right interface to the
drivers?


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)



diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 9663c2a..0f65aa9 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -178,6 +178,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/input/input-polldev.c b/drivers/input/input-polldev.c
index 92b3598..83a8046 100644
--- a/drivers/input/input-polldev.c
+++ b/drivers/input/input-polldev.c
@@ -151,7 +151,7 @@ int input_register_polled_device(struct

INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
if (!dev->poll_interval)
- dev->poll_interval = 500;
+ dev->poll_interval = 50000;
input->private = dev;
input->open = input_open_polled_device;
input->close = input_close_polled_device;
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 307c7b5..2deca60 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -263,8 +263,14 @@ void input_event(struct input_dev *dev,
{
unsigned long flags;

- if (is_event_supported(type, dev->evbit, EV_MAX)) {
+ if ((type == EV_SW) && (code == SW_LID)) {
+ int is_closed = value;
+ printk("LID: %d\n", value);
+ if (is_closed) atomic_dec(&cpu_needed);
+ else atomic_inc(&cpu_needed);
+ }

+ if (is_event_supported(type, dev->evbit, EV_MAX)) {
spin_lock_irqsave(&dev->event_lock, flags);
add_input_randomness(type, code, value);
input_handle_event(dev, type, code, value);
@@ -1575,6 +1581,8 @@ static int __init input_init(void)
goto fail2;
}

+ /* FIXME: should only inc it if LID is open */
+ atomic_inc(&cpu_needed);
return 0;

fail2: input_proc_exit();
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index 2ae0e83..ba5e806 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -149,16 +149,6 @@ rtc_sysfs_set_wakealarm(struct device *d

alarm = simple_strtoul(buf, NULL, 0);
if (alarm > now) {
- /* Avoid accidentally clobbering active alarms; we can't
- * entirely prevent that here, without even the minimal
- * locking from the /dev/rtcN api.
- */
- retval = rtc_read_alarm(rtc, &alm);
- if (retval < 0)
- return retval;
- if (alm.enabled)
- return -EBUSY;
-
alm.enabled = 1;
} else {
alm.enabled = 0;
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 09a309b..991af06 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -246,6 +246,10 @@ #define device_init_wakeup(dev,val) \
device_set_wakeup_enable(dev,val); \
} while(0)

+void detect_idle(void);
+void enter_auto_sleep(void);
+extern atomic_t cpu_needed;
+
#endif /* __KERNEL__ */

#endif /* _LINUX_PM_H */
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 3cdf95b..fc1c7c1 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -22,6 +22,8 @@ #include <linux/freezer.h>
#include <linux/vmstat.h>
#include <linux/syscalls.h>

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

BLOCKING_NOTIFIER_HEAD(pm_chain_head);
@@ -145,6 +147,8 @@ static int suspend_enter(suspend_state_t
* suspend_devices_and_enter - suspend devices and enter the desired system sleep
* state.
* @state: state to enter
+ *
+ * Needs to be called from process state and may sleep.
*/
int suspend_devices_and_enter(suspend_state_t state)
{
@@ -224,6 +228,8 @@ static inline int valid_state(suspend_st
* happen when we wake up.
* Then, do the setup for suspend, enter the state, and cleaup (after
* we've woken up).
+ *
+ * Needs to be called from process context, and may sleep.
*/
static int enter_state(suspend_state_t state)
{
@@ -253,6 +259,40 @@ 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;
+
+int
+do_auto_sleep(void)
+{
+ int error,i;
+ int state = PM_SUSPEND_MEM;
+
+ if (slept)
+ return;
+ slept++;
+ suspend_enter(state);
+
+ for (i=0; i<10; i++) {
+ panic_blink(10);
+ mdelay(100);
+ }
+
+// if (suspend_ops->finish)
+// suspend_ops->finish();
+
+ return 0;
+}
+
+void
+enter_auto_sleep(void)
+{
+ int error = do_auto_sleep();
+ if (error)
+ printk("enter auto sleep failed: %d\n", error);
+}

/**
* pm_suspend - Externally visible function for suspending system.
@@ -321,6 +361,30 @@ #endif
p = memchr(buf, '\n', n);
len = p ? p - buf : n;

+ if (len == 4 && !strncmp(buf, "auto", len)) {
+ static int acpi_ready = 0;
+ if (!acpi_ready) {
+ int error;
+ int state = PM_SUSPEND_MEM;
+
+ if (suspend_ops->set_target) {
+ error = suspend_ops->set_target(state);
+ if (error)
+ return error;
+ }
+
+ if (suspend_ops->prepare) {
+ error = suspend_ops->prepare();
+ if (error)
+ return error;
+ }
+ acpi_ready = 1;
+ }
+ atomic_dec(&cpu_needed);
+ error = 0;
+ goto Exit;
+ }
+
/* First, check if we are requested to hibernate */
if (len == 4 && !strncmp(buf, "disk", len)) {
error = hibernate();
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index cb89fa8..456a662 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -9,7 +9,7 @@
*
* Started by: Thomas Gleixner and Ingo Molnar
*
- * For licencing details see kernel-base/COPYING
+ * Distribute under GPLv2.
*/
#include <linux/cpu.h>
#include <linux/err.h>
@@ -502,7 +508,7 @@ #endif /* NO_HZ */
*/
#ifdef CONFIG_HIGH_RES_TIMERS
/*
- * We rearm the timer until we get disabled by the idle code
+ * We rearm the timer until we get disabled by the idle code.
* Called with interrupts disabled and timer->base->cpu_base->lock held.
*/
static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
index 12c5f4c..645ec51 100644
--- a/kernel/time/timer_list.c
+++ b/kernel/time/timer_list.c
@@ -65,9 +65,9 @@ #ifdef CONFIG_TIMER_STATS
SEQ_printf(m, ", %s/%d", tmp, timer->start_pid);
#endif
SEQ_printf(m, "\n");
- SEQ_printf(m, " # expires at %Lu nsecs [in %Lu nsecs]\n",
+ SEQ_printf(m, " # expires at %Lu nsecs [in %Ld nsecs]\n",
(unsigned long long)ktime_to_ns(timer->expires),
- (unsigned long long)(ktime_to_ns(timer->expires) - now));
+ (long long)(ktime_to_ns(timer->expires) - now));
}

static void
@@ -285,3 +285,82 @@ static int __init init_timer_list_procfs
return 0;
}
__initcall(init_timer_list_procfs);
+
+/*
+ * Sleepy linux support
+ */
+
+#include <linux/suspend.h>
+#include <asm/atomic.h>
+
+atomic_t cpu_needed = ATOMIC_INIT(1);
+
+static s64
+detect_active_timers(struct hrtimer_clock_base *base, s64 first_timer)
+{
+ struct hrtimer *timer, tmp;
+ unsigned long next = 0, i;
+ struct rb_node *curr;
+ unsigned long flags;
+
+next_one:
+ i = 0;
+ spin_lock_irqsave(&base->cpu_base->lock, flags);
+
+ curr = base->first;
+ /*
+ * Crude but we have to do this O(N*N) thing, because
+ * we have to unlock the base when printing:
+ */
+ while (curr && i < next) {
+ curr = rb_next(curr);
+ i++;
+ }
+
+ if (curr) {
+ timer = rb_entry(curr, struct hrtimer, node);
+ tmp = *timer;
+ spin_unlock_irqrestore(&base->cpu_base->lock, flags);
+
+// printk("[%Ld]", ktime_to_ns(tmp.expires));
+ first_timer = min_t(s64, first_timer, ktime_to_ns(tmp.expires));
+
+ next++;
+ goto next_one;
+ }
+ spin_unlock_irqrestore(&base->cpu_base->lock, flags);
+ return first_timer;
+}
+
+void detect_idle(void)
+{
+ int i;
+ s64 first_timer = (3600ULL*NSEC_PER_SEC);
+ int cpu;
+ s64 now;
+
+ if (num_online_cpus() != 1)
+ return;
+
+ for_each_online_cpu(cpu) {
+ struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);
+ for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
+// printk("_");
+ first_timer = detect_active_timers(cpu_base->clock_base + i, first_timer);
+ }
+ }
+ now = ktime_to_ns(ktime_get());
+ if (first_timer ==3600ULL*NSEC_PER_SEC) {
+ printk("nohz: No timers at all?!\n");
+ if (!atomic_read(&cpu_needed)) {
+ printk("Auto sleep\n");
+ enter_auto_sleep();
+ }
+ } else if (first_timer > (now + 3ULL*NSEC_PER_SEC)) {
+ printk("nohz: Ready for ~ %Ld msec wait, %d\n", (long long) first_timer - (long long) now, atomic_read(&cpu_needed));
+ if (!atomic_read(&cpu_needed)) {
+ printk("Auto sleep\n");
+ enter_auto_sleep();
+ }
+ }
+}
diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c
index c36bb7e..417da8c 100644
--- a/kernel/time/timer_stats.c
+++ b/kernel/time/timer_stats.c
@@ -26,7 +26,7 @@
* the pid and cmdline from the owner process if applicable.
*
* Start/stop data collection:
- * # echo 1[0] >/proc/timer_stats
+ * # echo [1|0] >/proc/timer_stats
*
* Display the information collected so far:
* # cat /proc/timer_stats
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 52d5e7c..dc7f748 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -220,6 +220,7 @@ int queue_delayed_work_on(int cpu, struc
struct timer_list *timer = &dwork->timer;
struct work_struct *work = &dwork->work;

+ timer_stats_timer_set_start_info(&dwork->timer);
if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) {
BUG_ON(timer_pending(timer));
BUG_ON(!list_empty(&work->entry));
@@ -581,6 +582,7 @@ EXPORT_SYMBOL(schedule_delayed_work);
int schedule_delayed_work_on(int cpu,
struct delayed_work *dwork, unsigned long delay)
{
+ timer_stats_timer_set_start_info(&dwork->timer);
return queue_delayed_work_on(cpu, keventd_wq, dwork, delay);
}
EXPORT_SYMBOL(schedule_delayed_work_on);
diff --git a/mm/slab.c b/mm/slab.c
index 2e338a5..8a5d988 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -945,7 +945,7 @@ static void __cpuinit start_cpu_timer(in
init_reap_node(cpu);
INIT_DELAYED_WORK(reap_work, cache_reap);
schedule_delayed_work_on(cpu, reap_work,
- __round_jiffies_relative(HZ, cpu));
+ __round_jiffies_relative(HZ*10000, cpu)); /* FIXME !*/
}
}

diff --git a/mm/vmstat.c b/mm/vmstat.c
index e8d846f..7fd3dbb 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -794,7 +794,7 @@ #endif /* CONFIG_PROC_FS */

#ifdef CONFIG_SMP
static DEFINE_PER_CPU(struct delayed_work, vmstat_work);
-int sysctl_stat_interval __read_mostly = HZ;
+int sysctl_stat_interval __read_mostly = 10000 * HZ;

static void vmstat_update(struct work_struct *w)
{

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


2007-12-26 17:27:47

by Oliver Neukum

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

Am Mittwoch, 26. Dezember 2007 00:07:31 schrieb Pavel Machek:
> Heute 00:07:31
> ?
> This is RFC. It does not even work for me... it sleeps but it will not
> wake up, because SATA wakeup code is missing. Code attached for illustration.
>
> I wonder if this is the right approach? What is right interface to the
> drivers?

IMHO you are making to many special cases. The system can be "sleepy"
if all devices can be runtime suspended and all CPUs are idle.

Regards
Oliver

2007-12-26 18:57:48

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

Pavel Machek wrote:
> This is RFC. It does not even work for me... it sleeps but it will not
> wake up, because SATA wakeup code is missing. Code attached for illustration.
>
> I wonder if this is the right approach? What is right interface to the
> drivers?
>
> 3) Network card that is either down
> or can wake up system on any packet (and not loose too many packets)
>

This is the big crux I see. You're going to constantly wake up the
machine due to broadcast packets, and spend a lot of power just going in
and out of S3.

-hpa

2007-12-26 19:01:16

by Pavel Machek

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

On Wed 2007-12-26 10:56:59, H. Peter Anvin wrote:
> Pavel Machek wrote:
>> This is RFC. It does not even work for me... it sleeps but it will not
>> wake up, because SATA wakeup code is missing. Code attached for
>> illustration.
>> I wonder if this is the right approach? What is right interface to the
>> drivers?
>> 3) Network card that is either down
>> or can wake up system on any packet (and not loose too many packets)
>
> This is the big crux I see. You're going to constantly wake up the machine
> due to broadcast packets, and spend a lot of power just going in and out of
> S3.

Yep... for the first version, I'll be very happy if it autosleeps when
I'm traveling by bus or something. Working with ethernet plugged in is
quite a distant goal.

(But I guess some cleverness could be done on the router or
something. Automagically converting "interesting" packets into WoL
enabled ones, or...?)
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2007-12-26 19:03:16

by Pavel Machek

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

On Wed 2007-12-26 18:28:04, Oliver Neukum wrote:
> Am Mittwoch, 26. Dezember 2007 00:07:31 schrieb Pavel Machek:
> > Heute 00:07:31
> > ?
> > This is RFC. It does not even work for me... it sleeps but it will not
> > wake up, because SATA wakeup code is missing. Code attached for illustration.
> >
> > I wonder if this is the right approach? What is right interface to the
> > drivers?
>
> IMHO you are making to many special cases. The system can be "sleepy"
> if all devices can be runtime suspended and all CPUs are idle.

Pretty much, except that "timer device" needs to be runtime suspended,
too... We probably should not sleep if wakeup is scheduled 1 second in
future.

Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2007-12-26 19:23:19

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

Pavel Machek wrote:
>
> Yep... for the first version, I'll be very happy if it autosleeps when
> I'm traveling by bus or something. Working with ethernet plugged in is
> quite a distant goal.
>
> (But I guess some cleverness could be done on the router or
> something. Automagically converting "interesting" packets into WoL
> enabled ones, or...?)
> Pavel

You've just eliminated 90%+ of the available Ethernet infrastructure.

However, there may be Ethernet controllers which can do something smart
with incoming packets, and perhaps more importantly, we can always write
a spec and try to push it to Intel, Broadcom, Realtek and Nvidia.

-hpa

2007-12-26 20:08:20

by Oliver Neukum

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

Am Mittwoch, 26. Dezember 2007 19:56:59 schrieb H. Peter Anvin:
> > 3) Network card that is either down
> > ? ?or can wake up system on any packet (and not loose too many packets)
> >
>
> This is the big crux I see. ?You're going to constantly wake up the
> machine due to broadcast packets, and spend a lot of power just going in
> and out of S3.

How many machines care a lot about saving power while they are connected
to an ethernet? Wlan might be more of a problem.

Regards
Oliver

2007-12-26 20:17:45

by Pavel Machek

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

On Wed 2007-12-26 18:28:04, Oliver Neukum wrote:
> Am Mittwoch, 26. Dezember 2007 00:07:31 schrieb Pavel Machek:
> > Heute 00:07:31
> > ?
> > This is RFC. It does not even work for me... it sleeps but it will not
> > wake up, because SATA wakeup code is missing. Code attached for illustration.
> >
> > I wonder if this is the right approach? What is right interface to the
> > drivers?
>
> IMHO you are making to many special cases. The system can be "sleepy"
> if all devices can be runtime suspended and all CPUs are idle.

Is there an easy way to tell if all the devices are runtime suspended?

I guess I need to know from atomic context :-(.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2007-12-26 20:23:20

by Oliver Neukum

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

Am Mittwoch, 26. Dezember 2007 21:17:22 schrieb Pavel Machek:
> On Wed 2007-12-26 18:28:04, Oliver Neukum wrote:
> > Am Mittwoch, 26. Dezember 2007 00:07:31 schrieb Pavel Machek:
> > > Heute 00:07:31
> > > ?
> > > This is RFC. It does not even work for me... it sleeps but it will not
> > > wake up, because SATA wakeup code is missing. Code attached for illustration.
> > >
> > > I wonder if this is the right approach? What is right interface to the
> > > drivers?
> >
> > IMHO you are making to many special cases. The system can be "sleepy"
> > if all devices can be runtime suspended and all CPUs are idle.
>
> Is there an easy way to tell if all the devices are runtime suspended?

Do you really want to know whether they are suspended or whether they
could be suspended?

> I guess I need to know from atomic context :-(.

Urgh. suspend() must be able to sleep and can fail.

Regards
Oliver

2007-12-26 20:25:05

by Igor Stoppa

[permalink] [raw]
Subject: Re: [linux-pm] [RFC] sleepy linux

Hi,
On Wed, 2007-12-26 at 00:07 +0100, ext Pavel Machek wrote:
> This is RFC. It does not even work for me... it sleeps but it will not
> wake up, because SATA wakeup code is missing. Code attached for illustration.
>
> I wonder if this is the right approach? What is right interface to the
> drivers?
>
>
> 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

Why can't these cases be based on CPUIdle?

> 3) You can sleep now, but wake me up in 8:30 with mp3 player

This is about setting up properly the wakeup sources which means:

- the wakeup source is really capable of generating wakeups for the
target idle state

- the wakeup source is not actually capable of genrating wakeups from
the target idle state, which can be solved in 2 ways:

- if the duration of the activity is known, set up an alarm
(assuming alarms are proper wakeup sources) so that the
system is ready just in time, in a less efficient but more
responsive power saving state

- if the duration of the activity is unknown choose the more
efficient amongst the following solutions:

- go to deep sleep state and periodically wakeup and
poll, with a period compatible with the timing
of the event source

- prevent too deep sleep states till the event happens

> 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.

It might be that some hw doesn't provide deep power saving state for
some devices, but if the only missing feature is the wakeup capability,
it could be effectively replaced by some HW timer.


> 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)

These are just few system specific case, but if you start including USB
devices, the situation is going to get quite complicated very soon, if
you explicitly include certain HW devices in your model.


--
Cheers, Igor

Igor Stoppa <[email protected]>
(Nokia Multimedia - CP - OSSO / Helsinki, Finland)

2007-12-26 20:33:23

by Pavel Machek

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

On Wed 2007-12-26 21:23:37, Oliver Neukum wrote:
> Am Mittwoch, 26. Dezember 2007 21:17:22 schrieb Pavel Machek:
> > On Wed 2007-12-26 18:28:04, Oliver Neukum wrote:
> > > Am Mittwoch, 26. Dezember 2007 00:07:31 schrieb Pavel Machek:
> > > > Heute 00:07:31
> > > > ?
> > > > This is RFC. It does not even work for me... it sleeps but it will not
> > > > wake up, because SATA wakeup code is missing. Code attached for illustration.
> > > >
> > > > I wonder if this is the right approach? What is right interface to the
> > > > drivers?
> > >
> > > IMHO you are making to many special cases. The system can be "sleepy"
> > > if all devices can be runtime suspended and all CPUs are idle.
> >
> > Is there an easy way to tell if all the devices are runtime suspended?
>
> Do you really want to know whether they are suspended or whether they
> could be suspended?

If they are suspended.

My plan is: let the drivers autosuspend on their own. If I see all of
them are autosuspended, then it looks like great time to put whole
system into s2ram...

> > I guess I need to know from atomic context :-(.
>
> Urgh. suspend() must be able to sleep and can fail.

That's ok.

... I also don't need to call any suspend() routines, because all the
drivers are already suspended, right?

And yes, I want device activity to prevent s2ram. If user is burning
CD, machine should not sleep. If user is actively typing, machine
should not sleep. My vision is: screen saver tells kernel keyboard
need not be very responsive, at that point keyboard driver can
autosuspend the keyboard, and if that was the last device, whole
system sleeps.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2007-12-26 20:45:10

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

Oliver Neukum wrote:
> Am Mittwoch, 26. Dezember 2007 19:56:59 schrieb H. Peter Anvin:
>>> 3) Network card that is either down
>>> or can wake up system on any packet (and not loose too many packets)
>>>
>> This is the big crux I see. You're going to constantly wake up the
>> machine due to broadcast packets, and spend a lot of power just going in
>> and out of S3.
>
> How many machines care a lot about saving power while they are connected
> to an ethernet? Wlan might be more of a problem.

A lot of them should. An inordinate amount of machines sit there
burning power for no reason. You can argue that S3 isn't needed -- that
nohz + C3/C4 + turning off the screen would be enough, and that might be
legit. Heck, I'm constantly frustrated by every distro upgrade breaking
power management for my monitor.

-hpa

2007-12-26 20:51:30

by Pavel Machek

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

On Wed 2007-12-26 12:43:56, H. Peter Anvin wrote:
> Oliver Neukum wrote:
>> Am Mittwoch, 26. Dezember 2007 19:56:59 schrieb H. Peter Anvin:
>>>> 3) Network card that is either down
>>>> or can wake up system on any packet (and not loose too many packets)
>>>>
>>> This is the big crux I see. You're going to constantly wake up the
>>> machine due to broadcast packets, and spend a lot of power just going in
>>> and out of S3.
>> How many machines care a lot about saving power while they are connected
>> to an ethernet? Wlan might be more of a problem.
>
> A lot of them should. An inordinate amount of machines sit there burning
> power for no reason. You can argue that S3 isn't needed -- that nohz +
> C3/C4 + turning off the screen would be enough, and that might be
> + legit.

NOHZ + C4 + turn off screen + turn off disk + turn off SATA is still
~8W on thinkpad x60.

S3 is ~1W.

That's quite significant difference.

(But yes, connected-to-ethernet is not most important use scenario.)
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2007-12-26 20:55:08

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

Pavel Machek wrote:
> On Wed 2007-12-26 12:43:56, H. Peter Anvin wrote:
>> Oliver Neukum wrote:
>>> Am Mittwoch, 26. Dezember 2007 19:56:59 schrieb H. Peter Anvin:
>>>>> 3) Network card that is either down
>>>>> or can wake up system on any packet (and not loose too many packets)
>>>>>
>>>> This is the big crux I see. You're going to constantly wake up the
>>>> machine due to broadcast packets, and spend a lot of power just going in
>>>> and out of S3.
>>> How many machines care a lot about saving power while they are connected
>>> to an ethernet? Wlan might be more of a problem.
>> A lot of them should. An inordinate amount of machines sit there burning
>> power for no reason. You can argue that S3 isn't needed -- that nohz +
>> C3/C4 + turning off the screen would be enough, and that might be
>> + legit.
>
> NOHZ + C4 + turn off screen + turn off disk + turn off SATA is still
> ~8W on thinkpad x60.
>
> S3 is ~1W.
>
> That's quite significant difference.
>
> (But yes, connected-to-ethernet is not most important use scenario.)
> Pavel

Still... if we could get the desktops of the world down anywhere close
to that range when not used, it would be a huge win.

-hpa

2007-12-26 23:15:26

by Oliver Neukum

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

Am Mittwoch, 26. Dezember 2007 21:32:58 schrieb Pavel Machek:
> On Wed 2007-12-26 21:23:37, Oliver Neukum wrote:
> > Am Mittwoch, 26. Dezember 2007 21:17:22 schrieb Pavel Machek:

> > > Is there an easy way to tell if all the devices are runtime suspended?
> >
> > Do you really want to know whether they are suspended or whether they
> > could be suspended?
>
> If they are suspended.
>
> My plan is: let the drivers autosuspend on their own. If I see all of
> them are autosuspended, then it looks like great time to put whole
> system into s2ram...

Your calculation of cost/benefit will be wrong. A driver will have timeouts
based on the cost of a suspend/resume cycle of that device only.
You'd have to calculate of keeping the whole system awake against that.

Regards
Oliver

2007-12-27 10:00:28

by Oliver Neukum

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

Am Mittwoch, 26. Dezember 2007 21:32:58 schrieb Pavel Machek:

> ... I also don't need to call any suspend() routines, because all the
> drivers are already suspended, right?

Well, you have a number of devices which cannot do runtime pm.
They can do suspend/resume with the whole system. For them these
operations mean saving/restoring state.
So for these devices implementing autosuspend makes no sense.
They would sensibly do only idle/busy detection.

> And yes, I want device activity to prevent s2ram. If user is burning
> CD, machine should not sleep. If user is actively typing, machine

In these cases the devices involved should report themselves busy,
shouldn't they?

> should not sleep. My vision is: screen saver tells kernel keyboard
> need not be very responsive, at that point keyboard driver can
> autosuspend the keyboard, and if that was the last device, whole
> system sleeps.

We lack a notion of telling devices that they are opened only for
detecting wakeups. Currently a driver has to assume that an opened
device has to be fully functional.

Regards
Oliver

2007-12-29 22:46:30

by Pavel Machek

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

Hi!

> >NOHZ + C4 + turn off screen + turn off disk + turn off SATA is still
> >~8W on thinkpad x60.
> >
> >S3 is ~1W.
> >
> >That's quite significant difference.
> >
> >(But yes, connected-to-ethernet is not most important use scenario.)
> > Pavel
>
> Still... if we could get the desktops of the world down anywhere close
> to that range when not used, it would be a huge win.

Plus, it is probably mandatory if you want EnergyStar logo ...
Pavel

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2007-12-29 22:50:21

by Pavel Machek

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

Hi!

> > > > Is there an easy way to tell if all the devices are runtime suspended?
> > >
> > > Do you really want to know whether they are suspended or whether they
> > > could be suspended?
> >
> > If they are suspended.
> >
> > My plan is: let the drivers autosuspend on their own. If I see all of
> > them are autosuspended, then it looks like great time to put whole
> > system into s2ram...
>
> Your calculation of cost/benefit will be wrong. A driver will have timeouts
> based on the cost of a suspend/resume cycle of that device only.
> You'd have to calculate of keeping the whole system awake against that.

Hmm, right. Driver probably should have chance to autosuspend but tell
the core that whole system probably should not sleep... Hmm....

Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2007-12-29 22:53:28

by Pavel Machek

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

Hi!

> > ... I also don't need to call any suspend() routines, because all the
> > drivers are already suspended, right?
>
> Well, you have a number of devices which cannot do runtime pm.
> They can do suspend/resume with the whole system. For them these
> operations mean saving/restoring state.
> So for these devices implementing autosuspend makes no sense.
> They would sensibly do only idle/busy detection.

Yep... Let's call busy/idle detection and save/restore state
"autosuspend" for those devices. It does not save any power, but it
can be viewed as "kind-of-suspend". (No, I do not have this kind of
details ready).

> > And yes, I want device activity to prevent s2ram. If user is burning
> > CD, machine should not sleep. If user is actively typing, machine
>
> In these cases the devices involved should report themselves busy,
> shouldn't they?

Yes.

> > should not sleep. My vision is: screen saver tells kernel keyboard
> > need not be very responsive, at that point keyboard driver can
> > autosuspend the keyboard, and if that was the last device, whole
> > system sleeps.
>
> We lack a notion of telling devices that they are opened only for
> detecting wakeups. Currently a driver has to assume that an opened
> device has to be fully functional.

Yes, we'll need to add some userland interfaces. No, this will not be
easy.

Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2007-12-30 11:18:54

by Ingo Molnar

[permalink] [raw]
Subject: Re: [RFC] sleepy linux


* Pavel Machek <[email protected]> wrote:

> 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

very nice approach! It might require smarter hardware to be really
efficient, but the generic ability for Linux to utilize S3 automatically
would _quickly_ drive the creation of smarter hardware i'm sure - so i'd
propose to include this even if it wastes power in some cases.

a quick feature request: could you please make the wake-on-RTC
capability generic and add a CONFIG_DEBUG_SUSPEND_ON_RAM=y config option
(disabled by default) that does a short 1-second suspend-to-RAM sequence
upon bootup? That way we could test s2ram automatically (which is a MUCH
needed feature for automated regression testing and automatic
bisection). In addition, some sort of 'suspend for N seconds' /sys or
/dev/rtc capability would be nice as well.

btw., how far are you from having a working prototype?

Ingo

2007-12-30 16:50:33

by Oliver Neukum

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

Am Sonntag, 30. Dezember 2007 00:51:34 schrieb Pavel Machek:
> Hi!
>
> > > ... I also don't need to call any suspend() routines, because all the
> > > drivers are already suspended, right?
> >
> > Well, you have a number of devices which cannot do runtime pm.
> > They can do suspend/resume with the whole system. For them these
> > operations mean saving/restoring state.
> > So for these devices implementing autosuspend makes no sense.
> > They would sensibly do only idle/busy detection.
>
> Yep... Let's call busy/idle detection and save/restore state
> "autosuspend" for those devices. It does not save any power, but it
> can be viewed as "kind-of-suspend". (No, I do not have this kind of
> details ready).

Well, you probably would have to walk through all devices and check
all devices are either suspended or can be suspended. That would mean
struct device has to be extended to show common attributes.

But what's wrong with calling suspend() the conventional way once you've
decided to go into sleepy mode?

[..]
> > We lack a notion of telling devices that they are opened only for
> > detecting wakeups. Currently a driver has to assume that an opened
> > device has to be fully functional.
>
> Yes, we'll need to add some userland interfaces. No, this will not be
> easy.

This mainly means input devices.

Regards
Oliver

2007-12-31 13:47:17

by Pavel Machek

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

On Sun 2007-12-30 17:39:42, Oliver Neukum wrote:
> Am Sonntag, 30. Dezember 2007 00:51:34 schrieb Pavel Machek:
> > Hi!
> >
> > > > ... I also don't need to call any suspend() routines, because all the
> > > > drivers are already suspended, right?
> > >
> > > Well, you have a number of devices which cannot do runtime pm.
> > > They can do suspend/resume with the whole system. For them these
> > > operations mean saving/restoring state.
> > > So for these devices implementing autosuspend makes no sense.
> > > They would sensibly do only idle/busy detection.
> >
> > Yep... Let's call busy/idle detection and save/restore state
> > "autosuspend" for those devices. It does not save any power, but it
> > can be viewed as "kind-of-suspend". (No, I do not have this kind of
> > details ready).
>
> Well, you probably would have to walk through all devices and check
> all devices are either suspended or can be suspended. That would mean
> struct device has to be extended to show common attributes.
>
> But what's wrong with calling suspend() the conventional way once you've
> decided to go into sleepy mode?

I'm not sure if it can be done in non-racy way. It is different from
"conventional" suspend(): you can still have userland requests after
this suspend(), and you should abort auto-sleep if you get one. (As
opposed to blocking in system suspend case).
Pavel

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2008-01-02 10:53:19

by Oliver Neukum

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

Am Montag, 31. Dezember 2007 15:44:47 schrieb Pavel Machek:
> On Sun 2007-12-30 17:39:42, Oliver Neukum wrote:

> > But what's wrong with calling suspend() the conventional way once you've
> > decided to go into sleepy mode?
>
> I'm not sure if it can be done in non-racy way. It is different from
> "conventional" suspend(): you can still have userland requests after
> this suspend(), and you should abort auto-sleep if you get one. (As
> opposed to blocking in system suspend case).

But we are always racing against hardware in these cases.

Strictly speaking you cannot have pure userland request. If no task
is runnable and no timer about to fire any activity will require kernel
activity unless you are doing direct hardware access from user space
which in the generic case precludes suspension anyway.

Regards
Oliver

2008-01-05 21:51:22

by Pavel Machek

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

On Sun 2007-12-30 12:15:52, Ingo Molnar wrote:
>
> * Pavel Machek <[email protected]> wrote:
>
> > 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
>
> very nice approach! It might require smarter hardware to be really
> efficient, but the generic ability for Linux to utilize S3 automatically
> would _quickly_ drive the creation of smarter hardware i'm sure - so i'd
> propose to include this even if it wastes power in some cases.
>
> a quick feature request: could you please make the wake-on-RTC
> capability generic and add a CONFIG_DEBUG_SUSPEND_ON_RAM=y config option
> (disabled by default) that does a short 1-second suspend-to-RAM sequence
> upon bootup? That way we could test s2ram automatically (which is a MUCH
> needed feature for automated regression testing and automatic
> bisection). In addition, some sort of 'suspend for N seconds' /sys or
> /dev/rtc capability would be nice as well.

Hmm, are you sure it is good idea to do this from kernel? I guess this
is better done from script...

> btw., how far are you from having a working prototype?

SCSI/SATA issues stop me just now, but even if I get that to work, it
will be extremely disgusting hack... and it is unclear how to do it
nicely :-(.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2008-01-08 16:38:22

by Ingo Molnar

[permalink] [raw]
Subject: Re: [RFC] sleepy linux


* Pavel Machek <[email protected]> wrote:

> > a quick feature request: could you please make the wake-on-RTC
> > capability generic and add a CONFIG_DEBUG_SUSPEND_ON_RAM=y config
> > option (disabled by default) that does a short 1-second
> > suspend-to-RAM sequence upon bootup? That way we could test s2ram
> > automatically (which is a MUCH needed feature for automated
> > regression testing and automatic bisection). In addition, some sort
> > of 'suspend for N seconds' /sys or /dev/rtc capability would be nice
> > as well.
>
> Hmm, are you sure it is good idea to do this from kernel? I guess this
> is better done from script...

i have this low-prio effort to make all self-checks automatically
available via 'make randconfig' as well, for all features that have no
natural exposure during normal bootup. So far we've got rcutorture,
kprobes-check, locking/lockdep-self-test and a handful of others.
External scripts tend to go out of sync and LTP takes way too much time
to finish.

> > btw., how far are you from having a working prototype?
>
> SCSI/SATA issues stop me just now, but even if I get that to work, it
> will be extremely disgusting hack... and it is unclear how to do it
> nicely :-(.

as long as the sleep periods are within say 10-20 seconds, and our s2ram
cycle is fast and optimal enough, we could do this with networking
enabled too, without dropping/stalling TCP connections left and right.

(Perhaps if we could notify routers that they should batch packets for N
seconds and we could turn off PHY during that time, it would be even
nicer - is there any such router extension in existence?)

but if it's nothing else but a s2ram debug/stress utility, that alone
would be great too :-)

Ingo

2008-01-08 19:15:29

by Pavel Machek

[permalink] [raw]
Subject: Re: [RFC] sleepy linux

Hi!
>
> > > a quick feature request: could you please make the wake-on-RTC
> > > capability generic and add a CONFIG_DEBUG_SUSPEND_ON_RAM=y config
> > > option (disabled by default) that does a short 1-second
> > > suspend-to-RAM sequence upon bootup? That way we could test s2ram
> > > automatically (which is a MUCH needed feature for automated
> > > regression testing and automatic bisection). In addition, some sort
> > > of 'suspend for N seconds' /sys or /dev/rtc capability would be nice
> > > as well.
> >
> > Hmm, are you sure it is good idea to do this from kernel? I guess this
> > is better done from script...
>
> i have this low-prio effort to make all self-checks automatically
> available via 'make randconfig' as well, for all features that have no
> natural exposure during normal bootup. So far we've got rcutorture,
> kprobes-check, locking/lockdep-self-test and a handful of others.
> External scripts tend to go out of sync and LTP takes way too much time
> to finish.

Well, I can give you a three liner, and if it stops working, I'll
treat is as a regression, because userland ABI changed...?

Or you can get about 10 lines of C, no problem, but I do not think
that should be merged to Linus.

> > > btw., how far are you from having a working prototype?
> >
> > SCSI/SATA issues stop me just now, but even if I get that to work, it
> > will be extremely disgusting hack... and it is unclear how to do it
> > nicely :-(.
>
> as long as the sleep periods are within say 10-20 seconds, and our s2ram
> cycle is fast and optimal enough, we could do this with networking
> enabled too, without dropping/stalling TCP connections left and
> right.

I do not think TCP would survive "10 seconds sleep, 1 second up". But...

> (Perhaps if we could notify routers that they should batch packets for N
> seconds and we could turn off PHY during that time, it would be even
> nicer - is there any such router extension in existence?)

...yes, we should probably play with the routers.

> but if it's nothing else but a s2ram debug/stress utility, that alone
> would be great too :-)

I expect to stress s2ram way too much ;-).
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html