mbp-2016-linux
mbp-2016-linux copied to clipboard
Apple NVMe low-power self-refresh mode
Some Apple NVMe controllers support low-power self-refresh mode, LPSR. The following information describes the usage of LPSR by IONVMeFamily. Note that it is not derived from any Apple documentation and may be inaccurate. In addition to LPSR, there's also QoS with power budgets features, which is not considered here.
ACPI property "nvme-self-refresh" for the PCI controller indicates whether LPSR is supported for that device. It appears that LPSR is not supported by S3ELab.
LPSR is entered when the controller has been idle for some time. The idleness period is determined
by the LPSR counter. Let lpsrCount
denote the current LPSR counter value, lpsrTimeout
the idle
timer period in seconds. Then, whenever the timer expires, the values are updated as follows:
if (lpsrCount >= 9500000) {
lpsrTimeout = 0; // Disable timer
} else {
if (RunningOnExternalPower)
lpsrTimeout = 15;
else if (lpsrCount <= 6999999)
lpsrTimeout = 3;
else if (lpsrCount <= 7999999)
lpsrTimeout = 5;
else
lpsrTimeout = 8;
}
setIdleTimerPeriod(lpsrTimeout);
LPSR is prohibited in ACPI S3, S4 states if ACPI property for the controller
nvme-LPSR-during-S3-S4 != 1
.
Value lpsrCount
is initialised whenever the Identify command has been completed for the
controller. In order to fetch lpsrCount
, the following command is used:
command.features.opcode = 0xc2; // DebugServiceRead
command.features.dword12 = 0;
command.features.dword13 = 848;
lpsrCount = IssueCommand(command) << 32;
command.features.dword13 = 849;
lpsrCount |= IssueCommand(command);
When the timer expires, LPSR entry is initiated:
-
lpsrCount
is incremented. - Submission and completion queues are frozen, and the shutdown notification is sent by writing
0b11
toCC.SHN
controller register. - CSTS is then polled to ensure completion of shutdown.
- ACPI device "_PS3" or "_PS0" object is evaluated, respectively when entering or exiting LPSR.
For S3X, command with opcode 0xcc is sent (PrepareForShutdown
) before LPSR entry.
Note that for LPSR the reserved bit of CC.SHN
is used. Otherwise, for a normal shutdown, CC.SHN
is set to 0b01
.
IONVMeFamily hardcodes the response timeout for the above procedure to be 30 s for S3ELab, 60 s for S3X, and 5 s otherwise.
There is a public patent, describing parts of LPSR.
There was some discussion regarding LPSR and how it was needed to put the NVMecontroller in sleep mode. However, no solution was ever found. It's believed that this is the reason that suspend/resume does not work on the macbook 12-inch models (8,1 + 9,1 and 10,1)
https://github.com/cb22/macbook12-spi-driver/pull/2 https://github.com/cb22/macbook12-spi-driver/pull/30
@leifliddy you're right about command 0xcc being issued before shutdown, but it is only needed for S3X. I don't believe that LPSR is required for NVM shutdown in general, though.
@07151129 I'm not a kernel developer and don't know enough about acpi or nvme to know to implement that. There is however, a lot of interest in getting resume/suspend working on the Macbook 12 inch models: 8,1 + 9,1 + 10,1 and Macbook Pro models: 13,1 and 14,1 It sounds like this nvme LPSR problem is at the heart of the issue.