[TRACKING] Linux battery life tuning

@Jonathan_Walters and @D.H PPD is a daemon that works with both KDE and Gnome – here’s the repo.

I have a fairly in-depth understanding of it – in case you missed this, there’s some relevant/foundational info on how/what power profiles are (which set EPP values through the Intel P-State driver. EPP = Energy Performance Preference).

Long story short I forked PPD and adjusted the code – PPD IIRC simply just changes the EPP values which can be set yourself via /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference.
You can see my changes here which should result in some further understanding of what PPD does per the .patch file diffs:

I’d recommend just removing PPD altogether if you’re using TLP since it seems that PPD just changes EPP values, which TLP does via:

CPU_ENERGY_PERF_POLICY_ON_AC=
CPU_ENERGY_PERF_POLICY_ON_BAT=

Also since TLP FAQs state it conflicts with PPD.

The only downside I can see is:

  • having only two power profiles with TLP (AC and BAT/battery, though those exact EPP values are user customization) instead of PPD’s 3 (which are fixed and imo aren’t ideal values for power savings anyways)
  • and the lack of Gnome/KDE shell integration.

So that should broadly answer your question, though I’m not sure if there’s any synergy with some Framework firmware setting. I don’t believe there are – if there were, I think it’d either be the Intel P-State driver itself and/or thermald. I could be totally wrong here, haha.

edit: just read @lhl’s comments and saw it covered some stuff I typed

1 Like

Although we don’t have a Linux updater yet, we have Beta firmware for the DisplayPort Expansion Card that should improve both s0 and s0ix battery life in Linux: [Beta] DisplayPort Expansion Card firmware update to reduce system power consumption

You can run the updater using another PC if you have access to one with Windows.

7 Likes

It is possible to optimize the power usage of the HDMI module (at least in Ubuntu 22.04) without hawing to remove it using TLP:
The device ID of the expansion card ID should be 32ac:0002 but it can be verified with:
lsusb | grep HDMI
In /etc/tlp.conf, add the following setting:
USB_ALLOWLIST="32ac:0002"
Then restart tlp with sudo tlp start or reboot the laptop.
In my case, in powertop, the estimated power usage of the HDMI expansion card goes down from 360 mW to 0 mW. Plugging an external display in the HDMI port still works immediately.
Side note: the keyboard backlight uses up to 1W when set to the maximum!

5 Likes

Nice, thanks!

Though we need to see if it actually makes a difference. When I checked in powertop, it reported that the HDMI expansion card uses 10 W (!). But I don’t believe this number, it’s higher than the battery discharge rate…

Yes, the power consumption of the devices is nowhere near exact. But the drastic reduction in those values plus the fact that the battery discharge rate dropped a bit on my computer when I changed this setting (don’t remember by how much though) gives me hope that it should definitively improve the HDMI expansion power usage.

2 Likes

By the way, this may also help with other expansion cards (drives, SD card reader, DP and ethernet) but I only have the HDMI one at hand. The IDs of the devices can be found with lsusb when they are plugged in.

2 Likes

That’s about in line with reported power savings from USB autosuspend:


TLP by default enables autosuspend mode for USB devices (USB_AUTOSUSPEND=1). Keeping USB_AUTOSUSPEND=1 already enables autosuspend on my HDMI Expansion card, so I use that, and issue devices (like wired mice going to sleep) can be added to USB_DENYLIST= .
I’m curious, is there a reason you’re using USB_ALLOWLIST instead? (just the reverse of what I’m doing, or is there extra voodoo power savings from adding specifically to USB_ALLOWLIST?)
https://linrunner.de/tlp/settings/usb.html


Also, toggling/checking autosuspend values for a device can be easily done in powertop in the Tunables section (changing it here doesn’t persist it after reboot):

Pressing enter on Autosuspend for USB device HDMI Expansion Card [Framework] shows the value that’s changed, e.g.

echo 'auto' > '/sys/bus/usb/devices/3-4/power/control'

Note the value is either auto or on. The number e.g. 3-4 is subject to change.

  • on means that the device should be resumed and autosuspend is not allowed. (Of course, system suspends are still allowed.)
  • auto is the normal state in which the kernel is allowed to autosuspend and autoresume the device.

https://docs.kernel.org/driver-api/usb/power-management.html?highlight=autosuspend#the-user-interface-for-dynamic-pm


Yeah, as already stated, the line items that powertop shows are just estimates and really can’t be trusted. An accurate way to measure (IMO):

Bring the system to idle/~0% CPU and ensure the total power usage remains consistent over e.g. a minute+. Note the baseline total power usage, then do whatever change (e.g. plug in HDMI card), and then measure the total power usage afterwards. Finally, calculate the delta between the two totals. This allows a high confidence rate of pinpointing the change in power usage totals to the user change that occurred (e.g. plugging in HDMI card).

2 Likes

Indeed, it suffices to enable media.ffmpeg.vaapi.enabled. Maybe the opening post should simply link to Firefox - ArchWiki , which I consider almost a canonical source for the correct settings.

2 Likes

In fact, at least on Fedora, firefox is packaged with vaapi enabled by default:

https://fedoraproject.org/wiki/Firefox_Hardware_acceleration#Video_decoding

