Fast Resume and how if affects your driver
Fast resume, which was introduced in Windows XP, is often mentioned when implementing power support in your WDM driver. But what does "fast resume" mean and when implementing fast resume, what side effects occur in your driver? I'll to answer both of these questions as well as the reasoning behind this feature. When I started to write this entry, I tried to look up fast resume in the WDK and found absolutely nothing! I was shocked since this is a very common term (at least internally at Microsoft); after speaking with the power team, there is a white paper that describes fast resume but you would never know it from the title "Measuring System Resume Performance on Windows Vista."
First, let's go over how to handle IRP_MN_SET_POWER/SystemPowerState for PowerSystemWorking (aka S0) IRP. You are supposed to pend the S0 irp and subsequently complete the S0 irp after you have requested a IRP_MN_SET_POWER/DevicePowerState PowerDeviceD0 IRP and it has been processed by the entire stack (which means you must register a Po completion routine which is where you complete the S0 IRP). In short, this means that the S0 IRP is pended in your driver as long as it takes for your device to power up. The definition of fast resume is simply that instead of pending the S0 IRP until the D0 IRP completes, you do not pend the S0 IRP and let it complete before the D0 IRP has been processed in your stack.
Sounds simple, right? Well, the devil is in the details. Here are a couple of issues with fast resume that I have encountered:
- Device power IRPs are not synchronized with PnP state changing IRPs as I wrote about earlier this year. This has a direct side effect on a fast resume implementation. Previous to fast resume, your D0 IRP could never be concurrently processed while a PnP state changing IRP (like a surprise remove) was being processed. This is due to the fact that system power IRPs are synchronized against PnP state changing IRPs and by pending the S0 IRP, you guard your device power up path from running concurrently with a PnP state change. This made life simple for both PnP and power IRP handling in your driver, but with fast resume this is no longer true. Now the state changing PnP can be running concurrently with your power up path and you must make sure that the PnP dispatch routine does not assume the device's power state nor does it free resources that the power dispatch path may be using.
- If this is a bus driver, the "free" power state synchronization between your parent device and your enumerated children goes away. WDM dictates that for a child device to be powered on, the parent must be powered on. By default you can get the right behavior, only after the parent device's S0 IRP has completed back to the power manager will the power manager send S0 IRPs to your child devices. This means that if you complete the S0 IRP before processing the D0 irp in the parent device, a new race condition occurs. The children could receive their S0 IRP and request their D0 IRP before the parent has processed (or even requested!) its own D0 IRP. This can be handled in the bus driver by pending each child's D0 IRP until the parent has completed its D0 IRP, but it can get complicated quickly (especially in the face of failure to power up).
So given these issues, why would you even want to implement fast resume? The answer lies in the history of fast resume, or rather, Windows 2000 which did not have this feature. Resume times on Windows 2000 laptops was not great. There were a causes for the poor resume time, but a large contributor was device resume time. Since the OS serialized S0 IRPs to all devices in the PnP tree, the time for each device to resume added sequentially to the system's resume time. The OS serialization of the S0 IRPs could not change for Windows XP, so the problem was attacked at the other end...each driver would complete the S0 IRP as fast as it could so the OS could resume quickly and then asynchronously power up the device. This way each device could power up in parallel and the total time to power up was not sequential (nor was it only the longest of any device to power up since there is still ordering between parent and child devices) and resume time could be dramatically slower.
Given the perceivable value you are giving to the user by implementing fast resume, I recommend that you implement it in your (non bus) function driver and handle the new races between PnP state changing IRPs and power IRPs (which if you implemented idle during S0, must also be accounted for already. Considering the complicated aspects of asynchronously managing a parent's power state and a child's power state, I would not recommend that you implement fast resume in a bus driver. This follows the recommendations in the aforementioned white paper.
Obligatory KMDF plug: KMDF automatically implements fast resume for you and handles both issues behind the scenes. You will not process a pnp state changing irp while power up (or down) and if you are a bus driver, you will get an implementation which maintains the parent/child relationship with respect to power state.