First, we have to list all of the different power IRPs a driver can receive. The minor function is not the only value that determines the type of power irp, you also have to look at if the power irp reflects the system or device power state. Dx means any device power state lower the D0, Sx means any system power state lower the S0.
Pessimistically speaking, you could come to the conclusion that all 8 power IRPs could be in the stack at once, but you have a few mitigating rules and behaviors that will narrow down the list.
- IRP_MN_POWER_SEQUENCE is not implemented by the power manager in any OS released so far. That leaves the potential of having 7 pending power IRPs at once.
- IRP_MN_QUERY_POWER/Sx and IRP_MN_SET_POWER/Sx are logically exclusive. The OS sends a query power before a set power and it would not make any sense to send a query for a certain power state while sending a set for a power state at the same time. That leaves the potential of having 6 pending power IRPs at once.
- IRP_MN_QUERY_POWER/Dx is an optional power IRP. It is up to the stack’s power policy owner to send this IRP if it wants. This IRP doesn’t make much sense in hindsight since power policy ownership is complicated enough without allowing other devices in the stack to veto/influence power operations. For instance, KMDF does not send a query Dx irp before requesting a set Dx IRp. That leaves the potential of having 5 pending power IRPs at once.
- IRP_MN_SET_POWER/Sx and IRP_MN_SET_POWER/S0 are mutually exclusive for 2 reasons. First, it doesn’t make sense that the machine would be transitioning into a low power state and S0 state at the same time. Second, IRP_MN_SET_POWER/SystemPowerState is a state changing IRP which is serialized against other state changing IRPs, which means only one can be in the stack at once. That leaves the potential of having 4 pending power IRPs at once.
- On the same vein as 4, IRP_MN_SET_POWER/Dx and IRP_MN_SET_POWER/D0 are mutually exclusive. In theory you could have both set Dx and set D0 pending in the stack at once because these are requested by the driver (vs IRP_MN_SET_POWER/SystemPowerState which are only sent by the OS power manager) and you don’t have control over every driver in the stack, but in practice, this is not a problem The power manager allows only one IRP_MN_SET_POWER/DevicePowerState IRP to be sent to a stack at once. That leaves the potential of having 3 pending power IRPs at once.
- Just like IRP_MN_SET_POWER/DevicePowerState IRPs, the power manager only one IRP_MN_WAIT_WAKE IRP to be sent to a stack at once. This does not reduce the number of potentially simultaneous power IRPs, but it simplifies wake processing at both the power policy owner and bus wake owner.
So, our list of potentially simultaneous pended power IRPs in a stack has been whittled down to the following:
- IRP_MN_SET_POWER/DevicePowerState (either D0 or Dx)
- IRP_MN_SET_POWER/SystemPowerState (either S0 or Sx)
This list is the final list. There are no more restrictions that can trim the list any further. If you think about it, this list makes sense if you think of the actions required to arm your device to wake from Sx. You receive a IRP_MN_SET_POWER/Sx and pend it. Before pending the Sx IRP, you request a IRP_MN_WAIT_WAKE IRP. When the IRP_MN_WAIT_WAKE IRP arrives, you arm yourself for wake, send the wake IRP down the stack and request a Dx IRP. When the Dx IRP arrives, you power down the device. At this point, all 3 power IRPs are pended in the stack. (For completeness sake, the power down sequence is finalized by sending the Dx IRP down the stack and upon its completion, sending the Sx irp down the stack and letting it complete back to the power manager.)