Authored by Vivek Gupta [MSFT]
Windows 8 supports a new device power state called the D3cold state. Adopting D3cold for USB presents some unique challenges for USB devices and drivers. In this blog post, I will talk about those challenges and certain restrictions. This post assumes that you are familiar with the content presented in Supporting D3cold in a Driver.
The deepest sleep state for a USB device defined in the USB specification is selective suspend. Whenever the power policy owner (often the function driver for the device) requests a D0->D2 or D0->D3 transition, the Microsoft-provided USB driver stack sends the device to the selective suspended state. In that state, the device consumes power in the range of few milliwatts. For traditional PC platforms, that power consumption is insignificant compared to the total system power consumption while the system is in S0. Therefore sending devices to selective suspend to conserve power has traditionally been good enough.
However, for newer platforms that support connected standby, the overall system power consumption in S0 can be extremely low. For such a system, even the few milliwatts that a USB device consumes while in selective suspend, starts to matter. With the goal of optimizing power for the new systems, we have defined D3cold for internal USB devices. In that state, the system cuts power to the device, the device drops off the bus, and the device does not consume any power.
Typically a device drops off the bus when the user surprise-removes (unplugs) the device. When a device is surprise removed, the USB stack detects the removal and reports it to PnP manager as removed, so the device stack can be torn down.
When a device enters D3cold, the hardware state is very similar to the surprise removal state but USB driver stack behaves differently. For D3cold, the driver stack does not report the device as removed and the device stack remains just the same. Later, when the device exits D3cold, the driver stack restores the USB configuration for the device. In Windows 8, only the USB 3.0 driver stack restores configuration but not the USB 2.0 driver stack. Therefore D3cold is not supported by the USB 2.0 driver stack. For information about USB 2.0 and USB 3.0 driver stacks, see USB Driver Stack Architecture.
In order for power to be cut in D3cold the ACPI firmware should describe power resources appropriately. More information about how to enable D3cold in ACPI, refer to the ACPI specification. In particular, see the _PR3 method.
The USB driver stack only supports D3cold for internal devices. That is because there is no way for the driver stack to distinguish between a device that is in D3cold and another device that has been surprise-removed by the user. Because internal devices cannot be surprise-removed, it is safe for the driver stack to assume that the device is in D3cold state. Therefore, the USB driver stack enables D3cold only for those USB devices that are marked as non-removable in ACPI.
In D3cold, a USB device drops off the bus. Because of that behavior, the USB stack needs to do some extra work to ensure that the process of the device entering and exiting D3cold remains transparent to the end user and applications.
To support D3cold, the function driver must implement these functionalities:
To support D3cold, the function driver must explicitly enable the state. The driver can do that either by using the D3cold interface or by modifying the DDInstall.HW section of the device INF. For information about those modifications, see the Remarks section in this topic.
To send the device to D3cold, the function driver must use D3 as the target device power state with IRP_MN_SET_POWER. Traditionally, if the driver uses the idle IRP mechanism with D3, USB driver stack fails the idle IRP on receiving the power IRP with D3. To avoid that behavior, the driver must set a new registry entry in the hardware key for the device:
Path: HKLM\System\CCS\Enum\<DeviceId>\<InstanceID>\Device Parameters
Name: AllowIdleIrpInD3 Type: REG_DWORD Value: 1
Then there is the question of the device losing its internal device state (such as information about the USB configuration) in D3cold. Even though the USB driver stack (only the USB 3.0 driver stack) restores the configuration state of the device, there might be additional device or class-specific state settings that get lost in D3cold. If there is any such setting, the function driver is responsible for preserving that state information. That implementation is similar to the driver’s functionality when the device resumes from a system sleep transition.
The function driver does not know exactly when the device transitions from D3 to D3cold. Therefore the driver must be prepared to save state information before it sends the D3 IRP. D3cold interface provides query functions that can help the driver optimize that behavior. By calling GetD3ColdCapability, the driver can determine whether its device can enter D3cold. By calling GetLastTransitionStatus, the driver determines whether the device successfully entered D3cold.
Though this is not unique to USB, it’s worth calling out that the function driver should be registered with the power framework so that the function driver can bring back the device to D0 in the case of surprise power on. If the driver chooses not to register with the power framework, then D3Cold can only be enabled in the case where the device does not share a power rail with any other device.
For a USB device to support D3cold, it should be able to connect to the USB bus within 1 second of being powered on. This is because after the function driver initiates a resume from D3cold state, power is restored to the device and then USB driver stack waits for the device to re-appear on the bus so that the stack can enumerate the device. If the device takes longer than 1 second, the driver stack does not wait for the device and reports the device as missing (removed).
Because the USB device is not attached to the bus in D3cold, there is no in-band support for wake from D3cold. Therefore, D3cold should be enabled only for those scenarios that do not require device-initiated wake. In fact the USB driver stack does not allow a wait-wake IRP in conjunction with a D3 IRP. If the function driver sends a wait-wake IRP followed by a D3 IRP, the driver stack fails the wait-wake IRP.
However, on some system configurations, there might be a mechanism to perform out-of-band wake from D3 cold with the help of ACPI. For example, there might be a dedicated GPIO line for that purpose. If appropriate methods are defined in the ACPI, ACPI filter driver pends the wait-wake IRP and completes it only when the out-of-band wake event occurs. In that case, the USB driver stack never gets the wait-wake IRP; therefore it’s ok for the function driver to send a wait-wake IRP with the D3 IRP. However, because ACPI always keeps the wait-wake IRP pending, the driver stack does not arm the device for in-band wake, even when the device transitions to D3hot. Therefore, if the device requires USB wake from D3hot, the device must use the same out-of-band mechanism to enable the device for wake and then propagate the device wake event.
A composite device has multiple functions, each managed by its own function driver. The following guidelines apply for such devices as long as the parent driver for the entire device is the Microsoft-provided USB Generic Parent Driver (Usbccgp.sys). In order to support D3cold on a composite device,
To summarize, in addition to the requirements listed in the MSDN documentation, D3cold for a USB device can be enabled only on Windows 8 if the following restrictions are met.
If you are a device manufacturer, read the restriction described in this post and decide if it is possible to enable D3cold for your device. Improper implementation of D3cold for the device can lead to poor user experience.