The packages needed for actually having it active are not installed by default, however, so you still have to undertake some action to actually get it to work (described on the page above).

2 Likes

I installed laptop-mode, acpi on gentoo, setup elogind to use hibernate/suspend, enabled powersave governor in the kernel and max battery (default is max performance) option in bios, the battery estimate shows about 7 hours.

Good enough?

1 Like

I’m not sure how to tune the system. I’m on Arch Linux with kernel version 5.19.10, and have tried s3 without nvme.noacpi=1, s3 with nvme.noacpi=1, and s2 with nvme.noacpi=1. However the best result I can achieve is about 2.x% per hour. And with s2idle + nvme.noacpi=1 I didn’t managed to get better results and sometimes leave the laptop not suspending correctly leading to an about 16% drop in one hour and a half, and the computer feels pretty warm. I’m not sure if there’s anything better I can do.
Other settings enabled:
In TLP:

CPU_SCALING_GOVERNOR_ON_AC="performance"
CPU_SCALING_GOVERNOR_ON_BAT="powersave"
CPU_ENERGY_PERF_POLICY_ON_AC="performance"
CPU_ENERGY_PERF_POLICY_ON_BAT="balance_power"
#CPU_MIN_PERF_ON_AC=0
CPU_MAX_PERF_ON_AC="100"
#CPU_MIN_PERF_ON_BAT=0
#CPU_MAX_PERF_ON_BAT="30"
CPU_BOOST_ON_AC="1"
CPU_BOOST_ON_BAT="0"
CPU_HWP_DYN_BOOST_ON_AC="1"
CPU_HWP_DYN_BOOST_ON_BAT="0"
PCIE_ASPM_ON_AC="performance"
PCIE_ASPM_ON_BAT="powersupersave"
PLATFORM_PROFILE_ON_AC="performance"
PLATFORM_PROFILE_ON_BAT="low-power"
USB_AUTOSUSPEND="1"

Thermald enabled
And the expansion cards on the computer include two USB-A and two USB-C.
The nvme drive is SK Hynix P41.
The battery’s current capacity is 87%.

1 Like

@nrp Could you please update, if the issue is resolved or what all subissues are pending? Its 1 year since the post was posted, would be nice to have a summary on the updates.

2 Likes

For those following along at home, can you quote what issue or subissues you’re referencing? This is a general linux battery tuning thread so I think this is primarily a collection of best practices/discussion of workarounds, I don’t think there’s any single resolution expected for this thread.

I think the biggest known remaining battery issues are non-Linux specific:

  • higher-than-average battery drain in suspend, exacerbated by attached USB device expansion cards (Windows generally gets around this by hibernating automatically at 5% battery usage and in Linux you can do something similar with suspend-and-hibernate; I wrote a simple tool to track battery drain in suspend btw).
  • potential RTC boot issues if left off and unplugged for an extended period of time (weeks)

Each of these problems has their own threads and hopefully updates go there (or in this thread that was gathering known issues).

4 Likes

Sorry for the late reply, you might need to select “BAT1” in the config though I don’t recall needing to set it.

2 Likes

I’m seeing something strange: deep is using more power than s2idle. Anyone else see this?

I have a 12th Gen with Debian Bookworm A1 (kernel 5.19.11-1). Letting the system suspend for about 10hrs in s2idle results in about 7% battery loss. If I use deep, an overnight suspend uses 15%. I have not tuned or set any other parameters.

Note that I used echo deep... for testing. I’ll try with a boot variable and initram update. Maybe the setting isn’t completely taking with only the echo change? Also note I used systemctl suspend instead of letting the power manager timer initiate the suspend. Not sure that matters but it is different than my previous tests.

1 Like

In my tests, deep is what made the most radical change (apart from removing costly expansion cards) in standby usage, so no, I haven’t seen that yet. :slight_smile:

1 Like

I didn’t see a significant change after adding that boot option. Debian GNU/Linux testing/bookworm, Linux 5.19.11, WD Blue SN570 1TB SSD version 234100WD. LVFS says it has no pending firmware upgrade.

Detailed notes in this section of my review. I’m seeing fluctuating power usage: I somehow managed to go down to 14mA, but now I’m back at ~75mA, not sure what’s causing it.

1 Like

Wow, what a great writeup! Inspired by your post, I did some more detailed testing.

I’m still seeing backwards behavior in that deep uses about 3x more than s2idle. Specifically I see about 25mA for s2idle and 75mA for deep. This is consistent across multiple tests for various durations of 2-10 hours. I’ve tried various changes like nvme.noacpi, initiating manually/automatically, disabling AX210 radio, nothing seems to make a signifcant difference.

I’m using a 12th Gen, BIOS 3.05, Debian Bookworm A1, Xfce, SN770 1TB.

No one else is seeing this backwards behavior? Maybe I have a bad build or BIOS?

2 Likes

What app is this?

Now that you mention it, I have just tried, and I actually can’t suspend to s2idle anymore, at least not if I printf deep > /sys/power/mem_sleep; the machine just doesn’t suspend at all!

Definitely something fishy going on here… sigh.

update: turns out doing the runtime change doesn’t work. rebooting with mem_sleep_default changed does work though.

i’m doing more thorough tests to analyze what is taking up power during standby now, stay tuned.

1 Like