ReactOS  0.4.15-dev-1632-g4e289ce
powerpolicystatemachine.cpp
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) Microsoft. All rights reserved.
4 
5 Module Name:
6 
7  PowerPolicyStateMachine.cpp
8 
9 Abstract:
10 
11  This module implements the Power Policy state machine for the driver
12  framework. This code was split out from FxPkgPnp.cpp.
13 
14 Author:
15 
16 
17 
18 
19 Environment:
20 
21  Both kernel and user mode
22 
23 Revision History:
24 
25 
26 
27 --*/
28 
29 #include "pnppriv.hpp"
30 
31 #if FX_IS_KERNEL_MODE
32 #include <usbdrivr.h>
33 #endif
34 
35 #include "fxusbidleinfo.hpp"
36 
37 extern "C" {
38 #if defined(EVENT_TRACING)
39 #include "PowerPolicyStateMachine.tmh"
40 #endif
41 }
42 
43 //
44 // The Power Policy State Machine
45 //
46 // This state machine responds to the following events:
47 //
48 // PowerUp
49 // PowerDown
50 // PowerPolicyStart
51 // PowerPolicyStop
52 // IRP_MN_SET_POWER -- System State S0
53 // IRP_MN_SET_POWER -- System State Sx
54 // PowerTimeoutExpired
55 // IoPresent
56 // IRP_MN_WAIT_WAKE Complete
57 // IRP_MN_WAIT_WAKE Failed
58 //
59 
60 #if FX_SUPER_DBG
61  #define ASSERT_PWR_POL_STATE(_This, _State) \
62  ASSERT((_This)->m_Device->GetDevicePowerPolicyState() == (_State))
63 #else
64  #define ASSERT_PWR_POL_STATE(_This, _State) (0)
65 #endif
66 
67 #if FX_STATE_MACHINE_VERIFY
68  #define VALIDATE_PWR_POL_STATE(_CurrentState, _NewState) \
69  ValidatePwrPolStateEntryFunctionReturnValue((_CurrentState), (_NewState))
70 #else
71  #define VALIDATE_PWR_POL_STATE(_CurrentState, _NewState) (0)
72 #endif //FX_STATE_MACHINE_VERIFY
73 
74 // @@SMVERIFY_SPLIT_BEGIN
75 
77 {
80 };
81 
83 {
86 };
87 
89 {
95 };
96 
98 {
105 };
106 
108 {
111 };
112 
114 {
117 };
118 
120 {
127 };
128 
130 {
134 };
135 
137 {
140 };
141 
143 {
147 };
148 
150 {
153 };
154 
156 {
160 };
161 
163 {
167 };
168 
170 {
174 };
175 
177 {
180 };
181 
183 {
189 };
190 
192 {
199 };
200 
202 {
205 };
206 
208 {
211 };
212 
214 {
218 };
219 
221 {
230 };
231 
233 {
244 };
245 
247 {
250 };
251 
253 {
257 };
258 
260 {
264 };
265 
267 {
271 };
272 
274 {
277 };
278 
280 {
284 };
285 
287 {
290 };
291 
293 {
296 };
297 
299 {
304 };
305 
307 {
311 };
312 
314 {
317 };
318 
320 {
324 };
325 
327 {
330 };
331 
333 {
336 };
337 
339 {
342 };
343 
345 {
348 };
349 
351 {
354 };
355 
357 {
363 };
364 
366 {
369 };
370 
372 {
375 };
376 
378 {
382 };
383 
385 {
388 };
389 
391 {
395 };
396 
398 {
402 };
403 
405 {
408 };
409 
411 {
414 };
415 
417 {
420 };
421 
423 {
427 };
428 
430 {
433 };
434 
436 {
439 };
440 
442 {
445 };
446 
448 {
452 };
453 
455 {
458 };
459 
461 {
465 };
466 
468 {
471 };
472 
474 {
477 };
478 
480 {
483 };
484 
486 {
489 };
490 
492 {
495 };
496 
498 {
502 };
503 
505 {
508 };
509 
511 {
514 };
515 
517 {
520 };
521 
523 {
526 };
527 
529 {
532 };
533 
535 {
538 };
539 
541 {
546 };
547 
549 {
552 };
553 
555 {
558 };
559 
561 {
562  // transition function,
563  // { first target state },
564  // other target states
565  // queue open,
566 
567  // WdfDevStatePwrPolObjectCreated
568  { NULL,
571  { TRUE,
572  PwrPolS0 | // Sx -> S0 transition on a PDO which was enumerated and
573  // in the disabled state
574 
575  PwrPolSx | // Sx transition right after enumeration
577  },
578 
579  // WdfDevStatePwrPolStarting
583  { FALSE,
584  PwrPolPowerUpFailed // If the power state machine fails D0 entry upon
585  // initial start, we will get this event here. The
586  // pnp s.m. will not rely on the pwr pol s.m. to
587  // power down the stack in this case.
588  },
589  },
590 
591  // WdfDevStatePwrPolStartingSucceeded
594  NULL,
595  { FALSE,
596  0 },
597  },
598 
599  // WdfDevStatePwrPolStartingFailed
602  NULL,
603  { TRUE,
604  0 },
605  },
606 
607  // WdfDevStatePwrPolStartingDecideS0Wake
609  { PwrPolNull, WdfDevStatePwrPolNull }, // transition out based on wake from S0 enabled
610  NULL,
611  { FALSE,
612  0 },
613  },
614 
615  // WdfDevStatePwrPolStartedIdleCapable
619  { TRUE,
620  PwrPolS0 | // If the machine send a query Sx and it fails, it will send
621  // an S0 while in the running state (w/out ever sending a true set Sx irp)
622  PwrPolWakeArrived | // If the wake request is failed by the bus in between WakeArrived
623  // being posted in TimerExpiredWakeCapapble and being
624  // processed, this event will show up in this state if the idle
625  // setting changed at this exact moment as well
626  PwrPolPowerUp | // posted by power when we are powering up the first time
627  PwrPolIoPresent | // posted by the idle state machine. If we return
628  // to idle this can happen
629  PwrPolDevicePowerNotRequired | // The device-power-not-required event arrived just after an
630  // I/O request or or an S0-idle policy change caused us to
631  // become active again. The event is ignored in this case.
632  PwrPolDevicePowerRequired // The device-power-required event arrived, but we had already
633  // powered-up the device proactively because we detected that
634  // power was needed. The event is ignored in this case.
635  },
636  },
637 
638  // WdfDevStatePwrPolTimerExpiredNoWake
642  { FALSE,
643  0 },
644  },
645 
646  // WdfDevStatePwrPolTimerExpiredNoWakeCompletePowerDown
648  // NOTE: see the comments PowerPolWaitingArmedUsbSS() about why we query the
649  // idle state instead of going directly to WdfDevStatePwrPolWaitingUnarmed
652  { FALSE,
653  0 },
654  },
655 
656  // WdfDevStatePwrPolWaitingUnarmed
657  { NULL,
660  { TRUE,
661  PwrPolS0 | // If the machine send a query Sx and it fails, it will send
662  // an S0 while in the running state (w/out ever sending a true set Sx irp)
663  PwrPolDevicePowerNotRequired // When moving from Sx -> S0, we do not power up the
664  // device if:
665  // (UsingSystemManagedIdleTimeout == TRUE) and
666  // (IdleEnabled == TRUE) and
667  // (WakeFromS0Capable == FALSE) and
668  // (PowerUpIdleDeviceOnSystemWake == FALSE).
669  // In this situation, we declare to the active/idle
670  // state machine that we are idle, but ignore the
671  // device-power-not-required event, because we are
672  // already in Dx.
673  },
674  },
675 
676  // WdfDevStatePwrPolWaitingUnarmedQueryIdle
679  NULL,
680  { FALSE,
681  0 },
682  },
683 
684  // WdfDevStatePwrPolS0NoWakePowerUp
688  { FALSE,
689  0 },
690  },
691 
692  // WdfDevStatePwrPolS0NoWakeCompletePowerUp
696  { FALSE,
697  0 },
698  },
699 
700  // WdfDevStatePwrPolSystemSleepFromDeviceWaitingUnarmed
702  { PwrPolNull, WdfDevStatePwrPolNull }, // transition out based on wake from Sx enabled
703  NULL,
704  { FALSE,
705  0 },
706  },
707 
708  // WdfDevStatePwrPolSystemSleepNeedWake
712  { FALSE,
713  0 },
714  },
715 
716  // WdfDevStatePwrPolSystemSleepNeedWakeCompletePowerUp
720  { FALSE,
721  0 },
722  },
723 
724  // WdfDevStatePwrPolSystemSleepPowerRequestFailed
727  NULL,
728  { FALSE,
729  0, },
730  },
731 
732  // WdfDevStatePwrPolCheckPowerPageable
734  { PwrPolNull, WdfDevStatePwrPolNull }, // transition out based on which DO_POWER_Xxx flags set on DO
735  NULL,
736  { FALSE,
737  0 },
738  },
739 
740  // WdfDevStatePwrPolSleepingWakeWakeArrived
744  { FALSE,
745  PwrPolWakeFailed | // wake completed before we could cancel
746  // the request, so the event may end up here
747  PwrPolWakeSuccess| // -do-
748  PwrPolWakeInterruptFired // Wake interrupt fired when during power
749  // down as part of system sleep transition
750 
751  },
752  },
753 
754  // WdfDevStatePwrPolSleepingWakeRevertArmWake
758  { FALSE,
759  0 },
760  },
761 
762  // WdfDevStatePwrPolSystemAsleepWakeArmed
766  { TRUE,
767  PwrPolWakeFailed | // Wake failed while in Sx
768  PwrPolIoPresent | // IO arrived when the machine was going to Sx
769  PwrPolPowerTimeoutExpired | // we don't cancel the power timer when we goto
770  // sleep from an idleable state
771  PwrPolDevicePowerNotRequired // Upon receiving Sx, we simulated a device-power-
772  // not-required, so the device-power-requirement
773  // state machine sent us this event in response.
774  // We can drop it because we already powered down.
775  },
776  },
777 
778  // WdfDevStatePwrPolSystemWakeDeviceWakeEnabled
782  { FALSE,
783  PwrPolWakeInterruptFired // wake interrupt fired as we were waking the
784  // device on receiving S0 due to other reasons.
785  // This event can fire until the wake interrupt
786  // machine is notified of the power up.
787  },
788  },
789 
790  // WdfDevStatePwrPolSystemWakeDeviceWakeEnabledWakeCanceled
794  { FALSE,
795  PwrPolWakeInterruptFired // wake interrupt fired as we were waking the
796  // device on receiving S0 due to other reasons.
797  // This event can fire until the wake interrupt
798  // machine is notified of the power up.
799  },
800  },
801 
802  // WdfDevStatePwrPolSystemWakeDeviceWakeDisarm
804  { PwrPolNull, WdfDevStatePwrPolNull }, // transition out is hardcoded in func
805  NULL,
806  { FALSE,
807  0 },
808  },
809 
810  // WdfDevStatePwrPolSystemWakeDeviceWakeTriggered
811  { NULL,
813  NULL,
814  { TRUE,
815  0 },
816  },
817 
818  // WdfDevStatePwrPolSystemWakeDeviceWakeTriggeredS0
822  { FALSE,
823  0 },
824  },
825 
826  // WdfDevStatePwrPolSystemWakeDeviceWokeDisarm
828  { PwrPolNull, WdfDevStatePwrPolNull }, // transition out is hardcoded in func
829  NULL,
830  { FALSE,
831  0 },
832  },
833 
834  // WdfDevStatePwrPolSleepingWakeWakeArrivedNP,
838  { FALSE,
839  PwrPolWakeFailed | // wake completed before we could cancel
840  // the request, so the event may end up here
841  PwrPolWakeSuccess| // -do-
842  PwrPolWakeInterruptFired // Wake interrupt fired when during power
843  // down as part of system sleep transition
844 
845  },
846  },
847 
848  // WdfDevStatePwrPolSleepingWakeRevertArmWakeNP,
852  { FALSE,
853  0 },
854  },
855 
856  // WdfDevStatePwrPolSleepingWakePowerDownFailed
860  { FALSE,
861  0 },
862  },
863 
864  // WdfDevStatePwrPolSleepingWakePowerDownFailedWakeCanceled
867  NULL,
868  { FALSE,
869  0 },
870  },
871 
872  // WdfDevStatePwrPolSystemAsleepWakeArmedNP
876  { TRUE,
877  PwrPolWakeFailed | // Wake failed while in Sx
878  PwrPolIoPresent | // IO arrived when the machine was going to Sx
879  PwrPolPowerTimeoutExpired // we don't cancel the power timer when we goto
880  // sleep from an idleable state
881  },
882  },
883 
884  // WdfDevStatePwrPolSystemWakeDeviceWakeEnabledNP
888  { FALSE,
889  PwrPolWakeInterruptFired // wake interrupt fired as we were waking the
890  // device on receiving S0 due to other reasons.
891  // This event can fire until the wake interrupt
892  // machine is notified of the power up.
893  },
894  },
895 
896  // WdfDevStatePwrPolSystemWakeDeviceWakeEnabledWakeCanceledNP
900  { FALSE,
901  PwrPolWakeSuccess | // wake succeeded and completed before we could cancel
902  // the request, so the event ends up here
903 
904  PwrPolWakeInterruptFired // wake interrupt fired as we were waking the
905  // device on receiving S0 due to other reasons.
906  // This event can fire until the wake interrupt
907  // machine is notified of the power up.
908  },
909  },
910 
911  // WdfDevStatePwrPolSystemWakeDeviceWakeDisarmNP
913  { PwrPolNull, WdfDevStatePwrPolNull }, // transition out is hardcoded in func
914  NULL,
915  { FALSE,
916  0 },
917  },
918 
919  // WdfDevStatePwrPolSystemWakeDeviceWakeTriggeredNP
920  { NULL,
922  NULL,
923  { TRUE,
924  PwrPolIoPresent // I/O arrived before S0 arrival
925  },
926  },
927 
928  // WdfDevStatePwrPolSystemWakeDeviceWakeTriggeredS0NP
932  { FALSE,
933  0 },
934  },
935 
936  // WdfDevStatePwrPolSystemWakeDeviceWokeDisarmNP
938  { PwrPolNull, WdfDevStatePwrPolNull }, // transition out is hardcoded in func
939  NULL,
940  { FALSE,
941  0 },
942  },
943 
944  // WdfDevStatePwrPolSystemWakeDeviceWakeCompletePowerUp
948  { FALSE,
949  0 },
950  },
951 
952  // WdfDevStatePwrPolSleeping
955  NULL,
956  { FALSE,
957  0 },
958  },
959 
960  // WdfDevStatePwrPolSleepingNoWakePowerDown
964  { FALSE,
965  0 },
966  },
967 
968  // WdfDevStatePwrPolSleepingNoWakeCompletePowerDown
972  { FALSE,
973  PwrPolWakeArrived // wake arrived event posted after the ww irp
974  // completed from SleepingSendWake state. Ignore this
975  // event since wake is already trigged.
976  },
977  },
978 
979  // WdfDevStatePwrPolSleepingNoWakeDxRequestFailed
981  { PwrPolNull, WdfDevStatePwrPolNull }, // transition out is hardcoded in func
982  NULL,
983  { FALSE,
984  0 },
985  },
986 
987  // WdfDevStatePwrPolSleepingWakePowerDown
991  { FALSE,
992  0 },
993  },
994 
995  // WdfDevStatePwrPolSleepingSendWake
999  { FALSE,
1000  0 },
1001  },
1002 
1003  // WdfDevStatePwrPolSystemAsleepNoWake
1006  NULL,
1007  { TRUE,
1008  PwrPolS0IdlePolicyChanged | // Policy changed while the device is in Dx
1009  // because of Sx, we will reevaluate the idle
1010  // settings when we return to S0 anyways
1011  PwrPolWakeArrived | // If arming for wake from sx failed, the WakeArrived
1012  // event that was a part of that arming is dequeued here
1013  PwrPolIoPresent | // I/O showed up when going into Sx
1015  PwrPolDevicePowerNotRequired // Upon receiving Sx, we simulated a device-power-
1016  // not-required, so the device-power-requirement
1017  // state machine sent us this event in response.
1018  // We can drop it because we already powered down.
1019  },
1020  },
1021 
1022  // WdfDevStatePwrPolSystemWakeDeviceWakeDisabled
1024  { PwrPolNull, WdfDevStatePwrPolNull }, // transition out based on wake from S0 enabled
1025  NULL,
1026  { FALSE,
1027  0 },
1028  },
1029 
1030  // WdfDevStatePwrPolSystemWakeDeviceToD0
1034  { FALSE,
1035  0 },
1036  },
1037 
1038  // WdfDevStatePwrPolSystemWakeDeviceToD0CompletePowerUp
1042  { FALSE,
1043  0 },
1044  },
1045 
1046  // WdfDevStatePwrPolSystemWakeQueryIdle
1048  { PwrPolNull, WdfDevStatePwrPolNull}, // transition out based on timer expiration state
1049  NULL,
1050  { FALSE,
1051  0 },
1052  },
1053 
1054  // WdfDevStatePwrPolStartedWakeCapable
1058  { TRUE,
1059  PwrPolS0 | // If the machine send a query Sx and it fails, it will send
1060  // an S0 while in the running state (w/out ever sending a true set Sx irp)
1061  PwrPolPowerUp |
1062  PwrPolWakeArrived | // If the wake request is failed by the bus in between WakeArrived
1063  // being posted in TimerExpiredWakeCapapble and being
1064  // processed, this event will show up in this state
1065 
1066  PwrPolWakeSuccess | // wake succeeded while we were trying to cancel it
1067  // while coming out of WaitingArmed b/c of io present
1068 
1069  PwrPolWakeFailed | // wake request failed while we were trying to cancel it
1070  // while coming out of WaitingArmed b/c of io present
1071 
1073  PwrPolUsbSelectiveSuspendCompleted | // When returning from a success resume
1074  // from USB SS, the completion of the irp will
1075  // occur in the started state
1076 
1077  PwrPolIoPresent | // posted by the idle state machine. If we return
1078  // to idle this can happen
1079  PwrPolDevicePowerNotRequired | // The device-power-not-required event arrived just after an
1080  // I/O request or or an S0-idle policy change caused us to
1081  // become active again. The event is ignored in this case.
1082  PwrPolDevicePowerRequired // The device-power-required event arrived, but we had already
1083  // powered-up the device proactively because we detected that
1084  // power was needed. The event is ignored in this case.
1085  },
1086  },
1087 
1088  // WdfDevStatePwrPolTimerExpiredDecideUsbSS
1091  NULL,
1092  { FALSE,
1093  0 },
1094  },
1095 
1096  // WdfDevStatePwrPolTimerExpiredWakeCapablePowerDown
1100  { FALSE,
1101  0 },
1102  },
1103 
1104  // WdfDevStatePwrPolTimerExpiredWakeCapableSendWake
1108  { FALSE,
1109  0 },
1110  },
1111 
1112  // WdfDevStatePwrPolTimerExpiredWakeCapableUsbSS
1116  { TRUE,
1117  0 },
1118  },
1119 
1120  // WdfDevStatePwrPolTimerExpiredWakeCapableWakeArrived
1124  { FALSE,
1125  0 },
1126  },
1127 
1128  // WdfDevStatePwrPolTimerExpiredWakeCapableCancelWake
1132  { FALSE,
1133  0 },
1134  },
1135 
1136  // WdfDevStatePwrPolTimerExpiredWakeCapableWakeCanceled
1139  NULL,
1140  { FALSE,
1141  0 },
1142  },
1143 
1144  // WdfDevStatePwrPolTimerExpiredWakeCapableCleanup
1147  NULL,
1148  { FALSE,
1149  0 },
1150  },
1151 
1152  // WdfDevStatePwrPolTimerExpiredWakeCapableDxAllocFailed
1155  NULL,
1156  { FALSE,
1157  0 },
1158  },
1159 
1160  // WdfDevStatePwrPolTimerExpiredWakeCompletedPowerDown
1164  { FALSE,
1165  PwrPolWakeSuccess | // arming callback failed while going into Dx armed for wake from S0
1166  // but bus completed wake request with success
1167 
1168  PwrPolWakeArrived // if the wake request completes before PwrPolWakeArrived
1169  // can be processed in the PwrPolTimerExpiredWakeCapableSendWake
1170  // state, it will show up here
1171  },
1172  },
1173 
1174  // WdfDevStatePwrPolTimerExpiredWakeCompletedPowerUp
1178  { FALSE,
1179  PwrPolWakeSuccess | // arming callback failed while going into Dx armed for wake from S0
1180  // but bus completed wake request with success
1181 
1182  PwrPolWakeArrived // if the wake request completes before PwrPolWakeArrived
1183  // can be processed in the WdfDevStatePwrPolTimerExpiredWakeCapableSendWake
1184  // state, it will show up here
1185  },
1186  },
1187 
1188  // WdfDevStatePwrPolWaitingArmedUsbSS
1191  NULL,
1192  { FALSE,
1193  0 },
1194  },
1195 
1196  // WdfDevStatePwrPolWaitingArmed
1197  { NULL,
1200  { TRUE,
1201  PwrPolS0 // If the machine send a query Sx and it fails, it will send
1202  // an S0 while in the running state (w/out ever sending a true set Sx irp)
1203  },
1204  },
1205 
1206  // WdfDevStatePwrPolWaitingArmedQueryIdle
1209  NULL,
1210  { FALSE,
1211  0 },
1212  },
1213 
1214  // WdfDevStatePwrPolIoPresentArmed
1218  { FALSE,
1219  PwrPolWakeInterruptFired // wake interrupt fired as we were waking the
1220  // device on receiving IO.This event can fire
1221  // until the wake interrupt machine is notified
1222  // of the power up.
1223  },
1224  },
1225 
1226  // WdfDevStatePwrPolIoPresentArmedWakeCanceled
1230  { FALSE,
1231  PwrPolWakeSuccess | // The wake status was already processed before entering
1232  // this state - indicates that the client driver is
1233  // probably propagating a duplicate wake status using
1234  // the WdfDeviceIndicateWakeStatus ddi.
1235 
1236  PwrPolWakeFailed | // The wake status was already processed before entering
1237  // this state - indicates that the client driver is
1238  // probably propagating a duplicate wake status using
1239  // the WdfDeviceIndicateWakeStatus ddi.
1240 
1241  PwrPolWakeInterruptFired // wake interrupt fired as we were waking the
1242  // device on receiving IO.This event can fire
1243  // until the wake interrupt machine is notified
1244  // of the power up.
1245 
1246  },
1247  },
1248 
1249  // WdfDevStatePwrPolS0WakeDisarm,
1251  { PwrPolNull, WdfDevStatePwrPolNull }, // transition out is hardcoded in func
1252  NULL,
1253  { FALSE,
1254  0 },
1255  },
1256 
1257  // WdfDevStatePwrPolS0WakeCompletePowerUp
1261  { FALSE,
1262  0 },
1263  },
1264 
1265  // WdfDevStatePwrPolTimerExpiredWakeSucceeded
1267  { PwrPolNull, WdfDevStatePwrPolNull }, // transition out is hardcoded in func
1268  NULL,
1269  { FALSE,
1270  0 },
1271  },
1272 
1273  // WdfDevStatePwrPolTimerExpiredWakeCompletedDisarm
1276  NULL,
1277  { FALSE,
1278  0 },
1279  },
1280 
1281  // WdfDevStatePwrPolTimerExpiredWakeCapableWakeSucceeded
1282  { NULL,
1285  { FALSE,
1286  0 },
1287  },
1288 
1289  // WdfDevStatePwrPolTimerExpiredWakeCapableWakeFailed
1290  { NULL,
1293  { FALSE,
1294  0 },
1295  },
1296 
1297  // WdfDevStatePwrPolWakeFailedUsbSS
1300  NULL,
1301  { FALSE,
1302  0 },
1303  },
1304 
1305  // WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedCancelWake
1309  { FALSE,
1310  0 },
1311  },
1312 
1313  // WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedWakeCanceled
1316  NULL,
1317  { FALSE,
1318  0 },
1319  },
1320 
1321  // WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedUsbSS
1324  NULL,
1325  { FALSE,
1326  0 },
1327  },
1328 
1329  // WdfDevStatePwrPolCancelingWakeForSystemSleep
1333  { FALSE,
1334  0 },
1335  },
1336 
1337  // WdfDevStatePwrPolCancelingWakeForSystemSleepWakeCanceled
1341  { FALSE,
1342  PwrPolWakeSuccess // Wake completed successfully right as the transition
1343  // from WaitingArmed to goto Sx occurred
1344  },
1345  },
1346 
1347  // WdfDevStatePwrPolDisarmingWakeForSystemSleepCompletePowerUp
1351  { FALSE,
1352  0, },
1353  },
1354 
1355  // WdfDevStatePwrPolPowerUpForSystemSleepFailed
1358  NULL,
1359  { FALSE,
1360  0 },
1361  },
1362 
1363  // WdfDevStatePwrPolWokeFromS0UsbSS
1366  NULL,
1367  { FALSE,
1368  0 },
1369  },
1370 
1371  // WdfDevStatePwrPolWokeFromS0
1375  { FALSE,
1376  0 },
1377  },
1378 
1379  // WdfDevStatePwrPolWokeFromS0NotifyDriver
1382  NULL,
1383  { FALSE,
1384  0 },
1385  },
1386 
1387  // WdfDevStatePwrPolStoppingResetDevice
1391  { FALSE,
1392  0 },
1393  },
1394 
1395  // WdfDevStatePwrPolStoppingResetDeviceCompletePowerUp
1399  { FALSE,
1400  0 },
1401  },
1402 
1403  // WdfDevStatePwrPolStoppingResetDeviceFailed
1406  NULL,
1407  { FALSE,
1408  0 },
1409  },
1410 
1411  // WdfDevStatePwrPolStoppingD0
1415  { FALSE,
1416  PwrPolWakeSuccess | // In the waiting armed state, the wake completed
1417  // right after PwrPolStop arrived
1418  PwrPolWakeFailed // wake completed before we could cancel
1419  // the request, so the event may end up here
1420  },
1421  },
1422 
1423  // WdfDevStatePwrPolStoppingD0Failed
1426  NULL,
1427  { FALSE,
1428  0 },
1429  },
1430 
1431  // WdfDevStatePwrPolStoppingDisarmWake
1435  { FALSE,
1436  PwrPolWakeFailed | // wake completed before we could cancel
1437  // the request, so the event may end up here
1438  PwrPolWakeSuccess // -do-
1439  },
1440  },
1441 
1442  // WdfDevStatePwrPolStoppingDisarmWakeCancelWake
1446  { FALSE,
1447  PwrPolUsbSelectiveSuspendCompleted // pwr pol stopped from a usb SS device
1448  // in Dx and the irp completed when the D0
1449  // irp was sent
1450  },
1451  },
1452 
1453  // WdfDevStatePwrPolStoppingDisarmWakeWakeCanceled
1455  { PwrPolNull, WdfDevStatePwrPolNull}, // transition to Stopping occurs in function
1456  NULL,
1457  { FALSE,
1458  PwrPolUsbSelectiveSuspendCompleted // pwr pol stopped from a usb SS device
1459  // in Dx and the irp completed when the D0
1460  // irp was sent
1461  },
1462  },
1463 
1464  // WdfDevStatePwrPolStopping
1468  { FALSE,
1469  PwrPolUsbSelectiveSuspendCompleted // pwr pol stopped from a usb SS device
1470  // in Dx and the irp completed when the D0
1471  // irp was sent
1472  },
1473  },
1474 
1475  // WdfDevStatePwrPolStoppingFailed
1478  NULL,
1479  { FALSE,
1480  0 },
1481  },
1482 
1483  // WdfDevStatePwrPolStoppingSendStatus
1486  NULL,
1487  { FALSE,
1488  0 },
1489  },
1490 
1491  // WdfDevStatePwrPolStoppingCancelTimer
1494  NULL,
1495  { FALSE,
1496  0 },
1497  },
1498 
1499  // WdfDevStatePwrPolStoppingWaitForIdleTimeout
1500  { NULL,
1502  NULL,
1503  { TRUE,
1504  0 },
1505  },
1506 
1507  // WdfDevStatePwrPolStoppingCancelUsbSS
1510  NULL,
1511  { FALSE,
1512  0 },
1513  },
1514 
1515  // WdfDevStatePwrPolStoppingWaitForUsbSSCompletion
1516  { NULL,
1518  NULL,
1519  { TRUE,
1520  0 },
1521  },
1522 
1523  // WdfDevStatePwrPolStoppingCancelWake
1527  { TRUE,
1528  0 },
1529  },
1530 
1531  // WdfDevStatePwrPolStopped
1532  { NULL,
1535  { TRUE,
1536  PwrPolPowerTimeoutExpired | // idle timer fired right before stopping
1537  // pwr policy and before pwr pol could process
1538  // the timeout
1539  PwrPolIoPresent | // I/O arrived while transitioning to the
1540  // stopped state
1541  PwrPolDevicePowerRequired // Due to a power-related failure, we declared our device state
1542  // as failed and stopped the power policy state machine. But
1543  // before stopping the power policy machine, we would have
1544  // declared ourselves as powered-on (maybe fake) in order to
1545  // move the power framework to a consistent state. Since we've
1546  // already declared ourselves as powered-on, we can drop this.
1547  },
1548  },
1549 
1550  // WdfDevStatePwrPolCancelUsbSS
1554  { TRUE,
1555  PwrPolIoPresent // I/O arrived while we were waiting for the USB idle notification IOCTL
1556  // to be completed after we had canceled it. It is okay to drop this
1557  // event because we are already in the process to returning to the powered-
1558  // up state.
1559  },
1560  },
1561 
1562  // WdfDevStatePwrPolStarted
1566  { TRUE,
1567  PwrPolS0 | // If the machine send a query Sx and it fails, it will send
1568  // an S0 while in the running state (w/out ever sending a true set Sx irp)
1569  PwrPolWakeArrived | // If the wake request is failed by the bus in between WakeArrived
1570  // being posted in TimerExpiredWakeCapapble and being
1571  // processed, this event will show up in this state if the idle
1572  // setting changed at this exact moment as well
1573  PwrPolWakeSuccess | // returning from Dx armed for wake from Sx, wake
1574  // is completed w/success after S0 irp arrives
1575  PwrPolPowerUp |
1576  PwrPolUsbSelectiveSuspendCompleted | // sent when we move out of the armed
1577  // & idle enabled state into the
1578  // idle disabled state
1579  PwrPolIoPresent |// This just indicates that I/O arrived, which is fine here
1580  PwrPolPowerTimeoutExpired | // this can happen when idle timer is disabled
1581  // due to policy change while powering up.
1582  PwrPolDevicePowerRequired // idle policy changed when device was powered down
1583  // due to S0-idle. The policy change caused us to power
1584  // up. As part of powering up, the device-power-required
1585  // event arrived. Can drop because we already powered-up.
1586  },
1587  },
1588 
1589  // WdfDevStatePwrPolStartedCancelTimer
1592  NULL,
1593  { FALSE,
1594  0 },
1595  },
1596 
1597  // WdfDevStatePwrPolStartedWaitForIdleTimeout
1598  { NULL,
1601  { TRUE,
1602  0 },
1603  },
1604 
1605  // WdfDevStatePwrPolStartedWakeCapableCancelTimerForSleep
1608  NULL,
1609  { FALSE,
1610  0 },
1611  },
1612 
1613  // WdfDevStatePwrPolStartedWakeCapableWaitForIdleTimeout
1614  { NULL,
1616  NULL,
1617  { TRUE,
1618  0 },
1619  },
1620 
1621  // WdfDevStatePwrPolStartedWakeCapableSleepingUsbSS
1624  NULL,
1625  { TRUE,
1626  0 },
1627  },
1628 
1629  // WdfDevStatePwrPolStartedIdleCapableCancelTimerForSleep
1632  NULL,
1633  { FALSE,
1634  0 },
1635  },
1636 
1637  // WdfDevStatePwrPolStartedIdleCapableWaitForIdleTimeout
1638  { NULL,
1640  NULL,
1641  { TRUE,
1642  0 },
1643  },
1644 
1645  // WdfDevStatePwrPolDeviceD0PowerRequestFailed
1648  NULL,
1649  { FALSE,
1650  0 },
1651  },
1652 
1653  // WdfDevStatePwrPolDevicePowerRequestFailed
1657  { TRUE,
1658  PwrPolUsbSelectiveSuspendCompleted | // Device was suspened and surprise
1659  // removed while in Dx
1660  PwrPolS0 | // If the device failed D0Exit while the machine was going into
1661  // Sx, then we will get this event when the machine comes back up
1662 
1663  PwrPolWakeArrived | // wake was completed before PwrPolWakeArrived was
1664  // sent. On immediate power down or up, the power
1665  // operation failed
1666 
1667  PwrPolWakeFailed | // If the device failed exit d0 after being armed, the
1668  // this event will be processed in the failed state
1669  PwrPolDevicePowerRequired | // We can drop because we already declared ourselves
1670  // as being powered on (fake power-on in order to
1671  // move the power framework to consistent state).
1672  PwrPolIoPresent // We're being notified that we need to be powered-on because
1673  // there is I/O to process, but the device is already in failed
1674  // state and is about to be removed.
1675  },
1676  },
1677 
1678  // State exists only for the non power policy owner state machine
1679  // WdfDevStatePwrPolGotoDx
1680  { NULL,
1682  NULL,
1683  { TRUE,
1684  0 },
1685  },
1686 
1687  // WdfDevStatePwrPolGotoDxInDx
1688  { NULL,
1690  NULL,
1691  { TRUE,
1692  0 },
1693  },
1694 
1695  // State exists only for the non power policy owner state machine
1696  // WdfDevStatePwrPolDx
1697  { NULL,
1699  NULL,
1700  { TRUE,
1701  0 },
1702  },
1703 
1704  // State exists only for the non power policy owner state machine
1705  // WdfDevStatePwrPolGotoD0
1706  { NULL,
1708  NULL,
1709  { TRUE,
1710  0 },
1711  },
1712 
1713  // WdfDevStatePwrPolGotoD0InD0
1714  { NULL,
1716  NULL,
1717  { TRUE,
1718  0 },
1719  },
1720 
1721  // WdfDevStatePwrPolFinal
1722  { NULL,
1724  NULL,
1725  { TRUE,
1726  0 },
1727  },
1728 
1729  // WdfDevStatePwrPolSleepingPowerDownNotProcessed
1732  NULL,
1733  { FALSE,
1734  0 },
1735  },
1736 
1737  // WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownNotProcessed
1740  NULL,
1741  { FALSE,
1742  0 },
1743  },
1744 
1745  // WdfDevStatePwrPolTimerExpiredNoWakePowerDownNotProcessed
1748  NULL,
1749  { FALSE,
1750  0 },
1751  },
1752 
1753  // WdfDevStatePwrPolTimerExpiredNoWakePoweredDownDisableIdleTimer
1756  NULL,
1757  { FALSE,
1758  0 },
1759  },
1760 
1761  // WdfDevStatePwrPolStoppingWaitingForImplicitPowerDown
1762  { NULL,
1764  NULL,
1765  { FALSE,
1766  0 },
1767  },
1768 
1769  // WdfDevStatePwrPolStoppingPoweringUp
1770  { NULL,
1772  NULL,
1773  { FALSE,
1774  0 },
1775  },
1776 
1777  // WdfDevStatePwrPolStoppingPoweringDown
1778  { NULL,
1780  NULL,
1781  { FALSE,
1782  0 },
1783  },
1784 
1785  // WdfDevStatePwrPolPowerUpForSystemSleepNotSeen
1788  NULL,
1789  { FALSE,
1790  0 },
1791  },
1792 
1793  // WdfDevStatePwrPolWaitingArmedStoppingCancelUsbSS
1796  NULL,
1797  { FALSE,
1798  PwrPolWakeFailed | // wake completed before we could cancel
1799  // the request, so the event may end up here
1800  PwrPolWakeSuccess // -do-
1801  },
1802  },
1803 
1804  // WdfDevStatePwrPolWaitingArmedWakeFailedCancelUsbSS
1807  NULL,
1808  { FALSE,
1809  0 },
1810  },
1811 
1812  // WdfDevStatePwrPolWaitingArmedIoPresentCancelUsbSS
1815  NULL,
1816  { FALSE,
1817  PwrPolWakeFailed | // wake completed before we could cancel
1818  // the request, so the event may end up here
1819  PwrPolWakeSuccess | // -do-
1820  PwrPolWakeInterruptFired // wake interrupt fired as we were waking the
1821  // device on receiving IO.This event can fire
1822  // until the wake interrupt machine is notified
1823  // of the power up.
1824  },
1825  },
1826 
1827  // WdfDevStatePwrPolWaitingArmedWakeSucceededCancelUsbSS
1830  NULL,
1831  { FALSE,
1832  0 },
1833  },
1834 
1835  // WdfDevStatePwrPolCancelingUsbSSForSystemSleep
1838  NULL,
1839  { FALSE,
1840  PwrPolWakeFailed | // wake completed before we could cancel
1841  // the request, so the event may end up here
1842  PwrPolWakeSuccess // -do-
1843  },
1844  },
1845 
1846  // WdfDevStatePwrPolStoppingD0CancelUsbSS
1849  NULL,
1850  { FALSE,
1851  PwrPolWakeFailed | // wake completed before we could cancel
1852  // the request, so the event may end up here
1853  PwrPolWakeSuccess // -do-
1854  },
1855  },
1856 
1857  // WdfDevStatePwrPolStartingPoweredUp
1860  NULL,
1861  { FALSE,
1862  0 },
1863  },
1864 
1865  // WdfDevStatePwrPolIdleCapableDeviceIdle
1869  { TRUE,
1870  0 },
1871  },
1872 
1873  // WdfDevStatePwrPolDeviceIdleReturnToActive
1876  NULL,
1877  { FALSE,
1878  0 },
1879  },
1880 
1881  // WdfDevStatePwrPolDeviceIdleSleeping
1884  NULL,
1885  { FALSE,
1886  0 },
1887  },
1888 
1889  // WdfDevStatePwrPolDeviceIdleStopping
1892  NULL,
1893  { FALSE,
1894  0 },
1895  },
1896 
1897  // WdfDevStatePwrPolTimerExpiredNoWakeUndoPowerDown
1900  NULL,
1901  { FALSE,
1902  0 },
1903  },
1904 
1905  // WdfDevStatePwrPolWakeCapableDeviceIdle
1909  { TRUE,
1910  PwrPolDevicePowerRequired // The device-power-required event arrived, but we had already
1911  // powered-up the device proactively because we detected that
1912  // power was needed. And after we powered up, we become idle
1913  // again and arrived in our current state before the device-
1914  // power-required event was received. The event is ignored in
1915  // this case.
1916  },
1917  },
1918 
1919  // WdfDevStatePwrPolWakeCapableUsbSSCompleted
1922  NULL,
1923  { FALSE,
1924  0 },
1925  },
1926 
1927  // WdfDevStatePwrPolTimerExpiredWakeCapableUndoPowerDown
1930  NULL,
1931  { FALSE,
1932  0 },
1933  },
1934 
1935  // WdfDevStatePwrPolTimerExpiredWakeCompletedHardwareStarted
1938  NULL,
1939  { FALSE,
1940  0 },
1941  },
1942 
1943  // WdfDevStatePwrPolStoppedRemoving
1946  NULL,
1947  { FALSE,
1948  0 },
1949  },
1950 
1951  // WdfDevStatePwrPolRemoved
1955  { TRUE,
1956  PwrPolSx | // device is disabled (must be a PDO) and then the machine
1957  // moves into an Sx state
1958  PwrPolS0 | // driver failed power up when moving out of S0 Dx idle
1959  // state and system resumed after failure
1960  PwrPolS0IdlePolicyChanged // driver changes S0 idle settings while being
1961  // removed
1962  },
1963  },
1964 
1965  // WdfDevStatePwrPolRestarting
1969  { FALSE,
1970  0 },
1971  },
1972 
1973  // WdfDevStatePwrPolRestartingFailed
1976  NULL,
1977  { FALSE,
1978  0 },
1979  },
1980 
1981  // WdfDevStatePwrPolStartingPoweredUpFailed
1984  NULL,
1985  { FALSE,
1986  0 },
1987  },
1988 
1989  // WdfDevStatePwrPolTimerExpiredNoWakeReturnToActive
1992  NULL,
1993  { FALSE,
1994  0 },
1995  },
1996 
1997  // WdfDevStatePwrPolWaitingArmedWakeInterruptFired
2001  { FALSE,
2002  0 },
2003  },
2004 
2005  // WdfDevStatePwrPolSystemWakeDeviceWakeInterruptFired
2009  { FALSE,
2010  0 },
2011  },
2012 
2013  // WdfDevStatePwrPolSystemWakeDeviceWakeInterruptFiredNP
2017  { FALSE,
2018  0 },
2019  },
2020 
2021  // WdfDevStatePwrPolTimerExpiredWakeCapableWakeInterruptArrived
2025  { FALSE,
2026  0 },
2027  },
2028 
2029  // WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedWakeInterruptArrived
2030  { NULL,
2033  { FALSE,
2034  0 },
2035  },
2036 
2037  // WdfDevStatePwrPolWaitingArmedWakeInterruptFiredDuringPowerDown
2038  { NULL,
2041  { FALSE,
2042  0 },
2043  },
2044 
2045  // WdfDevStatePwrPolNull
2046  // *** no entry for this state ***
2047 };
2048 
2049 // @@SMVERIFY_SPLIT_END
2050 
2051 VOID
2053  VOID
2054  )
2055 /*++
2056 
2057 Routine Description:
2058  This routine is never actually called by running code, it just has
2059  WDFCASSERTs who upon failure, would not allow this file to be compiled.
2060 
2061  DO NOT REMOVE THIS FUNCTION just because it is not callec by any running
2062  code.
2063 
2064 Arguments:
2065  None
2066 
2067 Return Value:
2068  None
2069 
2070  --*/
2071 {
2072  WDFCASSERT(sizeof(FxPwrPolStateInfo) == sizeof(ULONG));
2073 
2075  ==
2077 
2078  // we assume these are the same length when we update the history index
2080  sizeof(m_PowerPolicyMachine.m_Queue[0]))
2081  ==
2083  sizeof(m_PowerPolicyMachine.m_States.History[0])));
2084 }
2085 
2086 CfxDevice *
2088  VOID
2089  )
2090 {
2091  IdlePolicySettings * idlePolicySettings = NULL;
2092  FxPowerPolicyOwnerSettings * ppoSettings = NULL;
2093  FxPkgPnp * pPkgPnp = NULL;
2094 
2095  idlePolicySettings = (IdlePolicySettings *) CONTAINING_RECORD(
2096  this,
2098  m_TimeoutMgmt
2099  );
2101  idlePolicySettings,
2103  m_IdleSettings
2104  );
2105  pPkgPnp = ppoSettings->m_PkgPnp;
2106 
2107  return pPkgPnp->GetDevice();
2108 }
2109 
2113  )
2114 {
2115  LONG idleTimeoutStatusSnapshot;
2116  LONG updatedIdleTimeoutStatus;
2117  LONG preInterlockedIdleTimeoutStatus;
2118 
2119  //
2120  // Take a snapshot of the idle timeout management status
2121  //
2122  idleTimeoutStatusSnapshot = m_IdleTimeoutStatus;
2123 
2124  //
2125  // Verify that the flag we're trying to set is not already set
2126  //
2127  if (0 != (idleTimeoutStatusSnapshot & Flag)) {
2129  }
2130 
2131  //
2132  // Verify that the idle timeout management status is not already
2133  // "frozen"
2134  //
2135  if (0 != (idleTimeoutStatusSnapshot & IdleTimeoutStatusFrozen)) {
2136  //
2137  // It was too late to set the flag. The flag value was already
2138  // "frozen".
2139  //
2141  }
2142 
2143  //
2144  // Try to set the flag
2145  //
2146  updatedIdleTimeoutStatus = idleTimeoutStatusSnapshot | Flag;
2147 
2148  preInterlockedIdleTimeoutStatus = InterlockedCompareExchange(
2150  updatedIdleTimeoutStatus,
2151  idleTimeoutStatusSnapshot
2152  );
2153  if (preInterlockedIdleTimeoutStatus != idleTimeoutStatusSnapshot) {
2154 
2155  if (0 != (preInterlockedIdleTimeoutStatus &
2157  //
2158  // It was too late to set the flag. The flag value was already
2159  // "frozen".
2160  //
2162  }
2163  else {
2164  //
2165  // Idle timeout management status is being changed by multiple
2166  // threads in parallel. This is not supported.
2167  //
2169  }
2170  }
2171 
2172  //
2173  // We have successfully set the flag
2174  //
2176 }
2177 
2178 NTSTATUS
2181  )
2182 {
2183  NTSTATUS status;
2184  IdleTimeoutStatusUpdateResult statusUpdateResult;
2185  CfxDevice * device;
2186 
2187  //
2188  // First check if we are running on Windows 8 or above
2189  //
2191 
2192  //
2193  // Get the device object so we can use it for logging
2194  //
2195  device = GetDevice();
2196 
2197  //
2198  // Try to update the flag that specifies that the power framework should
2199  // determine the idle timeout.
2200  //
2201  statusUpdateResult = UpdateIdleTimeoutStatus(IdleTimeoutSystemManaged);
2202 
2203  switch (statusUpdateResult) {
2205  {
2206  //
2207  // Status is already frozen. Too late to update it.
2208  //
2212  "WDFDEVICE %p !devobj %p If the power framework is made "
2213  "responsible for determining the idle timeout, then the "
2214  "first call to assign S0-idle policy must occur before the "
2215  "first start IRP is completed. However, in this case, it "
2216  "occurred after the first start IRP was completed. "
2217  "%!STATUS!.",
2218  device->GetHandle(),
2219  device->GetDeviceObject(),
2220  status
2221  );
2223  }
2224  break;
2225 
2227  {
2228  //
2229  // Status being updated from multiple threads in parallel. Not
2230  // supported.
2231  //
2235  "WDFDEVICE %p !devobj %p Calls to assign S0-idle settings "
2236  "and to specify power framework settings are happening in "
2237  "parallel. The driver needs to serialize these calls with "
2238  "respect to each other. %!STATUS!.",
2239  device->GetHandle(),
2240  device->GetDeviceObject(),
2241  status
2242  );
2244  }
2245  break;
2246 
2248  {
2249  //
2250  // Status flag was already set. This should never happen for the
2251  // IdleTimeoutSystemManaged flag. The caller ensures this.
2252  //
2253  ASSERTMSG(
2254  "IdleTimeoutManagement::UseSystemManagedIdleTimeout was "
2255  "called more than once\n", FALSE);
2256  }
2257 
2258  //
2259  // Fall through
2260  //
2261  // || || ||
2262  // \/ \/ \/
2263  //
2265  {
2267  }
2268  break;
2269 
2270  default:
2271  {
2272  ASSERTMSG("Unexpected IdleTimeoutStatusUpdateResult value\n",
2273  FALSE);
2275  }
2276  }
2277 
2278  } else {
2279  //
2280  // If we're not running on Windows 8 or above, then there is nothing to
2281  // do.
2282  //
2284  }
2285 
2286  return status;
2287 }
2288 
2289 VOID
2292  )
2293 {
2294  LONG idleTimeoutSnapshot;
2295  LONG idleTimeoutStatus;
2296  LONG idleTimeoutPreviousStatus;
2297  CfxDevice * device;
2298 
2299  //
2300  // Get the device object so we can use it for logging
2301  //
2302  device = GetDevice();
2303 
2304  //
2305  // Take a snapshot of the idle timeout management status
2306  //
2307  idleTimeoutSnapshot = m_IdleTimeoutStatus;
2308 
2309  //
2310  // Set the bit that freezes the status
2311  //
2312  idleTimeoutStatus = idleTimeoutSnapshot | IdleTimeoutStatusFrozen;
2313 
2314  //
2315  // Update the status
2316  //
2317  idleTimeoutPreviousStatus = InterlockedExchange(&m_IdleTimeoutStatus,
2318  idleTimeoutStatus);
2319 
2320  if (idleTimeoutPreviousStatus != idleTimeoutSnapshot) {
2321  //
2322  // An update of idle timeout status is racing with the freezing of idle
2323  // timeout status
2324  //
2327  "WDFDEVICE %p !devobj %p The driver's S0-idle settings and/or power"
2328  " framework settings did not take effect because they were supplied"
2329  " too late. The driver must ensure that the settings are provided "
2330  "before the first start IRP is completed.",
2331  device->GetHandle(),
2332  device->GetDeviceObject()
2333  );
2335  }
2336 
2337  //
2338  // If the driver has specified power framework settings and system managed
2339  // idle timeout is available on this OS, then the driver must have opted for
2340  // system managed idle timeout.
2341  //
2342  if ((0 != (idleTimeoutStatus & IdleTimeoutPoxSettingsSpecified)) &&
2344  (0 == (idleTimeoutStatus & IdleTimeoutSystemManaged))) {
2347  "WDFDEVICE %p !devobj %p The driver specified power framework "
2348  "settings, but did not opt for system-managed idle timeout.",
2349  device->GetHandle(),
2350  device->GetDeviceObject()
2351  );
2353  }
2354 }
2355 
2356 BOOLEAN
2358  VOID
2359  )
2360 {
2361  //
2362  // If the value of this constant is changed, the debugger extension needs
2363  // to be fixed as well.
2364  //
2366 
2368 }
2369 
2370 BOOLEAN
2372  VOID
2373  )
2374 {
2376 }
2377 
2378 NTSTATUS
2381  __in PPOX_SETTINGS PoxSettings
2382  )
2383 {
2384  NTSTATUS status;
2385  IdleTimeoutStatusUpdateResult statusUpdateResult;
2386  PVOID oldPoxSettings = NULL;
2387  BOOLEAN settingsSuccessfullySaved = FALSE;
2388  CfxDevice * device;
2389 
2390  //
2391  // We should never get here if system-managed idle timeout is not available
2392  //
2394 
2395  //
2396  // Get the device object so we can use it for logging
2397  //
2398  device = GetDevice();
2399 
2400  //
2401  // Try to save the driver's power framework settings
2402  //
2404  PoxSettings,
2405  NULL // Comparand
2406  );
2407  if (NULL != oldPoxSettings) {
2408  //
2409  // The driver's power framework settings have already been specified
2410  // earlier. The driver should not be attempting to specify them more
2411  // than once.
2412  //
2416  "WDFDEVICE %p !devobj %p The driver attempted to specify power "
2417  "framework settings more than once. %!STATUS!.",
2418  device->GetHandle(),
2419  device->GetDeviceObject(),
2420  status
2421  );
2423  goto exit;
2424  }
2425  settingsSuccessfullySaved = TRUE;
2426 
2427  //
2428  // Try to update the flag that indicates that the client driver has
2429  // specified settings that are to be used when we register with the power
2430  // framework.
2431  //
2432  statusUpdateResult = UpdateIdleTimeoutStatus(
2434  );
2435  switch (statusUpdateResult) {
2437  {
2438  //
2439  // Status is already frozen. Too late to update it.
2440  //
2444  "WDFDEVICE %p !devobj %p Power framework settings must be "
2445  "specified before the first start IRP is completed. %!STATUS!.",
2446  device->GetHandle(),
2447  device->GetDeviceObject(),
2448  status
2449  );
2451  goto exit;
2452  }
2453  break;
2454 
2456  {
2457  //
2458  // Status being updated from multiple threads in parallel. Not
2459  // supported.
2460  //
2464  "WDFDEVICE %p !devobj %p Calls to assign S0-idle settings and "
2465  "to specify power framework settings are happening in parallel."
2466  " The driver needs to serialize these calls with respect to "
2467  "each other. %!STATUS!.",
2468  device->GetHandle(),
2469  device->GetDeviceObject(),
2470  status
2471  );
2473  goto exit;
2474  }
2475  break;
2476 
2478  {
2479  //
2480  // Status flag was already set. This should never happen for the
2481  // IdleTimeoutPoxSettingsSpecified flag because we have logic in the
2482  // beginning of this function to ensure that only the first caller
2483  // attempts to set this flag.
2484  //
2485  ASSERTMSG(
2486  "Attempt to set the IdleTimeoutPoxSettingsSpecified flag more "
2487  "than once\n", FALSE);
2489  goto exit;
2490  }
2491 
2493  {
2495  }
2496  break;
2497 
2498  default:
2499  {
2500  ASSERTMSG("Unexpected IdleTimeoutStatusUpdateResult value\n",
2501  FALSE);
2503  goto exit;
2504  }
2505  }
2506 
2507  //
2508  // If we get here, we must have a successful status
2509  //
2511 
2512 exit:
2513  if (FALSE == NT_SUCCESS(status)) {
2514  if (settingsSuccessfullySaved) {
2515  //
2516  // Since a failure has occurred, we must reset the pointer to the
2517  // power framework settings.
2518  //
2519  m_PoxSettings = NULL;
2520  }
2521  }
2522  return status;
2523 }
2524 
2526 {
2527 
2528 
2529 
2530 
2531 
2532 
2533 
2534 }
2535 
2537  VOID
2539 {
2540  m_Owner = NULL;
2541 
2542  RtlZeroMemory(&m_Queue[0], sizeof(m_Queue));
2543  RtlZeroMemory(&m_States, sizeof(m_States));
2544 
2546 
2548 }
2549 
2551  VOID
2552  )
2553 {
2554  if (m_Owner != NULL) {
2555  delete m_Owner;
2556  m_Owner = NULL;
2557  }
2558 }
2559 
2561 NTSTATUS
2563  VOID
2564  )
2565 {
2566  FxUsbIdleInfo* pInfo;
2567  NTSTATUS status;
2568 
2569  //
2570  // The field is already set, we are good to go
2571  //
2572  if (m_Owner->m_UsbIdle != NULL) {
2573  return STATUS_SUCCESS;
2574  }
2575 
2576  pInfo = new (m_PkgPnp->GetDriverGlobals()) FxUsbIdleInfo(m_PkgPnp);
2577 
2578  if (pInfo == NULL) {
2580  }
2581 
2582  status = pInfo->Initialize();
2583  if (!NT_SUCCESS(status)) {
2584  delete pInfo;
2585  return status;
2586  }
2587 
2589  pInfo,
2590  NULL) == NULL) {
2591  //
2592  // This thread was the one that set the field value.
2593  //
2594  DO_NOTHING();
2595  }
2596  else {
2597  //
2598  // Another thread raced in and beat this thread in setting the field,
2599  // just delete our allocation and use the other allocated FxUsbIdleInfo.
2600  //
2601  delete pInfo;
2602  }
2603 
2604  return STATUS_SUCCESS;
2605 }
2606 
2608  __in FxPkgPnp* PkgPnp
2609  ) : m_PoxInterface(PkgPnp)
2610 {
2611  ULONG i;
2612 
2613  m_UsbIdle = NULL;
2614 
2615  m_PkgPnp = PkgPnp;
2616 
2617  //
2618  // Default every state to D3 except for system working which is D0 by
2619  // default.
2620  //
2622 
2623  for (i = 0; i < PowerSystemMaximum; i++) {
2626  : PowerDeviceD3,
2628  }
2629 
2631 
2636  m_PowerFailed = FALSE;
2637  m_CanSaveState = TRUE;
2638 
2642 
2646 
2649 }
2650 
2652  VOID
2653  )
2654 {
2655  //
2656  // There are paths which cleanup this object which do not go through the
2657  // pnp state machine, so make sure the power object callback fields are
2658  // freed. In these paths, we are guaranteed PASSIVE_LEVEL b/c there will
2659  // be no dangling references which can cause deletion at a greater IRQL.
2660  //
2662 
2663  if (m_UsbIdle != NULL) {
2664  delete m_UsbIdle;
2665  m_UsbIdle = NULL;
2666  }
2667 }
2668 
2669 VOID
2671  VOID
2672  )
2673 /*++
2674 
2675 Routine Description:
2676  Cleans up the power state callback registration for this object.
2677 
2678 Arguments:
2679  None
2680 
2681 Return Value:
2682  None
2683 
2684  --*/
2685 {
2689 
2690  }
2691 
2692  if (m_PowerCallbackObject != NULL) {
2695  }
2696 }
2697 
2699 NTSTATUS
2701  VOID
2702  )
2703 /*++
2704 
2705 Routine Description:
2706  Initialize the object. We will try to register a power state callback so
2707  that we can be informed of when the machine is changing S states. We are
2708  interested in system state changes because we need to know when NOT to write
2709  to the registry (to save wake settings) so that we don't cause a deadlock
2710  in a non power pageable device while moving into Sx.
2711 
2712 Arguments:
2713  None
2714 
2715 Return Value:
2716  NTSTATUS
2717 
2718  --*/
2719 {
2720  OBJECT_ATTRIBUTES oa;
2722  NTSTATUS status;
2723 
2724  RtlInitUnicodeString(&string, L"\\Callback\\PowerState");
2726  &oa,
2727  &string,
2729  NULL,
2730  NULL
2731  );
2732 
2733  //
2734  // Create a callback object, but we do not want to be the first ones
2735  // to create it (it should be created way before we load in NTOS
2736  // anyways)
2737  //
2739 
2740  if (NT_SUCCESS(status)) {
2744  this
2745  );
2746 
2748  //
2749  // Non-critical failure, so we'll free the callback object and keep
2750  // going
2751  //
2754  }
2755  }
2756 
2757  //
2758  // Initialize FxPowerIdleMachine
2759  //
2761  if (!NT_SUCCESS(status)) {
2762  return status;
2763  }
2764 
2765  return status;
2766 }
2767 
2768 VOID
2770  __in PVOID Context,
2773  )
2774 /*++
2775 
2776 Routine Description:
2777  Callback invoked by the power subsystem when the system is changing S states
2778 
2779 Arguments:
2780  Context - FxPowerPolicyOwnerSettings pointer (the "this" pointer)
2781 
2782  Argument1 - Reason why the callback was invoked, we only care about
2783  PO_CB_SYSTEM_STATE_LOCK
2784 
2785  Argument2 - State transition that is occurring
2786 
2787 Return Value:
2788  None
2789 
2790  --*/
2791 {
2793 
2795 
2797  return;
2798  }
2799 
2800  pThis->m_PkgPnp->m_PowerPolicyMachine.m_StateMachineLock.AcquireLock(
2801  pThis->m_PkgPnp->GetDriverGlobals(),
2802  NULL
2803  );
2804 
2805  if (Argument2 == (PVOID) 0) {
2806  //
2807  // Write out the state if necessary before we turn off the paging path.
2808  //
2809  pThis->m_PkgPnp->SaveState(TRUE);
2810 
2811  //
2812  // Exiting S0
2813  //
2814  pThis->m_CanSaveState = FALSE;
2815  }
2816  else if (Argument2 == (PVOID) 1) {
2817  //
2818  // We have reentered S0
2819  //
2820  pThis->m_CanSaveState = TRUE;
2821 
2822  //
2823  // Write out the state if necessary now that the paging path is back
2824  //
2825  pThis->m_PkgPnp->SaveState(TRUE);
2826  }
2827 
2828  pThis->m_PkgPnp->m_PowerPolicyMachine.m_StateMachineLock.ReleaseLock(
2829  pThis->m_PkgPnp->GetDriverGlobals()
2830  );
2831 }
2832 
2833 /*++
2834 
2835 The locking model for the Power policy state machine requires that events be enqueued
2836 possibly at DISPATCH_LEVEL. It also requires that the state machine be
2837 runnable at PASSIVE_LEVEL. Consequently, we have two locks, one DISPATCH_LEVEL
2838 lock that guards the event queue and one PASSIVE_LEVEL lock that guards the
2839 state machine itself.
2840 
2841 The Power policy state machine has a few constraints that the PnP state machine
2842 doesn't. Sometimes it has to call some driver functions at PASSIVE_LEVEL, but
2843 with the disks turned off. This means that these functions absolutely must not
2844 page fault. You might think that this means that we should call the driver at
2845 DISPATCH_LEVEL, and you'd be right if your only concern were for perfectly
2846 safe code. The problem with that approach, though is that it will force much
2847 of the rest of the driver to DISPATCH_LEVEL, which will only push the driver
2848 writer into using lots of asynchronous work items, which will complicate their
2849 code and make it unsafe in a new variety of ways. So we're going to go with
2850 PASSIVE_LEVEL here and setting a timeout of 20 seconds. If the driver faults,
2851 the timer will fire and log the failure. This also means that the driver must
2852 complete these callbacks within 20 seconds. Even beyond that, it means that
2853 the work items must be queued onto a special thread, one that once the machine
2854 has started to go to sleep, never handles any work items that may fault.
2855 
2856 Algorithm:
2857 
2858 1) Acquire the Power policy queue lock.
2859 2) Enqueue the event. events are put at the end of the queue.
2860 3) Drop the Power policy queue lock.
2861 4) If the thread is running at PASSIVE_LEVEL, skip to step 6.
2862 5) Queue a work item onto the special power thread.
2863 6) Attempt to acquire the state machine lock, with a zero-length timeout (*).
2864 7) If successful, skip to step 9.
2865 8) Queue a work item onto the special power thread.
2866 9) Acquire the state machine lock.
2867 10) Acquire the Power policy queue lock.
2868 11) Attempt to dequeue an event.
2869 12) Drop the Power policyqueue lock.
2870 13) If there was no event to dequeue, drop the state machine lock and exit.
2871 14) Execute the state handler. This may involve taking one of the other state
2872  machine queue locks, briefly, to deliver an event.
2873 15) Go to Step 10.
2874 
2875 (*) zero length is different then NULL (infinite) being passed for the timeout
2876 
2877 Implementing this algorithm requires three functions.
2878 
2879 PowerPolicyProcessEvent -- Implements steps 1-8.
2880 _PowerPolicyProcessEventInner -- Implements step 9.
2881 PowerPolicyProcessEventInner -- Implements steps 10-15.
2882 
2883 --*/
2884 
2885 VOID
2888  __in BOOLEAN ProcessOnDifferentThread
2889  )
2890 /*++
2891 
2892 Routine Description:
2893  This function implements steps 1-8 of the algorithm described above.
2894 
2895 Arguments:
2896  Event - Current Power event
2897 
2898 Return Value:
2899 
2900  NTSTATUS
2901 
2902 --*/
2903 {
2904  NTSTATUS status;
2905  ULONG mask;
2906  KIRQL irql;
2907 
2908  //
2909  // Take the lock, raising to DISPATCH_LEVEL.
2910  //
2911  m_PowerPolicyMachine.Lock(&irql);
2912 
2913  //
2914  // If the input Event is any of the events described by PowerSingularEventMask,
2915  // then check whether it is already queued up. If so, then dont enqueue this
2916  // Event.
2917  //
2921  }
2922  else {
2925  "WDFDEVICE 0x%p !devobj 0x%p current pwr pol state "
2926  "%!WDF_DEVICE_POWER_POLICY_STATE! dropping event "
2927  "%!FxPowerPolicyEvent! because the Event is already enqueued.",
2928  m_Device->GetHandle(),
2931 
2932  m_PowerPolicyMachine.Unlock(irql);
2933  return;
2934  }
2935  }
2936 
2937  if (m_PowerPolicyMachine.IsFull()) {
2938  //
2939  // The queue is full. Bail.
2940  //
2941  m_PowerPolicyMachine.Unlock(irql);
2942 
2943  ASSERT(!"The Power queue is full. This shouldn't be able to happen.");
2944  return;
2945  }
2946 
2950  "WDFDEVICE 0x%p !devobj 0x%p current pwr pol state "
2951  "%!WDF_DEVICE_POWER_POLICY_STATE! dropping event "
2952  "%!FxPowerPolicyEvent! because of a closed queue",
2953  m_Device->GetHandle(),
2956 
2957  //
2958  // The queue is closed. Bail
2959  //
2960  m_PowerPolicyMachine.Unlock(irql);
2961 
2962  return;
2963  }
2964 
2965  //
2966  // Enqueue the event. Whether the event goes on the front
2967  // or the end of the queue depends on which event it is and if we are the
2968  // PPO or not.
2969  //
2970  // Yes, mask could be a member variable of m_PowerPolicyMachine, but why
2971  // waste 4 bytes when it is very easy to figure out?
2972  //
2975 
2976  if (Event & mask) {
2977  //
2978  // Stick it on the front of the queue, making it the next event that
2979  // will be processed if, otherwise let these events go by.
2980  //
2982  }
2983  else {
2984  //
2985  // Stick it on the end of the queue.
2986  //
2988  }
2989 
2990  //
2991  // Drop the lock.
2992  //
2993  m_PowerPolicyMachine.Unlock(irql);
2994 
2995  //
2996  // Now, if we are running at PASSIVE_LEVEL, attempt to run the state
2997  // machine on this thread. If we can't do that, then queue a work item.
2998  //
3000  irql,
3001  ProcessOnDifferentThread
3002  )) {
3003 
3004  LONGLONG timeout = 0;
3005 
3008 
3009  if (FxWaitLockInternal::IsLockAcquired(status)) {
3011 
3012  //
3013  // We now hold the state machine lock. So call the function that
3014  // dispatches the next state.
3015  //
3017 
3018  //
3019  // The pnp state machine should be the only one deleting the object
3020  //
3021  ASSERT(info.m_DeleteObject == FALSE);
3022 
3024  GetDriverGlobals());
3025 
3026  info.Evaluate(this);
3027 
3028  return;
3029  }
3030  }
3031 
3032  //
3033  // The tag added above will be released when the work item runs
3034  //
3035 
3036  //
3037  // For one reason or another, we couldn't run the state machine on this
3038  // thread. So queue a work item to do it. If m_PnPWorkItemEnqueuing
3039  // is non-zero, that means that the work item is already being enqueued
3040  // on another thread. This is significant, since it means that we can't do
3041  // anything with the work item on this thread, but it's okay, since the
3042  // work item will pick up our work and do it.
3043  //
3045 }
3046 
3047 VOID
3052  )
3053 {
3054 
3056 
3057  //
3058  // Take the state machine lock.
3059  //
3060  This->m_PowerPolicyMachine.m_StateMachineLock.AcquireLock(
3061  This->GetDriverGlobals()
3062  );
3063 
3064  //
3065  // Call the function that will actually run the state machine.
3066  //
3067  This->PowerPolicyProcessEventInner(Info);
3068 
3069  //
3070  // We are being called from the work item and m_WorkItemRunning is > 0, so
3071  // we cannot be deleted yet.
3072  //
3073  ASSERT(Info->SomethingToDo() == FALSE);
3074 
3075  //
3076  // Now release the lock
3077  //
3078  This->m_PowerPolicyMachine.m_StateMachineLock.ReleaseLock(
3079  This->GetDriverGlobals()
3080  );
3081 }
3082 
3083 VOID
3086  )
3087 {
3090  ULONG i;
3091  KIRQL irql;
3092 
3093  if (IsPowerPolicyOwner()) {
3095 
3096  //
3097  // Process as many events as we can.
3098  //
3099  for ( ; ; ) {
3101 
3102  //
3103  // Get an event from the queue.
3104  //
3105  m_PowerPolicyMachine.Lock(&irql);
3106 
3107  if (m_PowerPolicyMachine.IsEmpty()) {
3109 
3110  //
3111  // The queue is empty.
3112  //
3113  m_PowerPolicyMachine.Unlock(irql);
3114  return;
3115  }
3116 
3118 
3119  //
3120  // At this point, we need to determine whether we can process this
3121  // event.
3122  //
3124  //
3125  // These are always possible to handle.
3126  //
3127  DO_NOTHING();
3128  }
3129  else {
3130  //
3131  // Check to see if this state can handle new events, ie if this
3132  // is a green dot (queue open) or red dot (queue *not* open) state.
3133  //
3134  if (entry->StateInfo.Bits.QueueOpen == FALSE) {
3135  //
3136  // This state can't handle new events.
3137  //
3138  m_PowerPolicyMachine.Unlock(irql);
3139  return;
3140  }
3141  }
3142 
3143  //
3144  // If the event obtained from the queue was a singular event, then
3145  // clear the flag to allow other similar events to be put into this
3146  // queue for processing.
3147  //
3150  }
3151 
3153  m_PowerPolicyMachine.Unlock(irql);
3154 
3155  //
3156  // Find the entry in the power policy state table that corresponds
3157  // to this event.
3158  //
3159  newState = WdfDevStatePwrPolNull;
3160 
3161  if (entry->FirstTargetState.PowerPolicyEvent == event) {
3162  newState = entry->FirstTargetState.TargetState;
3163 
3164  DO_EVENT_TRAP(&entry->FirstTargetState);
3165  }
3166  else if (entry->OtherTargetStates != NULL) {
3167  for (i = 0;
3168  entry->OtherTargetStates[i].PowerPolicyEvent != PwrPolNull;
3169  i++) {
3170  if (entry->OtherTargetStates[i].PowerPolicyEvent == event) {
3171  newState = entry->OtherTargetStates[i].TargetState;
3172  DO_EVENT_TRAP(&entry->OtherTargetStates[i]);
3173  break;
3174  }
3175  }
3176  }
3177 
3178  if (newState == WdfDevStatePwrPolNull) {
3179  //
3180  // This state doesn't respond to the event. Just throw the event
3181  // away.
3182  //
3185  "WDFDEVICE 0x%p !devobj 0x%p current pwr pol state "
3186  "%!WDF_DEVICE_POWER_POLICY_STATE! dropping event "
3187  "%!FxPowerPolicyEvent!", m_Device->GetHandle(),
3190 
3191  if ((entry->StateInfo.Bits.KnownDroppedEvents & event) == 0) {
3192  COVERAGE_TRAP();
3193 
3196  "WDFDEVICE 0x%p !devobj 0x%p current state "
3197  "%!WDF_DEVICE_POWER_POLICY_STATE!, policy event "
3198  "%!FxPowerPolicyEvent! is not a known dropped "
3199  "event, known dropped events are %!FxPowerPolicyEvent!",
3202  event, entry->StateInfo.Bits.KnownDroppedEvents);
3203 
3204 
3205  }
3206 
3207  //
3208  // Failsafes for events which have required processing in them.
3209  //
3210  switch (event) {
3211  case PwrPolSx:
3212  //
3213  // The Sx handling code expects that the state machine
3214  // complete the Sx irp. (S0 irps are never pended). Since
3215  // we don't have a state to transition to that will complete
3216  // the request, do so now.
3217  //
3218  // (This can legitimately happen if a PDO is disabled and
3219  // the machines moves into an Sx state.)
3220  //
3222  break;
3223 
3225  //
3226  // This state did not handle the event and event got
3227  // dropped. However some state is definitely going to wait
3228  // for this event. That's why we need m_EventDropped flag.
3229  // If we didn't have this flag there will be no way to know
3230  // if the event got dropped and some state will end up
3231  // waiting for it indefinitely.
3232  //
3234  break;
3235 
3238  break;
3239 
3240  case PwrPolWakeSuccess:
3241  case PwrPolWakeFailed:
3242  //
3243  // This state did not handle the event and event got
3244  // dropped. However some state is definitely going to wait
3245  // for this event. That's why we need
3246  // m_WakeCompletionEventDropped flag. If we didn't have this
3247  // flag there will be no way to know if the event got
3248  // dropped and some state will end up waiting for it
3249  // indefinitely.
3250  //
3252  break;
3253 
3254  default:
3255  DO_NOTHING();
3256  break;
3257  }
3258  }
3259  else {
3260  //
3261  // Now enter the new state.
3262  //
3263  PowerPolicyEnterNewState(newState);
3264  }
3265  }
3266  }
3267  else {
3268  //
3269  // Process as many events as we can.
3270  //
3271  for ( ; ; ) {
3273 
3274 #pragma prefast(suppress:__WARNING_DEREF_NULL_PTR, "The current power policy state will always be in the table so entry will never be NULL")
3277  );
3278 
3279  //
3280  // Get an event from the queue.
3281  //
3282  m_PowerPolicyMachine.Lock(&irql);
3283 
3284  if (m_PowerPolicyMachine.IsEmpty()) {
3285  //
3286  // The queue is empty.
3287  //
3288  m_PowerPolicyMachine.Unlock(irql);
3289  return;
3290  }
3291 
3293 
3294  //
3295  // At this point, we need to determine whether we can process this
3296  // event.
3297  //
3299  //
3300  // These are always possible to handle.
3301  //
3302  DO_NOTHING();
3303  }
3304  else {
3305  //
3306  // Check to see if this state can handle new events, ie if this
3307  // is a green dot (queue open) or red dot (queue *not* open) state.
3308  //
3309  if (entry->QueueOpen == FALSE) {
3310  //
3311  // This state can't handle new events.
3312  //
3313  m_PowerPolicyMachine.Unlock(irql);
3314  return;
3315  }
3316  }
3317 
3318  //
3319  // If the event obtained from the queue was a singular event, then
3320  // clear the flag to allow other similar events to be put into this
3321  // queue for processing.
3322  //
3325  }
3326 
3328  m_PowerPolicyMachine.Unlock(irql);
3329 
3330  if (entry != NULL && entry->TargetStatesCount > 0) {
3331  for (i = 0; i < entry->TargetStatesCount; i++) {
3332  if (event == entry->TargetStates[i].PowerPolicyEvent) {
3333  DO_EVENT_TRAP(&entry->TargetStates[i]);
3334 
3335  //
3336  // Now enter the new state.
3337  //
3339  entry->TargetStates[i].TargetState);
3340  break;
3341  }
3342  }
3343  }
3344  }
3345  }
3346 }
3347 
3348 VOID
3351  )
3352 /*++
3353 
3354 Routine Description:
3355  This function looks up the handler for a state and then calls it.
3356 
3357 Arguments:
3358  Event - Current power plicy event
3359 
3360 Return Value:
3361 
3362  NTSTATUS
3363 
3364 --*/
3365 {
3367  WDF_DEVICE_POWER_POLICY_STATE currentState, newState;
3369  FxWatchdog watchdog(this);
3370 
3371  currentState = m_Device->GetDevicePowerPolicyState();
3372  newState = NewState;
3373 
3374  while (newState != WdfDevStatePwrPolNull) {
3377  "WDFDEVICE 0x%p !devobj 0x%p entering power policy state "
3378  "%!WDF_DEVICE_POWER_POLICY_STATE! from "
3379  "%!WDF_DEVICE_POWER_POLICY_STATE!", m_Device->GetHandle(),
3380  m_Device->GetDeviceObject(), newState, currentState);
3381 
3383  //
3384  // Callback for leaving the old state
3385  //
3386  RtlZeroMemory(&data, sizeof(data));
3387 
3389  data.Data.LeaveState.CurrentState = currentState;
3390  data.Data.LeaveState.NewState = newState;
3391 
3392  m_PowerPolicyStateCallbacks->Invoke(currentState,
3394  m_Device->GetHandle(),
3395  &data);
3396  }
3397 
3400 
3402  //
3403  // Callback for entering the new state
3404  //
3405  RtlZeroMemory(&data, sizeof(data));
3406 
3408  data.Data.EnterState.CurrentState = currentState;
3409  data.Data.EnterState.NewState = newState;
3410 
3413  m_Device->GetHandle(),
3414  &data);
3415  }
3416 
3418  currentState = newState;
3419 
3420  entry = GetPowerPolicyTableEntry(currentState);
3421 
3422  //
3423  // And call the state handler, if there is one.
3424  //
3425  if (entry->StateFunc != NULL) {
3426  watchdog.StartTimer(currentState);
3427  newState = entry->StateFunc(this);
3428  watchdog.CancelTimer(currentState);
3429 
3430  //
3431  // Validate the return value if FX_STATE_MACHINE_VERIFY is enabled
3432  //
3433  VALIDATE_PWR_POL_STATE(currentState, newState);
3434 
3435  }
3436  else {
3437  newState = WdfDevStatePwrPolNull;
3438  }
3439 
3441  //
3442  // Callback for post processing the new state
3443  //
3444  RtlZeroMemory(&data, sizeof(data));
3445 
3447  data.Data.PostProcessState.CurrentState = currentState;
3448 
3449  m_PowerPolicyStateCallbacks->Invoke(currentState,
3451  m_Device->GetHandle(),
3452  &data);
3453  }
3454  }
3455 }
3456 
3457 
3458 /*++
3459 
3460 One of the goals of the Driver Framework is to make it really easy to write
3461 a driver for a device which keeps the device in the lowest useful power state
3462 at all times. This could (and often does) mean that the device remains in the
3463 D0 state whenever the machine is running. Or it could mean that the device is
3464 only in D0 when there are outstanding IRPs in its queues. Or it could mean
3465 that the device is in D0 whenever the driver explicitly says that it has to be.
3466 
3467 Consequently, the Power Policy state machine has a bunch of states that relate
3468 only to managing the state of the device while the system is running, possibly
3469 allowing the device to "idle-out" to low power states while it isn't being
3470 heavily used. Once that idle-out process has begun, there needs to be some
3471 way for the Framework I/O Package and the driver itself to tell the Power Policy
3472 engine that the device must, for some time at least, be in the D0 (high-power,
3473 working) state. The problem is made much harder by the fact that the driver
3474 (or the Framework itself) probably has to stall some operation while the device
3475 is brought back into the D0 state.
3476 
3477 So we've created two operations, PowerReference and PowerDereference, which
3478 tell the Power Policy state machine when a device needs to be in the D0 state.
3479 The I/O Package uses these internally, and the driver may as well. We want
3480 these operations to be as light-weight as possible, so that a driver never
3481 experiences meaningful degradation in performance simply because it chose to
3482 be a good electricity consumer and enabled idle-time power management.
3483 Fortunately, the Framework I/O package can significantly reduce the number of
3484 times that it needs to call these functions by only calling them when the
3485 queue state transitions from empty to non-empty or back again. A caller within
3486 the driver itself will need to be aware that their usage can be somewhat
3487 expensive.
3488 
3489 Furthermore, these functions need to be callable at both PASSIVE_LEVEL and
3490 DISPATCH_LEVEL. This really necessitates two versions, as a PASSIVE_LEVEL
3491 user within the driver probably would like us to block while the device is
3492 moved into D0, while a DISPATCH_LEVEL user (or the Framework I/O package) would
3493 prefer a much more asynchronous mode of use.
3494 
3495 Dealing with these multiple modes involves a fairly complex locking scheme. Here
3496 is a statement of algorithm.
3497 
3498 Locks:
3499 
3500 A) Idle Transition Spinlock - DISPATCH_LEVEL
3501 B) Device in D0 Notification Event - PASSIVE_LEVEL
3502 
3503 Device-wide variables:
3504 
3505  I) Power Reference Count - number of outstanding reasons to be in D0.
3506  II) Idle Timout -- value set by the driver which governs the idle timer
3507 III) Transitioning -- boolean indicating whether we're in the process of
3508  moving the device from Dx to D0.
3509 
3510 PowerDecrement:
3511 
3512 1) Take Idle Transition lock.
3513 3) Decrement of the device-wide power reference count.
3514 3) If that's not zero, drop the lock and exit.
3515 4) Set the driver's Idle Timer.
3516 5) Drop the Idle Transition lock.
3517 
3518 PowerIncrement:
3519 
3520  1) Take Idle Transition lock.
3521  2) Increment of the device-wide power reference count.
3522  3) If that's 1, then we're transitioning out of idle. Goto Step 6.
3523  4) If Transitioning == TRUE, we need to wait, Goto Step 13.
3524  5) Drop the Idle Transition lock. Exit.
3525  6) Cancel the Idle Timer. If that was unsuccessful, then the timer was not
3526  set, which means that the device has either moved out of D0 or it is moving
3527  out of D0. Goto Step 8.
3528  7) Drop the Idle Transition lock. Exit.
3529  8) The timer was not succefully cancelled. This means that we have timed out
3530  in the past and we need to put the device back in D0.
3531  Set Transitioning = TRUE.
3532  9) Drop Idle Transition lock.
3533 10) Reset the D0 Notification Event.
3534 11) Send IoPresent event to the Power Policy state machine.
3535 12) If IRQL == DISPATCH_LEVEL goto Step 15.
3536 13) Wait for the D0 Notification Event.
3537 14) Exit.
3538 15) Note that I/O needs to be restarted later.
3539 16) Exit STATUS_PENDING.
3540 
3541 --*/
3545  )
3546 {
3548 
3549  This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.Start();
3550 
3551  This->PowerProcessEvent(PowerImplicitD0);
3552 
3553  //
3554  // Wait for the successful power up before starting any idle timers. If
3555  // the power up fails, we will not send a power policy stop from the pnp
3556  // engine.
3557  //
3558  return WdfDevStatePwrPolNull;
3559 }
3560 
3564  )
3565 /*++
3566 
3567 Routine Description:
3568  The power state policy state machine has powered up. Tell the active/idle
3569  state machine to initialize.
3570 
3571  The device needs to be in D0 before the active/idle state machine registers
3572  with the power framework. Therefore, we wait until the power state machine
3573  has brought the device into D0 before we tell the active/idle state machine
3574  to start. Moving the device into D0 allows us to touch hardware if needed
3575  (for example, to determine the number of components in the device) before
3576  registering with the power framework.
3577 
3578 Arguments:
3579  This - instance of the state machine
3580 
3581 Return Value:
3582  WdfDevStatePwrPolNull
3583 
3584 --*/
3585 {
3586  NTSTATUS status;
3588 
3589  //
3590  // The decision regarding whether or not the power framework determines the
3591  // idle timeout is now "frozen" and cannot be changed unless the device is
3592  // stopped and restarted.
3593  //
3594  This->m_PowerPolicyMachine.m_Owner->
3595  m_IdleSettings.m_TimeoutMgmt.FreezeIdleTimeoutManagementStatus(
3596  This->GetDriverGlobals()
3597  );
3598 
3599  status = This->m_PowerPolicyMachine.m_Owner->
3600  m_PoxInterface.InitializeComponents();
3601  if (FALSE == NT_SUCCESS(status)) {
3603  }
3604 
3606 }
3607 
3611  )
3612 /*++
3613 
3614 Routine Description:
3615  We failed to initialize the device's components. We have already started the
3616  power state machine, so ask it to run down before we tell the PNP state
3617  machine to fail device start.
3618 
3619 Arguments:
3620  This - instance of the state machine
3621 
3622 Return Value:
3623  WdfDevStatePwrPolNull
3624 
3625 --*/
3626 {
3628 
3629  This->PowerProcessEvent(PowerImplicitD3);
3630 
3631  return WdfDevStatePwrPolNull;
3632 }
3633 
3637  )
3638 /*++
3639 
3640 Routine Description:
3641  The power policy state machine has successfully started. Notify the pnp
3642  state machine that this has occurred and then tell the active/idle state
3643  machine to move to an active state.
3644 
3645 Arguments:
3646  This - instance of the state machine
3647 
3648 Return Value:
3649  WdfDevStatePwrPolStartingDecideS0Wake
3650 
3651  --*/
3652 {
3654 
3655  This->PnpProcessEvent(PnpEventPwrPolStarted);
3656 
3658 }
3659 
3663  )
3664 /*++
3665 
3666 Routine Description:
3667  Attempting to bring the device into the D0 state failed. Report the status
3668  to pnp.
3669 
3670 Arguments:
3671  This - instance of the state machine
3672 
3673 Return Value
3674  WdfDevStatePwrPolNull
3675 
3676  --*/
3677 {
3678  KIRQL irql;
3679 
3681 
3682  This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.Stop();
3683 
3684  //
3685  // We raise IRQL to dispatch level so that pnp is forced onto its own thread
3686  // to process the PwrPolStartFailed event. If pnp is on the power thread when
3687  // it processes the event and it tries to delete the dedicated thread, it
3688  // will deadlock waiting for the thread its on to exit.
3689  //
3690  Mx::MxRaiseIrql(DISPATCH_LEVEL, &irql);
3691  This->PnpProcessEvent(PnpEventPwrPolStartFailed);
3692  Mx::MxLowerIrql(irql);
3693 
3694  return WdfDevStatePwrPolNull;
3695 }
3696 
3700  )
3701 {
3703 
3704  This->PowerPolicyChildrenCanPowerUp();
3705 
3706  //
3707  // Save idle state if it is dirty. We check when deciding the S0 state
3708  // because any change in the S0 idle settings will go through this state.
3709  //
3710  This->SaveState(TRUE);
3711 
3712  //
3713  // If necessary update the idle timeout hint to the power framework
3714  //
3715  This->m_PowerPolicyMachine.m_Owner->m_PoxInterface.UpdateIdleTimeoutHint();
3716 
3717  if (This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.Enabled) {
3718  if (This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.WakeFromS0Capable) {
3719  //
3720  // We can idle out and wake from S0
3721  //
3723  }
3724  else {
3725  //
3726  // We can idle out, but not wake from the idle state
3727  //
3729  }
3730  }
3731 
3732  return WdfDevStatePwrPolStarted;
3733 }
3734 
3738  )
3739 {
3741 
3742  //
3743  // Enable the idle state machine. This will release any threads who are
3744  // waiting for the device to return to D0.
3745  //
3746  This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.EnableTimer();
3747 
3748  return WdfDevStatePwrPolNull;
3749 }
3750 
3754  )
3755 /*++
3756 
3757 Routine Description:
3758  We are now idle. Tell the active/idle state machine to move us to an idle
3759  state.
3760 
3761 Arguments:
3762  This - instance of the state machine
3763 
3764 Return Value:
3765  WdfDevStatePwrPolNull
3766 
3767  --*/
3768 {
3769  BOOLEAN canPowerDown;
3771 
3772  canPowerDown = This->m_PowerPolicyMachine.m_Owner->
3773  m_PoxInterface.DeclareComponentIdle();
3774 
3775  //
3776  // If we are using driver-managed idle timeout we can power down immediately
3777  // and so we jump to the next state (that initiates power down) immediately.
3778  // If we are using system-managed idle timeout, we wait in the current state
3779  // for device-power-not-required notification.
3780  //
3781  return (canPowerDown ?
3784 }
3785 
3789  )
3790 /*++
3791 
3792 Routine Description:
3793  We are idle, but still in D0. We need to return to an active state.
3794 
3795 Arguments:
3796  This - instance of the state machine
3797 
3798 Return Value:
3799  WdfDevStatePwrPolNull
3800 
3801  --*/
3802 {
3804 
3805  This->m_PowerPolicyMachine.m_Owner->
3806  m_PoxInterface.RequestComponentActive();
3807 
3809 }
3810 
3814  )
3815 /*++
3816 
3817 Routine Description:
3818  We are idle, but still in D0. System is going to a low power state.
3819 
3820 Arguments:
3821  This - instance of the state machine
3822 
3823 Return Value:
3824  WdfDevStatePwrPolNull
3825 
3826  --*/
3827 {
3829 
3830  //
3831  // Normally we'd make the component active when we get the device-power-
3832  // required notification. But we've not yet processed the device-power-not-
3833  // required notification, so we will not be processing the device-power-
3834  // required notification either. So let's activate the component before we
3835  // process the Sx IRP.
3836  //
3837  This->m_PowerPolicyMachine.m_Owner->
3838  m_PoxInterface.RequestComponentActive();
3839 
3841 }
3842 
3846  )
3847 /*++
3848 
3849 Routine Description:
3850  We are idle, but still in D0. Power policy state machine is being stopped.
3851 
3852 Arguments:
3853  This - instance of the state machine
3854 
3855 Return Value:
3856  WdfDevStatePwrPolNull
3857 
3858  --*/
3859 {
3861 
3862  //
3863  // Normally we'd make the component active when we get the device-power-
3864  // required notification. But we've not yet processed the device-power-not-
3865  // required notification, so we will not be processing the device-power-
3866  // required notification either. So let's activate the component before we
3867  // process the stop/remove request.
3868  //
3869  This->m_PowerPolicyMachine.m_Owner->
3870  m_PoxInterface.RequestComponentActive();
3871 
3873 }
3874 
3878  )
3879 {
3880  BOOLEAN poweredDown;
3881  NTSTATUS notifyPowerDownStatus;
3882 
3884 
3885  //
3886  // Notify the device power requirement state machine that we are about to
3887  // power down.
3888  //
3889  notifyPowerDownStatus = This->m_PowerPolicyMachine.m_Owner->
3890  m_PoxInterface.NotifyDevicePowerDown();
3891  if (FALSE == NT_SUCCESS(notifyPowerDownStatus)) {
3892  //
3893  // We couldn't notify the device power requirement state machine that
3894  // we are about to power down, because the "device-power-required"
3895  // notification has already arrived. So we should not power down at this
3896  // time. Revert back to the started state.
3897  //
3899  }
3900 
3901  poweredDown = This->PowerPolicyCanIdlePowerDown(
3902  This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.DxState
3903  );
3904 
3905  if (poweredDown == FALSE) {
3906  //
3907  // Upon failure, revert back to the started state.
3908  //
3910  }
3911 
3912  return WdfDevStatePwrPolNull;
3913 }
3914 
3918  )
3919 /*++
3920 
3921 Routine Description:
3922  The device idled out and we sent the Dx request. The power state machine has
3923  gone as far as stopping I/O is waiting to be notified to complete the Dx
3924  process. Send the PowerCompleteDx event to move the device fully into Dx.
3925 
3926 Arguments:
3927  This - instance of the state machine
3928 
3929 Return Value:
3930  WdfDevStatePwrPolNull
3931 
3932  --*/
3933 {
3936 
3937  This->PowerProcessEvent(PowerCompleteDx);
3938 
3939  return WdfDevStatePwrPolNull;
3940 }
3941 
3945  )
3946 /*++
3947 
3948 Routine Description:
3949  The device was in the WaitingUnarmed state and received a PwrPolIoPresent
3950  event. Before committing the device to move back to D0, check to see if
3951  the device has returned to an idle state. This can easily happen if the
3952  driver causes a power reference in D0Exit accidentally and the power
3953  reference is removed before exiting the function.
3954 
3955 Arguments:
3956  This - instance of the state machine
3957 
3958 Return Value:
3959  new state
3960 
3961  --*/
3962 {
3964 
3965  //
3966  // If QueryReturnToIdle returns TRUE, return to the waiting state
3967  //
3968  if (This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.QueryReturnToIdle()) {
3970  }
3971  else {
3973  }
3974 }
3975 
3979  )
3980 {
3981  NTSTATUS status;
3982 
3984 
3985  //
3986  // Attempt to get back to the D0 state
3987  //
3988  This->m_PowerPolicyMachine.m_Owner->
3989  m_PoxInterface.RequestComponentActive();
3990  status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
3991 
3992  if (!NT_SUCCESS(status)) {
3993  COVERAGE_TRAP();
3995  }
3996 
3997  return WdfDevStatePwrPolNull;
3998 }
3999 
4003  )
4004 /*++
4005 
4006 Routine Description:
4007  The device was in a Dx unarmed for wake while in S0 and is now being brought
4008  into the D0 state. The device is currently in a partial D0 state (HW
4009  started), move it into the full D0 state by sending PowerCompleteD0 to the
4010  power state machine.
4011 
4012 Arguments:
4013  This - instance of the state machine
4014 
4015 Return Value:
4016  WdfDevStatePwrPolNull
4017 
4018  --*/
4019 {
4021 
4022  This->m_PowerPolicyMachine.m_Owner->
4023  m_PoxInterface.DeviceIsPoweredOn();
4024 
4025  This->PowerProcessEvent(PowerCompleteD0);
4026 
4027  return WdfDevStatePwrPolNull;
4028 }
4029 
4033  )
4034 {
4035  SYSTEM_POWER_STATE systemState;
4036 
4039 
4040  systemState = This->PowerPolicyGetPendingSystemState();
4041 
4042  if (This->PowerPolicyIsWakeEnabled() &&
4043  This->PowerPolicyCanWakeFromSystemState(systemState)) {
4045  }
4046  else {
4048  }
4049 }
4050 
4054  )
4055 {
4056  NTSTATUS status;
4057  BOOLEAN result;
4058 
4060 
4061  result = This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.DisableTimer();
4062  ASSERT(result);
4064 
4065  status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
4066 
4067  //
4068  // We are currently in Dx and not armed for wake. While the current Dx
4069  // state may not be the same Dx state we would be for Sx, we can't get to
4070  // D0 to arm ourselves for Sx wake so just leave ourselves as is.
4071  //
4072  if (!NT_SUCCESS(status)) {
4074  This->GetDriverGlobals(), TRACE_LEVEL_WARNING, TRACINGPNP,
4075  "Failed to allocate D0 request to disarm from wake from S0 to allow "
4076  "arm for wake from Sx, %!STATUS!", status);
4077 
4078  COVERAGE_TRAP();
4079 
4080  //
4081  // If D0 IRP allocation fails, we don't treat that as an error. Instead,
4082  // we just let the device remain in Dx without arming it for
4083  // wake-from-Sx, even though the driver had enabled wake-from-Sx.
4084  //
4086  }
4087 
4088  return WdfDevStatePwrPolNull;
4089 }
4090 
4094  )
4095 /*++
4096 
4097 Routine Description:
4098  The machine is going into Sx while the device was in Dx. We have started
4099  the D0 process. The power state machine has moved the device into the HW
4100  working state and is waiting to be notified to complete the D0 process.
4101  Send the PowerCompleteD0 event to complete it.
4102 
4103 Arguments:
4104  This - instance of the state machine
4105 
4106 Return Value:
4107  WdfDevStatePwrPolNull
4108 
4109  --*/
4110 {
4113 
4114  This->PowerProcessEvent(PowerCompleteD0);
4115 
4116  return WdfDevStatePwrPolNull;
4117 }
4118 
4122  )
4123 /*++
4124 
4125 Routine Description:
4126  Power up failed in the power state machine. Complete the pending system
4127  power irp with success (system ignores the results) even if the Dx irp
4128  failed.
4129 
4130 Arguments:
4131  This - instance of the state machine
4132 
4133 Return Value:
4134  new state WdfDevStatePwrPolDevicePowerRequestFailed
4135 
4136  --*/
4137 {
4139 
4140  This->PowerPolicyCompleteSystemPowerIrp();
4141 
4143 }
4144 
4148  )
4149 /*++
4150 
4151 Routine Description:
4152  Checks to see if the device should move down the power pagable wake path
4153  or the NP path.
4154 
4155 Arguments:
4156  This - instance of the state machine
4157 
4158 Return Value:
4159  new state
4160 
4161  --*/
4162 {
4163  ULONG flags;
4165 
4167 
4168  deviceObject.SetObject(This->m_Device->GetDeviceObject());
4170 
4171  if (flags & DO_POWER_PAGABLE) {
4172  ASSERT((flags & DO_POWER_INRUSH) == 0);
4173 
4175  }
4176  else {
4177  //
4178  // DO_POWER_INRUSH also gets us to this state, but since it is mutually
4179  // exclusive with DO_POWER_PAGABLE, we don't need to check for it
4180  //
4182  }
4183 }
4184 
4188  )
4189 /*++
4190 
4191 Routine Description:
4192  The device is in partial Dx (I/O has stopped) and will now be armed for wake.
4193  Complete the going Dx transition by sending a PowerCompleteDx irp to the
4194 
4195 Arguments:
4196  This - instance of the state machine
4197 
4198 Return Value:
4199  new state
4200 
4201  --*/
4202 {
4203  NTSTATUS status;
4204  ULONG wakeReason;
4205 
4208 
4209  ASSERT(This->PowerPolicyCanWakeFromSystemState(
4210  This->PowerPolicyGetPendingSystemState()
4211  ));
4212 
4213  wakeReason = This->PowerPolicyGetCurrentWakeReason();
4214 
4215  status = This->m_PowerPolicyMachine.m_Owner->m_DeviceArmWakeFromSx.Invoke(
4216  This->m_Device->GetHandle(),
4219  );
4220 
4221  if (!NT_SUCCESS(status)) {
4223  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
4224  "WDFDEVICE %p Failed to arm for wake from Sx, %!STATUS!",
4225  This->m_Device->GetHandle(), status);
4226 
4228  }
4229 
4230  //
4231  // If the PDO is the Power Policy owner, then enable wake at bus, otherwise
4232  // the power state machine will enable wake at bus.
4233  //
4234  if (This->m_Device->IsPdo()) {
4235  status = This->PowerEnableWakeAtBusOverload();
4236  if (!NT_SUCCESS(status)) {
4238  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
4239  "WDFDEVICE %p Failed to Enable Wake at Bus, %!STATUS!",
4240  This->m_Device->GetHandle(), status);
4242  }
4243  }
4244 
4245  This->PowerProcessEvent(PowerCompleteDx);
4246 
4247  return WdfDevStatePwrPolNull;
4248 }
4249 
4253  )
4254 {
4257 
4259  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
4260  "reverting arm for wake from Sx due to failure to allocate wait wake "
4261  "request or wait wake request completed immeidately. Device will *NOT* "
4262  "be armed for wake from Sx");
4263 
4264  //
4265  // Enable calls should be matched with Disable calls even in the failure
4266  // cases. However, for the Enable wake at bus failure, we do not call the
4267  // disable wake at bus method as we try to keep the failure behavior
4268  // consistent with the Power State machine. Only the Device Disarm wake
4269  // callback will be invoked here.
4270  //
4271  This->PowerPolicyDisarmWakeFromSx();
4272 
4273  //
4274  // attempt to cancel ww
4275  //
4276  if (This->PowerPolicyCancelWaitWake() == FALSE &&
4277  This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
4279  }
4280 
4281  return WdfDevStatePwrPolNull;
4282 }
4283 
4287  )
4288 {
4290  This->PowerPolicyCompleteSystemPowerIrp();
4291 
4292  return WdfDevStatePwrPolNull;
4293 }
4294 
4298  )
4299 {
4302 
4303  if (This->PowerPolicyCancelWaitWake() == FALSE &&
4304  This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
4306  }
4307 
4308  return WdfDevStatePwrPolNull;
4309 }
4310 
4314  )
4315 {
4318 
4319  //
4320  // Make a note of the fact that system was woken by
4321  // a wake interrupt of this device
4322  //
4323  This->m_SystemWokenByWakeInterrupt = TRUE;
4324 
4325  if (This->PowerPolicyCancelWaitWake() == FALSE &&
4326  This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
4327 
4329  }
4330 
4331  return WdfDevStatePwrPolNull;
4332 }
4333 
4337  )
4338 {
4339  NTSTATUS status;
4340 
4343 
4344  status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
4345 
4346  if (!NT_SUCCESS(status)) {
4347  COVERAGE_TRAP();
4349  }
4350 
4351  return WdfDevStatePwrPolNull;
4352 }
4353 
4357  )
4358 {
4361 
4362  //
4363  // If the PDO is the Power Policy owner, then disable wake at bus, otherwise
4364  // the power state machine will disable wake at bus.
4365  //
4366  if (This->m_Device->IsPdo()) {
4367  This->PowerDisableWakeAtBusOverload();
4368  }
4369 
4370  This->PowerPolicyDisarmWakeFromSx();
4371 
4373 }
4374 
4378  )
4379 {
4380  NTSTATUS status;
4381 
4384 
4385  status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
4386 
4387  if (!NT_SUCCESS(status)) {
4388  COVERAGE_TRAP();
4390  }
4391 
4392  return WdfDevStatePwrPolNull;
4393 }
4394 
4398  )
4399 {
4402 
4403  //
4404  // If the PDO is the Power Policy owner, then disable wake at bus, otherwise
4405  // the power state machine will enable wake at bus.
4406  //
4407  if (This->m_Device->IsPdo()) {
4408  This->PowerDisableWakeAtBusOverload();
4409  }
4410 
4411  This->m_PowerPolicyMachine.m_Owner->m_DeviceWakeFromSxTriggered.Invoke(
4412  This->m_Device->GetHandle()
4413  );
4414 
4415  This->PowerPolicyDisarmWakeFromSx();
4416 
4418 }
4419 
4423  )
4424 /*++
4425 
4426 Routine Description:
4427  The device is in partial Dx (I/O has stopped) and will now be armed for wake.
4428  Complete the going Dx transition by sending a PowerCompleteDx irp to the
4429  power state machine.
4430 
4431 Arguments:
4432  This - instance of the state machine
4433 
4434 Return Value:
4435  new state
4436 
4437  --*/
4438 {
4439  NTSTATUS status;
4440  ULONG wakeReason;
4441 
4444 
4445  ASSERT(This->PowerPolicyCanWakeFromSystemState(
4446  This->PowerPolicyGetPendingSystemState()
4447  ));
4448 
4449  wakeReason = This->PowerPolicyGetCurrentWakeReason();
4450 
4451  status = This->m_PowerPolicyMachine.m_Owner->m_DeviceArmWakeFromSx.Invoke(
4452  This->m_Device->GetHandle(),
4455  );
4456 
4457  if (!NT_SUCCESS(status)) {
4459  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
4460  "WDFDEVICE %p Failed to arm for wake from Sx, %!STATUS!",
4461  This->m_Device->GetHandle(), status);
4462 
4464  }
4465 
4466  //
4467  // If the PDO is the Power Policy owner, then enable wake at bus, otherwise
4468  // the power state machine will enable wake at bus.
4469  //
4470  if (This->m_Device->IsPdo()) {
4471  status = This->PowerEnableWakeAtBusOverload();
4472  if (!NT_SUCCESS(status)) {
4474  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
4475  "WDFDEVICE %p Failed to Enable Wake at Bus, %!STATUS!",
4476  This->m_Device->GetHandle(), status);
4478  }
4479  }
4480 
4481  This->PowerProcessEvent(PowerCompleteDx);
4482 
4483  return WdfDevStatePwrPolNull;
4484 }
4485 
4489  )
4490 {
4493 
4495  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
4496  "reverting arm for wake from Sx due to failure to allocate wait wake "
4497  "request or wait wake request completed immeidately. Device will *NOT* "
4498  "be armed for wake from Sx");
4499 
4500  //
4501  // Enable calls should be matched with Disable calls even in the failure
4502  // cases. However, for the Enable wake at bus failure, we do not call the
4503  // disable wake at bus method as we try to keep the failure behavior
4504  // consistent with the Power State machine. Only the Device Disarm wake
4505  // callback will be invoked here.
4506  //
4507  This->PowerPolicyDisarmWakeFromSx();
4508 
4509  //
4510  // attempt to cancel ww
4511  //
4512  if (This->PowerPolicyCancelWaitWake() == FALSE &&
4513  This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
4515  }
4516 
4517  return WdfDevStatePwrPolNull;
4518 }
4519 
4523  )
4524 /*++
4525 
4526 Routine Description:
4527  Power down failed in the power state machine. Cancel the wait wake irp
4528  that was just sent down and revert the arming before moving to the failed
4529  state.
4530 
4531 Arguments:
4532  This - instance of the state machine.
4533 
4534 Return Value:
4535  new state
4536 
4537  --*/
4538 {
4541 
4542  if (This->PowerPolicyCancelWaitWake() == FALSE &&
4543  This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
4545  }
4546 
4547  return WdfDevStatePwrPolNull;
4548 }
4549 
4553  )
4554 /*++
4555 
4556 Routine Description:
4557  Wait wake irp has been cancelled. Complete the Sx irp and goto the failed
4558  state.
4559 
4560 Arguments:
4561  This - instance of the state machine
4562 
4563 Return Value:
4564  new state
4565 
4566  --*/
4567 {
4570 
4571  This->PowerPolicyCompleteSystemPowerIrp();
4572 
4574 }
4575 
4579  )
4580 {
4582 
4583  This->PowerPolicyCompleteSystemPowerIrp();
4584 
4585  return WdfDevStatePwrPolNull;
4586 }
4587 
4591  )
4592 {
4594 
4595  if (This->PowerPolicyCancelWaitWake() == FALSE &&
4596  This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
4598  }
4599 
4600  return WdfDevStatePwrPolNull;
4601 }
4602 
4606  )
4607 {
4610 
4611  //
4612  // Make a notee of the fact that system was woken by
4613  // a wake interrupt of this device
4614  //
4615  This->m_SystemWokenByWakeInterrupt = TRUE;
4616 
4617  if (This->PowerPolicyCancelWaitWake() == FALSE &&
4618  This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
4620  }
4621 
4622  return WdfDevStatePwrPolNull;
4623 }
4624 
4628  )
4629 {
4630  NTSTATUS status;
4631 
4634 
4635  status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
4636 
4637  if (!NT_SUCCESS(status)) {
4638  COVERAGE_TRAP();
4640  }
4641 
4642  return WdfDevStatePwrPolNull;
4643 }
4644 
4648  )
4649 {
4651 
4652  //
4653  // If the PDO is the Power Policy owner, then disable wake at bus, otherwise
4654  // the power state machine will disable wake at bus.
4655  //
4656  if (This->m_Device->IsPdo()) {
4657  This->PowerDisableWakeAtBusOverload();
4658  }
4659 
4660  This->PowerPolicyDisarmWakeFromSx();
4661 
4663 }
4664 
4668  )
4669 {
4670  NTSTATUS status;
4671 
4673 
4674  status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
4675 
4676  if (!NT_SUCCESS(status)) {
4677  COVERAGE_TRAP();
4679  }
4680 
4681  return WdfDevStatePwrPolNull;
4682 }
4683 
4687  )
4688 {
4690 
4691  //
4692  // If the PDO is the Power Policy owner, then disable wake at bus, otherwise
4693  // the power state machine will disable wake at bus.
4694  //
4695  if (This->m_Device->IsPdo()) {
4696  This->PowerDisableWakeAtBusOverload();
4697  }
4698 
4699  This->m_PowerPolicyMachine.m_Owner->m_DeviceWakeFromSxTriggered.Invoke(
4700  This->m_Device->GetHandle()
4701  );
4702 
4703  This->PowerPolicyDisarmWakeFromSx();
4704 
4706 }
4707 
4711  )
4712 /*++
4713 
4714 Routine Description:
4715  The system went into Sx and the device was armed for wake. The system has
4716  now returned to S0, the device has started the D0 transition, and the device
4717  has been disarmed for wake. We must now complete the D0 transition by sending
4718  PowerCompleteD0 to the power state machine.
4719 
4720 Arguments:
4721  This - instance of the state machine
4722 
4723 Return Value:
4724  WdfDevStatePwrPolNull
4725 
4726  --*/
4727 {
4730 
4731  //
4732  // Simulate a device-power-required notification from the power framework.
4733  // An S0-IRP is essentially equivalent to a device-power-required
4734  // notification.
4735  //
4736  This->m_PowerPolicyMachine.m_Owner->
4737  m_PoxInterface.SimulateDevicePowerRequired();
4738 
4739  //
4740  // Notify the device-power-requirement state machine that we are powered on
4741  //
4742  This->m_PowerPolicyMachine.m_Owner->
4743  m_PoxInterface.DeviceIsPoweredOn();
4744 
4745  This->PowerProcessEvent(PowerCompleteD0);
4746 
4747  return WdfDevStatePwrPolNull;
4748 }
4749 
4753  )
4754 /*++
4755 
4756 Routine Description:
4757  The machine is going into Sx. Send a Dx irp to the stack. The "x" depends
4758  on if the target system state is one which we can wake the system and
4759  the device is enabled to wake from Sx.
4760 
4761 Arguments:
4762  This - instance of the state machine
4763 
4764 Return Value:
4765  new state
4766 
4767  --*/
4768 {
4769  NTSTATUS notifyPowerDownStatus;
4770  SYSTEM_POWER_STATE systemState;
4771 
4773 
4774  //
4775  // If the bus/PDO is not in the hibernate path, then verify that all the
4776  // children have powered down by now.
4777  //
4778  if (This->GetUsageCount(WdfSpecialFileHibernation) == 0 &&
4779  This->m_PowerPolicyMachine.m_Owner->m_ChildrenPoweredOnCount > 0) {
4781  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
4782  "WDFDEVICE %p powering down before child devices have powered down. "
4783  "This usually indicates a faulty child device that completed the Sx "
4784  "irp before sending the Dx irp",
4785  This->m_Device->GetHandle());
4786 
4788  This->m_Device->GetDriverGlobals());
4789  }
4790 
4791  //
4792  // Simulate a device-power-not-required notification from the power
4793  // framework. An Sx-IRP is essentially equivalent to a device-power-not-
4794  // required notification.
4795  //
4796  This->m_PowerPolicyMachine.m_Owner->
4797  m_PoxInterface.SimulateDevicePowerNotRequired();
4798 
4799  //
4800  // Notify the device-power-requirement state machine that we are about to
4801  // power down
4802  //
4803  notifyPowerDownStatus = This->m_PowerPolicyMachine.m_Owner->
4804  m_PoxInterface.NotifyDevicePowerDown();
4805 
4806  //
4807  // We simulated a device-power-not-required notification before we notified
4808  // the device-power-requirement state machine that we are powering down.
4809  // Therefore, our notification should have succeeded.
4810  //
4811  ASSERT(NT_SUCCESS(notifyPowerDownStatus));
4812  UNREFERENCED_PARAMETER(notifyPowerDownStatus);
4813 
4814  systemState = This->PowerPolicyGetPendingSystemState();
4815 
4816  if (This->PowerPolicyIsWakeEnabled() &&
4817  This->PowerPolicyCanWakeFromSystemState(systemState)) {
4819  }
4820  else {
4822  }
4823 }
4824 
4828  )
4829 /*++
4830 
4831 Routine Description:
4832  Machine is going into Sx and the device is not enabled to wake from Sx.
4833  Request a D3 irp to put the device into a low power state.
4834 
4835 Arguments:
4836  This - instance of the state machine
4837 
4838 Return Value:
4839  new state
4840 
4841  --*/
4842 {
4843  NTSTATUS status;
4844  DEVICE_POWER_STATE dxState;
4845 
4847 
4848  dxState = (DEVICE_POWER_STATE)
4849  This->m_PowerPolicyMachine.m_Owner->m_IdealDxStateForSx;
4850 
4851  if (dxState != PowerDeviceD3) {
4852  DEVICE_POWER_STATE dxMappedState;
4853 
4854  //
4855  // Get the lightest Dx state for this Sx state as reported by the
4856  // device capabilities of the stack.
4857  //
4858  dxMappedState = _GetPowerCapState(
4859  This->PowerPolicyGetPendingSystemState(),
4860  This->m_PowerPolicyMachine.m_Owner->m_SystemToDeviceStateMap
4861  );
4862 
4863  //
4864  // If the ideal desired state is lighter than what the S->D mapping says
4865  // is the lightest supported D state, use the mapping value instead.
4866  //
4867  if (dxState < dxMappedState) {
4868  dxState = dxMappedState;
4869  }
4870  }
4871 
4872  ASSERT(dxState >= PowerDeviceD1 && dxState <= PowerDeviceD3);
4873 
4874  status = This->PowerPolicyPowerDownForSx(dxState, Retry);
4875 
4876  if (!NT_SUCCESS(status)) {
4877  COVERAGE_TRAP();
4879  }
4880 
4881  return WdfDevStatePwrPolNull;
4882 }
4883 
4887  )
4888 /*++
4889 
4890 Routine Description:
4891  The system has moved into Sx and the device is not armed for wake. The
4892  device in partial Dx (I/O has stopped), transition the device into full
4893  Dx by sending the PowerCompleteDx event to the power state machine.
4894 
4895 Arguments:
4896  This - instance of the state machine
4897 
4898 Return Value:
4899  WdfDevStatePwrPolNull
4900 
4901  --*/
4902 {
4905 
4906  This->PowerProcessEvent(PowerCompleteDx);
4907 
4908  return WdfDevStatePwrPolNull;
4909 }
4910 
4914  )
4915 {
4916  COVERAGE_TRAP();
4917 
4919 
4920  This->SetInternalFailure();
4921  This->PowerPolicyCompleteSystemPowerIrp();
4922 
4923  if (FALSE == This->m_ReleaseHardwareAfterDescendantsOnFailure) {
4924  This->PnpProcessEvent(PnpEventPowerDownFailed);
4925  }
4926 
4928 }
4929 
4933  )
4934 /*++
4935 
4936 Routine Description:
4937  The system is going into Sx and the device is set to arm itself for wake from
4938  Sx. Start the power down process by requesting the Dx irp to stop I/O in
4939  the power state machine.
4940 
4941 Arguments:
4942  This - instance of the state machine
4943 
4944 Return Value:
4945  new state
4946 
4947  --*/
4948 {
4949  NTSTATUS status;
4950 
4952 
4953  status = This->PowerPolicyPowerDownForSx(
4954  This->m_PowerPolicyMachine.m_Owner->m_WakeSettings.DxState, NoRetry
4955  );
4956 
4957  if (!NT_SUCCESS(status)) {
4958  COVERAGE_TRAP();
4960  }
4961 
4962  return WdfDevStatePwrPolNull;
4963 }
4964 
4968  )
4969 /*++
4970 
4971 Routine Description:
4972  Machine is moving into an Sx state and the device is in a partial Dx (I/O
4973  stopped) state. Send a wait wake request so that the device can be armed
4974  for wake from Sx.
4975 
4976 Arguments:
4977  This - instance of the state machine
4978 
4979 Return Value:
4980  new state
4981 
4982  --*/
4983 {
4984  SYSTEM_POWER_STATE systemState;
4985  NTSTATUS status;
4986 
4988 
4989  //
4990  // We are in a wake-enabled path, keep wake interrupts connected.
4991  //
4992  This->m_WakeInterruptsKeepConnected = TRUE;
4993 
4994  //
4995  // We use the deepest possible Sx state instead of the current Sx state so
4996  // that we can handle the FastS4 case where PowerPolicyGetPendingSystemState
4997  // would return, but we could possible goto S4. By using the deepest
4998  // possible state, we can arm for any possible Sx state that we are capable
4999  // of waking from.
5000  //
5001  systemState = This->PowerPolicyGetDeviceDeepestSystemWakeState();
5002 
5003  status = This->PowerPolicySendWaitWakeRequest(systemState);
5004 
5005  if (!NT_SUCCESS(status)) {
5007  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
5008  "Attempting to send wait wake request for EvtDeviceArmWakeFromSx() "
5009  "failed, %!STATUS!", status);
5010 
5011  COVERAGE_TRAP();
5012 
5014  }
5015 
5016  return WdfDevStatePwrPolNull;
5017 }
5018 
5022  )
5023 {
5025 
5026  This->PowerPolicyCompleteSystemPowerIrp();
5027 
5028  return WdfDevStatePwrPolNull;
5029 }
5030 
5034  )
5035 /*++
5036 
5037 Routine Description:
5038  The machine is moving from Sx->S0 and the device was in Dx and not armed for
5039  wake from Sx. Determine if the device should remain in Dx after the machine
5040  has moved into S0.
5041 
5042 Arguments:
5043  This - instance of the state machine
5044 
5045 Return Value:
5046  new state
5047 
5048  --*/
5049 {
5051 
5052  //
5053  // We do not attempt to let the device remain in Dx if we are using system-
5054  // managed idle timeout. This is because an S0 IRP is equivalent to a
5055  // device-power-required notification from the power framework. In response
5056  // to it, we need to power up the device and notify the power framework that
5057  // the device is powered on.
5058  //
5059  if ((This->m_PowerPolicyMachine.m_Owner->
5060  m_IdleSettings.m_TimeoutMgmt.UsingSystemManagedIdleTimeout() == FALSE)
5061  &&
5062  (This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.Enabled)
5063  &&
5064  (This->m_PowerPolicyMachine.m_Owner->
5065  m_IdleSettings.WakeFromS0Capable == FALSE)
5066  &&
5067  (This->m_PowerPolicyMachine.m_Owner->
5068  m_IdleSettings.PowerUpIdleDeviceOnSystemWake == FALSE)) {
5069 
5071  }
5072  else {
5074  }
5075 }
5076 
5080  )
5081 {
5082  NTSTATUS status;
5083 
5085 
5086  status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
5087  if (!NT_SUCCESS(status)) {
5088  COVERAGE_TRAP();
5090  }
5091 
5092  return WdfDevStatePwrPolNull;
5093 }
5094 
5098  )
5099 /*++
5100 
5101 Routine Description:
5102  The machine was in Sx and the device was not armed for wake from Sx. The
5103  machine is moving back into S0 and the device is in partial D0 (HW has
5104  started). Move the device into full D0 by sending the PowerCompleteD0
5105  event to the power state machine.
5106 
5107 Arguments:
5108  This - instance of the state machine
5109 
5110 Return Value:
5111  WdfDevStatePwrPolNull
5112 
5113  --*/
5114 {
5117 
5118  //
5119  // Simulate a device-power-not-required notification from the power
5120  // framework. An S0-IRP is essentially equivalent to a device-power-required
5121  // notification.
5122  //
5123  This->m_PowerPolicyMachine.m_Owner->
5124  m_PoxInterface.SimulateDevicePowerRequired();
5125 
5126  //
5127  // Notify the device-power-requirement state machine that we are powered on
5128  //
5129  This->m_PowerPolicyMachine.m_Owner->
5130  m_PoxInterface.DeviceIsPoweredOn();
5131 
5132  This->PowerProcessEvent(PowerCompleteD0);
5133 
5134  return WdfDevStatePwrPolNull;
5135 }
5136 
5140  )
5141 {
5143 
5144  //
5145  // This state can be reached only if we are using driver-managed idle
5146  // timeout.
5147  //
5148  ASSERT(
5149  This->m_PowerPolicyMachine.m_Owner->
5150  m_IdleSettings.m_TimeoutMgmt.UsingSystemManagedIdleTimeout() == FALSE
5151  );
5152 
5153  if (This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.QueryReturnToIdle()) {
5155  }
5156  else {
5158  }
5159 }
5160 
5161 
5165  )
5166 {
5168 
5169  //
5170  // Enable the idle state machine. This will release any threads who are
5171  // waiting for the device to return to D0.
5172  //
5173  This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.EnableTimer();
5174 
5175  return WdfDevStatePwrPolNull;
5176 }
5177 
5181  )
5182 /*++
5183 
5184 Routine Description:
5185  We are now idle. Tell the active/idle state machine to move us to an idle
5186  state.
5187 
5188 Arguments:
5189  This - instance of the state machine
5190 
5191 Return Value:
5192  WdfDevStatePwrPolNull
5193 
5194  --*/
5195 {
5196  BOOLEAN canPowerDown;
5197 
5199 
5200  canPowerDown = This->m_PowerPolicyMachine.m_Owner->
5201  m_PoxInterface.DeclareComponentIdle();
5202 
5203  //
5204  // If we are using driver-managed idle timeout we can power down immediately
5205  // and so we jump to the next state (that initiates power down) immediately.
5206  // If we are using system-managed idle timeout, we wait in the current state
5207  // for device-power-not-required notification.
5208  //
5209  return (canPowerDown ?
5212 }
5213 
5217  )
5218 /*++
5219 
5220 Routine Description:
5221  Decides how to handle the idle timer firing. If the device is capable of
5222  USB selective suspend, it will move the machine into that path. Otherwise,
5223  the machine will be moved into the normal arm for wake while in D0 path.
5224 
5225 Arguments:
5226  This - instance of the state machine
5227 
5228 Return Value:
5229  WdfDevStatePwrPolTimerExpiredWakeCapableUsbSS
5230  or
5231  WdfDevStatePwrPolTimerExpiredWakeCapable
5232 
5233  --*/
5234 {
5235  NTSTATUS notifyPowerDownStatus;
5236 
5238 
5239  //
5240  // Notify the device power requirement state machine that we are about to
5241  // power down.
5242  //
5243  notifyPowerDownStatus = This->m_PowerPolicyMachine.m_Owner->
5244  m_PoxInterface.NotifyDevicePowerDown();
5245  if (FALSE == NT_SUCCESS(notifyPowerDownStatus)) {
5246  //
5247  // We couldn't notify the device power requirement state machine that
5248  // we are about to power down, because the "device-power-required"
5249  // notification has already arrived. So we should not power down at this
5250  // time. Revert back to the started state.
5251  //
5253  }
5254 
5255  if (This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.UsbSSCapable) {
5257  }
5258  else {
5260  }
5261 }
5262 
5266  )
5267 /*++
5268 
5269 Routine Description:
5270  The device is enabled to be armed for wake from S0. The device just idled
5271  out and is now about to transition into this state. The first step is to
5272  move into a partial Dx state (I/O stopped), send the wake request, arm the
5273  device, and then move into full Dx. This function starts the transition
5274  by requesting a Dx irp.
5275 
5276 Arguments:
5277  This - instance of the state machine
5278 
5279 Return Value:
5280  new state
5281 
5282  --*/
5283 
5284 {
5285  BOOLEAN poweredDown;
5286 
5288 
5289  poweredDown = This->PowerPolicyCanIdlePowerDown(
5290  This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.DxState
5291  );
5292 
5293  if (poweredDown == FALSE) {
5294  //
5295  // Upon failure, revert back to the started state.
5296  //
5298  }
5299 
5300  return WdfDevStatePwrPolNull;