@@ -961,63 +961,98 @@ USBPORT_IsrDpcHandler(IN PDEVICE_OBJECT FdoDevice,
961961 return ;
962962 }
963963
964- for (List = ExInterlockedRemoveHeadList (& FdoExtension -> EpStateChangeList ,
965- & FdoExtension -> EpStateChangeSpinLock );
966- List != NULL ;
967- List = ExInterlockedRemoveHeadList (& FdoExtension -> EpStateChangeList ,
968- & FdoExtension -> EpStateChangeSpinLock ))
969- {
964+ /* Process the state change list.
965+ * - Always process the list (don't flush during suspend)
966+ * - If controller is suspended/off, mark endpoints as ready immediately
967+ * - Don't request interrupts if suspended */
968+ KeAcquireSpinLockAtDpcLevel (& FdoExtension -> EpStateChangeSpinLock );
969+ List = FdoExtension -> EpStateChangeList .Flink ;
970+ while (List != & FdoExtension -> EpStateChangeList )
971+ {
972+ BOOLEAN EndpointReady = FALSE;
973+ PLIST_ENTRY NextList ;
974+ BOOLEAN ControllerSuspended ;
975+
970976 Endpoint = CONTAINING_RECORD (List ,
971977 USBPORT_ENDPOINT ,
972978 StateChangeLink );
973979
974980 DPRINT_CORE ("USBPORT_IsrDpcHandler: Endpoint - %p\n" , Endpoint );
975981
976- KeAcquireSpinLockAtDpcLevel (& Endpoint -> EndpointSpinLock );
982+ /* Save the next entry before we potentially remove this one */
983+ NextList = List -> Flink ;
977984
978- KeAcquireSpinLockAtDpcLevel ( & FdoExtension -> MiniportSpinLock );
979- FrameNumber = Packet -> Get32BitFrameNumber (FdoExtension -> MiniPortExt );
980- KeReleaseSpinLockFromDpcLevel ( & FdoExtension -> MiniportSpinLock );
985+ /* Check if controller is suspended/off */
986+ ControllerSuspended = (FdoExtension -> Flags & USBPORT_FLAG_HC_SUSPEND ) != 0 ||
987+ ( FdoExtension -> CommonExtension . DevicePowerState == PowerDeviceD3 );
981988
982- if (FrameNumber <= Endpoint -> FrameNumber &&
983- !(Endpoint -> Flags & ENDPOINT_FLAG_NUKE ))
989+ if (ControllerSuspended )
990+ {
991+ /* Controller is suspended/off - mark endpoint as ready immediately */
992+ EndpointReady = TRUE;
993+ }
994+ else
984995 {
985- KeReleaseSpinLockFromDpcLevel (& Endpoint -> EndpointSpinLock );
986-
987- ExInterlockedInsertHeadList (& FdoExtension -> EpStateChangeList ,
988- & Endpoint -> StateChangeLink ,
989- & FdoExtension -> EpStateChangeSpinLock );
990-
991996 KeAcquireSpinLockAtDpcLevel (& FdoExtension -> MiniportSpinLock );
992- Packet -> InterruptNextSOF (FdoExtension -> MiniPortExt );
997+ FrameNumber = Packet -> Get32BitFrameNumber (FdoExtension -> MiniPortExt );
993998 KeReleaseSpinLockFromDpcLevel (& FdoExtension -> MiniportSpinLock );
994999
995- break ;
1000+ /* Check if the endpoint is ready to be processed */
1001+ if (FrameNumber > Endpoint -> FrameNumber ||
1002+ (Endpoint -> Flags & ENDPOINT_FLAG_NUKE ))
1003+ {
1004+ EndpointReady = TRUE;
1005+ }
9961006 }
9971007
998- KeReleaseSpinLockFromDpcLevel (& Endpoint -> EndpointSpinLock );
9991008
1000- KeAcquireSpinLockAtDpcLevel (& Endpoint -> StateChangeSpinLock );
1001- Endpoint -> StateLast = Endpoint -> StateNext ;
1002- KeReleaseSpinLockFromDpcLevel (& Endpoint -> StateChangeSpinLock );
1009+ if (EndpointReady )
1010+ {
1011+ /* Endpoint is ready - remove it from the list and process it */
1012+ RemoveEntryList (& Endpoint -> StateChangeLink );
1013+ Endpoint -> StateChangeLink .Flink = NULL ;
1014+ Endpoint -> StateChangeLink .Blink = NULL ;
10031015
1004- DPRINT_CORE ("USBPORT_IsrDpcHandler: Endpoint->StateLast - %x\n" ,
1005- Endpoint -> StateLast );
1016+ KeAcquireSpinLockAtDpcLevel (& Endpoint -> StateChangeSpinLock );
1017+ Endpoint -> StateLast = Endpoint -> StateNext ;
1018+ KeReleaseSpinLockFromDpcLevel (& Endpoint -> StateChangeSpinLock );
10061019
1007- if (IsDpcHandler )
1008- {
1009- USBPORT_InvalidateEndpointHandler (FdoDevice ,
1010- Endpoint ,
1011- INVALIDATE_ENDPOINT_ONLY );
1020+ DPRINT_CORE ("USBPORT_IsrDpcHandler: Endpoint->StateLast - %x\n" ,
1021+ Endpoint -> StateLast );
1022+
1023+ KeReleaseSpinLockFromDpcLevel (& FdoExtension -> EpStateChangeSpinLock );
1024+
1025+ if (IsDpcHandler )
1026+ {
1027+ USBPORT_InvalidateEndpointHandler (FdoDevice ,
1028+ Endpoint ,
1029+ INVALIDATE_ENDPOINT_ONLY );
1030+ }
1031+ else
1032+ {
1033+ USBPORT_InvalidateEndpointHandler (FdoDevice ,
1034+ Endpoint ,
1035+ INVALIDATE_ENDPOINT_WORKER_THREAD );
1036+ }
1037+
1038+ KeAcquireSpinLockAtDpcLevel (& FdoExtension -> EpStateChangeSpinLock );
10121039 }
1013- else
1040+ else if (! ControllerSuspended )
10141041 {
1015- USBPORT_InvalidateEndpointHandler (FdoDevice ,
1016- Endpoint ,
1017- INVALIDATE_ENDPOINT_WORKER_THREAD );
1042+ /* Endpoint is not ready yet - leave it in the list and request interrupt.
1043+ * Don't request interrupts if controller is suspended. */
1044+ KeAcquireSpinLockAtDpcLevel (& FdoExtension -> MiniportSpinLock );
1045+ Packet -> InterruptNextSOF (FdoExtension -> MiniPortExt );
1046+ KeReleaseSpinLockFromDpcLevel (& FdoExtension -> MiniportSpinLock );
10181047 }
1048+ /* If suspended and not ready, leave it in list but don't request interrupt */
1049+
1050+ /* Move to the next entry */
1051+ List = NextList ;
10191052 }
10201053
1054+ KeReleaseSpinLockFromDpcLevel (& FdoExtension -> EpStateChangeSpinLock );
1055+
10211056 if (IsDpcHandler )
10221057 {
10231058 USBPORT_DpcHandler (FdoDevice );
0 commit comments