Contribute
Register

Enabling PCIe ASPM for better power saving and battery life

Status
Not open for further replies.
Joined
Dec 23, 2014
Messages
42
Motherboard
Lenovo U310 (Clover)
CPU
i3-3217U (IvyBridge 1.80Ghz)
Graphics
HD4000, 1366x768
Mac
  1. 0
Classic Mac
  1. 0
Mobile Phone
  1. 0
For some time there has been a problem with laptops running Linux that some BIOSes wouldn't enable PCI Express power saving features ("Active State Power Management" or ASPM) for certain wireless cards, substantially reducing battery life.

I found this to be the case in my Hackbook: i installed lspci (I found it by googling 'lspci osx') and found out that the RTL8101E ethernet card in my laptop only had the L0s mode enabled by default, and the corresponding PCIe root complex wasn't enabling that either, while the AR9285 was enabling L1 only and ASPM for the root complex was again disabled.

To check which ASPM states are available and activated on your machine run lspci -vvv and look at the LinkCap(ability) and LinkCtl lines for each of your PCIe devices. If they differ, something is missing and you can try to enable it manually.

Somebody came up with a script based on setpci that enables the ASPM bit for the PCIe cards and root complexes specified by the user. The script is here http://drvbp1.linux-foundation.org/~...ts/enable-aspm

For ASPM to be effective the L0s and L1 modes should be enabled for both the endpoint (the card itself) and the root complex (the chipset bit). You can find the root complex corresponding to each card by running lspci -t. The script has to be edited according to their position (it is very well commented) and launched at startup. I am using it to enable ASPM states for my wireless and wired ethernet cards (so 2 endpoints and 2 root complexes).
I am not sure if setpci is normally available on OSX or it was installed by lspci, but it's working fine so far and I have all the ASPM capabilities turned on. My version of the script is here.

The best way to launch the script should be with a LaunchDaemon plist, but it was failing for me as it was probably being run too early in the boot process, so I resorted to launching it as a LoginHook, moving it in /usr/local/sbin and enabling it with
Code:
sudo defaults write com.apple.loginwindow LoginHook /usr/local/sbin/aspm.sh
This slows the login proces by a couple of seconds, but so far is working well.

Now I am not the primary user of this hack, I can't really say if and how much this improves battery life. Maybe somebody could give it a try and report back..
 
Interesting ...

It would seem that my Intel Ethernet NIC must not support this unless I'm doing it wrong.
Code:
Eriks-MacBook-Air:~ erikweiman$ lspci -tvnn
-[0000:00]-+-00.0  Intel Corporation Unknown device [8086:0a04]
           +-02.0  Intel Corporation Unknown device [8086:0a16]
           +-03.0  Intel Corporation Unknown device [8086:0a0c]
           +-14.0  Intel Corporation Unknown device [8086:9c31]
           +-16.0  Intel Corporation Unknown device [8086:9c3a]
           +-16.3  Intel Corporation Unknown device [8086:9c3d]
           +-19.0  Intel Corporation Unknown device [8086:155a]
           +-1b.0  Intel Corporation Unknown device [8086:9c20]
           +-1c.0-[0000:02]----00.0  Realtek Semiconductor Co., Ltd. Unknown device [10ec:5227]
           +-1c.1-[0000:03]----00.0  Intel Corporation Unknown device [8086:08b2]
           +-1d.0  Intel Corporation Unknown device [8086:9c26]
           +-1f.0  Intel Corporation Unknown device [8086:9c43]
           +-1f.2  Intel Corporation Unknown device [8086:9c03]
           \-1f.3  Intel Corporation Unknown device [8086:9c22]

Here is the code I changed to align with the root complex:
Code:
# You just need to modify these three values:
ROOT_COMPLEX="00:1c.1"
ROOT_COMPLEX_1="00:1c.0"
ENDPOINT="03:00.0"
ENDPOINT_1="02:00.0"

I was able to change this value on the WiFi card and the Media Card reader.
(note my WiFi card is actually an Atheros AR9285 card rather than the Intel card that it looks like in the output)

Code:
Eriks-MacBook-Air:~ erikweiman$ sudo ./aspm.sh
Root complex:
00:1c.0 PCI bridge: Intel Corporation Unknown device 9c1a (rev e4)
	0x50 : 0x40 --> 0x43 ... 
	[SUCCESS]]
	L1 and L0s
00:1c.1 PCI bridge: Intel Corporation Unknown device 9c14 (rev e4)
	0x50 : 0x40 --> 0x43 ... 
	[SUCCESS]]
	L1 and L0s

Endpoint:
03:00.0 Network controller: Intel Corporation Unknown device 08b2 (rev 01)
	0x70 : 0x40 --> 0x43 ... 
	[SUCCESS]]
	L1 and L0s
02:00.0 Class ff00: Realtek Semiconductor Co., Ltd. Unknown device 5227 (rev 01)
	0x80 : 0x40 --> 0x43 ... 
	[SUCCESS]]
	L1 and L0s
 
(note my WiFi card is actually an Atheros AR9285 card rather than the Intel card that it looks like in the output)
Is this because you had to rebrand it to make it through the bios whitelist?

However the script seems to work, L0s and L1 are enabled for both your cards (and they weren't before). Did you notice any improvement in battery life?
 
Is this because you had to rebrand it to make it through the bios whitelist?

However the script seems to work, L0s and L1 are enabled for both your cards (and they weren't before). Did you notice any improvement in battery life?

Correct to bypass bios whitelist.

I've not run it on battery long enough to know at this point if it helps.
 
I will definitely try this out when I have some time.

If it works maybe its possible to create a kext which attached to each IOPCIDevice and IOPCIBridge to enable ASPM.
 
Verified this one my machine, but all my PCI devices already have ASPM L0s and L1 enabled in LnkCtl where-ever LnkCap indicates availability.

So OS X seems to do this correctly by itself.
 
Status
Not open for further replies.
Back
Top