[Galaxy S I9000 Android Development] newmail:
I found the problem with the ondemand governor while in earlysuspend suspend mode. The problem is that the cpu starts to go in deep sleep, so a sampling_rate of 10000 is applied only once in a while, the real sampling_rate becomes 1second or more.

So when that happens the CPU goes in deel sleep all the time and ondemand tends to stay stuck at the max frequency all the time, by mistake, despite the load is near 0%.

After deep sleep when a wakeup happens we return to the 10000usec sampling rate. ondemand sees activity after the deep sleep wakeup but those wakeups "loads" must be adjusted down if the previous wall_time delta was huge and the current one is tiny. We're too close to deep sleep to ramp up cpu freq.

So my solution is to tweak the ondemand to scale down the "load" according to the decrease in the wall_time delta ratio (deep_sleep_ratio variable).

When screen is on, or during a call or during playback with screen off, the deep_sleep_ratio is 1, so the ondemand behaves as aggressive as always. But the deep_sleep_ratio ramp up when the phone is idle and the idle deep sleep states starts. With this tweak I can use the ondemand governor with the default values and the sampling rate set to 10000 (for max responsiveness) and the cpu freq will stay down to 100mhz with no jitter when the screen is off and the load is near 0% (instead of staying close to 1ghz most of the time with the 10000 sampling rate setting, 40000 of the JVS tends to hide it but it still jitters a lot and it hurts interactivity to be unable to set it below 40000).

In my first post I already noticed this jittering of the ondemand governor with the screen off. And I thought to solve it by lowering the freq to min with the screen off (which screwed csipsimple). I also noticed that a sampling_rate of the order of 100000 would decrease the jittering and with 10000 the cpu freq would be set at the maximum all the time. But the real problem was the ondemand comparing apples to oranges with the deep sleep state, and this explains why the jittering wasn't as bad with the screen on, as opposed to the badness with the screen off and the CPU going in deep sleep at high freq most of the time.

So this heuristic I wrote solves the problem, and I also disabled all those dvfs magics in cpufreq that prevented to use the 100hz frequency most of the time. It works fine for me with screen on, and now with screen off (proximity sensors) voip works perfectly too (I also verified deep_sleep_ratio is 1 during calls with proximity sensor activated). Any real activity will prevent the deep sleeps so it's perfectly ok to ignore the high loads measured just after returning from the deep sleep.

Anyway feel free to experiment. I also wrote another patch to switch the governor to performance automatically when screen goes on, and return to ondemand (with deep sleep detection) when screen goes off. But I think this heuristic is better and ondemand won't be exactly as fast as "performance" but especially at 10000 sampling_rate the difference should not be noticeable. And so I prefer to save a tiny bit of power by using ondemand all the time. Plus it proofs the new logic is good if it works for both scenarios.

I still decrease the max cpu frequency when screen is off to 800mhz (not anymore to 100mhz after I found it screws the voip and playback with screen off). ondemand will immediately jump to max the moment the threshold is exceeded (default threshold is 95% of not idle time). So this helps because all csimpsimple/skype/musicplayer background non-interactive workloads that may run with the screen is off and this will avoid to ever reach 1ghz which isn't needed for any of those background apps. 1ghz returns when screen goes on again.

In addition to this patch you can also consider adding these two lines to init.rc, but they're just to tune it a bit more aggressively. In the end I couldn't measure any difference from either one (default is 0 for io_is_busy, and 95 for up_threshold) so I'm using the default values and I didn't add the below to my currently running kernel. Probably you can ignore this and only apply the patch to the kernel.

write /sys/devices/system/cpu/cpufreq/ondemand/io_is_busy 1

write /sys/devices/system/cpu/cpufreq/ondemand/up_threshold 80

I recall having read of some tweakded ondemand governor in some rom, but there was no link to source... again I recommend folks to post link to source whenever a new cooked rom is published.

Considering this is closer to a bugfix, if this is confirmed to work by others I can try push the deep_sleep_ratio as a core feature in the kernel, maybe under some better name, to enable in sysfs so in future releases changing init.rc would be enough. It may be useful to other than arm as this is a common problem of what happens after the cpuidle governor enter deep sleep and sleeps more than the sampling_rate.

You can use this to monitor the effect before/after.

adb shell 'cd /sys/devices/system/cpu/cpu0/cpufreq; while :; do cat stats/*; sleep 1; done'

With the patch applied (which also sets sampling_rate at 10000, your default currently is 40000) you will get this when screen is off.

3384

1000000 11256

800000 21625

400000 1642

200000 6266

100000 469564

3384

1000000 11256

800000 21625

400000 1642

200000 6266

100000 469669

3384

1000000 11256

800000 21625

400000 1642

200000 6266

100000 469774

3384

1000000 11256

800000 21625

400000 1642

200000 6266

100000 469888

3384

And this with screen on (without touching :-)

3461

1000000 11316

800000 22619

400000 2067

200000 6290

100000 477547

3461

1000000 11316

800000 22619

400000 2067

200000 6290

100000 477652

3461

1000000 11316

800000 22619

400000 2067

200000 6290

100000 477758

3461

1000000 11316

800000 22619

400000 2067

200000 6290

100000 477864

3461

1000000 11324

800000 22619

400000 2067

200000 6297

100000 477956

3464

There is some seldom jitter still but nothing significant anymore (and with sampling_rate set to 10000, it wasn't just a jittering problem but it was at max freq all the time). Some minor jittering like above is just unavoidable if some userland run a bit longer, and at 100mhz it doesn't take much CPU load to run longer.

I also measured the raw performance by calculating PI and it's within the measurement range error if compared to performance governor. quadrant just fine too unchanged over 1600 at the 3rd run, so I'm optimistic it's not degrading perf.