site logo

Strategically Optimizing Battery Life on Linux

Recently I got a new laptop. It is an ASUS Zenbook flip model with i7-1165G7 (4 core…). I thought about getting an AMD model, but if there is anything good about Intel these days, it is their Linux support for mobile CPU. Right after I got this laptop, I did the thing any person would do: Putting Arch Linux on it.

The bundled Windows 10 is anything but user-friendly. Upon first boot, the laptop immediately exploded. Apparently this had something to do with “Windows Update”?

Basically, I installed Linux on it. Now I can finally get my 10 hour battery life, I thought. It apparently only lasted 5 hours max. There’s no way that’s right! And so begins my journey of Linux laptop battery optimization.

Saving power for Intel CPU

Enable power saving for Intel HWP

Intel Hardware P-State, or HWP, supports managing a CPU’s power states from dedicated chips. We can order the CPU to run on lower frequencies directly from HWP.

To enable that, create /etc/tmpfiles.d/energy_performance_preference.conf, and enter the following:

w /sys/devices/system/cpu/cpufreq/policy?/energy_performance_preference - - - - power

Set CPU governor to powersave: 7.5W

powersave? That is a name I haven’t heard for years. Back in the days, powersave is the CPU governor that severely limits CPU frequencies to achieve “lower” power consumption. I know we need more battery life, but not that extreme, right?

In newer kernels, Intel CPU’s governor is managed by the special intel_pstate driver. As a result, powersave actually works fantastically for them! It consumes somewhat less power, while still making the system usable.

To save power by enabling powersave CPU governor, type

cpupower frequency-set -g powersave

Or if you want a healthy balance between power and performance, you can set it to balance_power.

After that, my laptop is consuming at around 7.5W at idle. This means roughly 7 hours of idling battery life. That’s a start, albeit not a good one.

Saving power for peripheral PCIe devices: 6W

7.5W is still a big chunk of my power budget. Where did that come from? Probably all the peripheral PCIe devices. They are never properly turned off or anything. Could this be the difference between the “amazing” Windows battery life and puny Linux ones?

Fortunately, the power saver for PCIe, Active State Power Management, is supported by Linux. So we can simply enable it, and set it to power saving mode:

echo powersupersave > /sys/module/pcie_aspm/parameters/policy

That instantly saved ~2W(!!) for me. With ~6W power usage, that means 9 hours of idling! Nice one.

Less Intel GPU power: 5.5W

Similarly, there exists some power saving features for Intel GPU.

For example, since my laptop uses Intel Xe GPU, it supports Panel Self Refresh 2/Selective Refresh. PSR2 is quite useful for 4K displays, since updating a fraction of the display instead of the whole saves more power. It is not enabled by default though. My i915 GPU also supports Frame Buffer Compression, another power saving technique.

Moreover, modern Intel GPUs require binary firmware at startup for advanced power management.

I tried with different conbinations of i915 module options, and this is what seems to be the most effective:

echo "options i915 enable_guc=2 enable_dc=4 enable_fbc=1 enable_psr=1 enable_psr2_sel_fetch=1 disable_power_well=1" > /etc/modprobe.d/i915.conf

Wait, didn’t the title say “4W”?

I am glad you asked. 9 hours of idle battery life is like nothing compared to Apple M1. Even on Windows, this laptop would (supposedly) get ~9 hours of life during web browsing. What is going on?

To be honest, I had no idea. Intel CPU and GPU drivers are usually well optimized. 6W does not seem like a lot, since literally anything could take some power and ruin your battery life. Maybe that is what Linux users deserve?

But I refuse. Upon checking powertop, I realized that CPU’s package C-state never went below pc02, even once. The point of having C-states is to decrease idle power usage. It should go to pc08 while idling. Common cause for this issue is, sadly, a broken PCIe ASPM implementation. Ugh.

I almost gave up at that point. Force enabling pc08 from kernel parameters did not work. And hence the mysterious 6 Watts. I was confident that it is caused by incorrect C-states.

But what caused it?

The road to 4W: Disabling Rapid Storage

After Linux installation, my laptop could not boot up due to an issue with NVMe drivers. Apparently Intel Rapid Storage is enabled for this laptop, and I could not disable it in the BIOS. As a temporary solution, I installed vmd driver for this, then simply forgot about it completely.

What if an incorrect implementation in vmd is preventing NVMe drive from hibernation, and thus making CPU’s C-state stuck at pc2?

I force flashed the laptop’s BIOS, and viola! There is now an option to disable Rapid Storage.

Time for the truth. After switching Rapid Storage off in the BIOS, powertop reported ~4.5W of power consumption. And C-state is correctly lowered to pc8 when idling.

Power saving for wireless card

The wireless card, an Intel AX205, supports power saving mode. It can be enabled via another kernel parameter:

echo "options iwlwifi power_save=1" >> /etc/modprobe.d/iwlwifi.conf
echo "options iwlmvm power_scheme=3" >> /etc/modprobe.d/iwlwifi.conf

After some optimizations for its wireless card, it finally reached below 4W: 3.97W.

And it is beautiful. 15 hours of idle battery life. Even better, when the laptop is in “tablet mode”, powertop reported above 16 hours of battery life!

Does aggressive optimizations matter?

Someone might say: “Wow, 16 hours for your laptop to do absolutely nothing. I want my laptop to have maximum productivity for 5 hours.”

They do have a point. If everything on Linux is power-hungry, this 3.5 watts of power saving means nothing. So I tested it.

Prior to all these optimizations, I could use the laptop for 4 hours max during some light browsing with music. And now, 7 hours of battery life, even with an extra IDE opened. Yes, these small optimizations do matter!

(Extra) To the Extreme: Turning off Display

“But why? Why would you turn off the laptop’s screen?” To go for the last mile.

Turning off the display means iGPU can be shut down completely. In turn, the CPU can reach an even lower C-State: pc10. It would be fun to test the idle power consumption of the motherboard.

There is also another reason: People always talk about how power efficient Raspberry Pis are. I mean, they have slow CPUs, and have considerably simpler circuit designs. In contrast, Intel systems have this huge PCB, considerably more capacitors, a fabulous 14nm fab, and 5 GHz of raw power to cook your loved ones evenly.

Would this consume more power than a small Raspberry Pi 4? Logically, yes.

Actually, I don’t know. According to this article, an idling Pi 4 consumes 4W. My Intel laptop with display on consumes 4W at idle! What if the display is turned off?

Turns out my laptop consumes ~0.5W at idle with display off and WiFi on. With WiFi off the power consumption approaches 0.3W. That’s with a whole NVMe SSD and other peripherals.

Intel really is onto something if they can put Alder Lake into the stage successfully.