mbp-2016-linux icon indicating copy to clipboard operation
mbp-2016-linux copied to clipboard

Apple NVMe low-power self-refresh mode

Open 07151129 opened this issue 5 years ago • 3 comments

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:

  1. lpsrCount is incremented.
  2. Submission and completion queues are frozen, and the shutdown notification is sent by writing 0b11 to CC.SHN controller register.
  3. CSTS is then polled to ensure completion of shutdown.
  4. 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.

07151129 avatar Jan 20 '20 17:01 07151129

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 avatar Jan 21 '20 06:01 leifliddy

@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 avatar Jan 21 '20 12:01 07151129

@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.

leifliddy avatar Feb 04 '20 12:02 leifliddy