DragonflyBSD on a Macbook Air 2017 (Part 3)

Power management is better than it used to be when it comes to Linux and BSDs - but there are still steps you can take to improve battery life. Here are some tweaks I've made to increase battery life on DragonflyBSD.

asmc(4)

One glaring omission you may notice coming from FreeBSD or Linux is keyboard backlight support, fan speed control, and access to the various macbook-specific temperature sensors. On FreeBSD, support for these things is implemented by asmc(4). This module has not been ported to DragonflyBSD. I'm considering putting up a bounty to encourage movement on this, but as I don't really use these things, I also may not.

What we do have

Although we may not have asmc(4), we do have a lot of other things we can prod, owing to how much of the macbook is produced by Intel:

intel_backlight(1) provides command-line control of the display backlight. The lower the backlight, the less power used.

powerd(8) provides automatic CPU scaling based on CPU temperature (more on that below) and presence of an external power supply. In my experience, powerd is less extreme than MacOS's throttling with its default settings. However you can configure the thresholds and minimum/maximum clockrates as you like.

sysctl(8) can be used to tweak the C-states (power modes) your processor will drop into. Details on these C-states are available in a few places. State C2 is generally safe, and available everywhere. C3 can apparently cause issues with SMP scheduling, however I haven't observed this:

machdep.mwait.CX.idle=AUTODEEP
hw.acpi.cpu.cx_lowest=C3

iwm(4) provides a tunable to set the power management scheme. I leave this set to the default (balanced), however it can be set to low-power mode with the hw.iwm.power_scheme tunable.

usbconfig(8) can be used to force power states for USB devices. I very rarely use the SD card reader, so I typically turn it off. A trivial savings, but one I have little reason not to make.

[root@oolong /]# usbconfig
ugen0.1: 0x8086 XHCI root HUB at usbus0, cfg=0 md=HOST spd=SUPER (5.0Gbps) pwr=SAVE (0mA)
ugen0.2: vendor 0x8087 product 0x0025 at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (100mA)
ugen0.3: Apple Inc. Apple Internal Keyboard at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (500mA)
ugen0.4: Apple Card Reader at usbus0, cfg=0 md=HOST spd=SUPER (5.0Gbps) pwr=ON (224mA)

[root@oolong /]# usbconfig -d 0.4 power_off

[root@oolong /]# usbconfig
ugen0.1: 0x8086 XHCI root HUB at usbus0, cfg=0 md=HOST spd=SUPER (5.0Gbps) pwr=SAVE (0mA)
ugen0.2: vendor 0x8087 product 0x0025 at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (100mA)
ugen0.3: Apple Inc. Apple Internal Keyboard at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (500mA)

Reviewing

I made these changes a long time ago, so I don't have hard data to back up the impact this made to battery life. However, you yourself can gather some of that information using the corepower(4) driver to expose (at the very least) CPU package power usage:

[root@oolong /]# sysctl hw.sensors
hw.sensors.cpu0.temp0: 62.00 degC (node0 core0 temp), OK
hw.sensors.cpu1.temp0: 62.00 degC (node0 core1 temp), OK
hw.sensors.cpu2.temp0: 62.00 degC (node0 core0 temp), OK
hw.sensors.cpu3.temp0: 62.00 degC (node0 core1 temp), OK
hw.sensors.cpu_node0.temp0: 62.00 degC (node0 temp), OK
hw.sensors.cpu_node0.power0: 5.76 W (node0 Package Power)
hw.sensors.cpu_node0.power1: 0.54 W (node0 DRAM Power)
hw.sensors.cpu_node0.power2: 0.63 W (node0 Cores Power)
hw.sensors.cpu_node0.power3: 1.86 W (node0 Graphics Power)
hw.sensors.dev_idmax: 6