I have yet another issue with USB driver, selective suspend and XP SP2. This one is rather easy to reproduce. It seems as race conditions between IDLE IRP callback and surprise removal. Lets compare.
Normal situation:
- IDLE notification callback is called
- callback sends D2 IRP and waits until completed
- IDLE notification callback finishes
- device is physically disconnected
- IDLE IRP completion routine is called
- completion routine sends D0 IRP
- D0 IRP is completed
- driver receives few PnP IRPs and finally surprise removal
- driver waits until all requests complete, makes cleanup and passes IRP below
- driver receives device removal IRP, finishes processing and everything is OK
Now remove device a bit sooner:
- IDLE notification callback is called
2 - 3. callback sends D2 IRP and waits until completed
2 - 3. device is physically disconnected - driver receives the first PnP IRP from the removal series (IRP_MN_QUERY_DEVICE_RELATIONS)
- driver finds IDLE IRP isn’t completed, yet and tries to cancel it. Because callback was already called, it sends D0 IRP down the stack to achieve it.
- driver receives next PnP IRP and finally surprise removal
- driver waits until both D0 and IDLE IRPs are completed and waits forever because they aren’t.
OK, postpone waiting as late as possible:
7. driver doesn’t wait, makes cleanup and passes IRP below, instead
8. driver receives device removal IRP, finishes processing and waits for D0 and IDLE IRPs
9. IDLE IRP is completed
10. driver still waits for D0 IRP completion and waits forever
According to my experiments, window is about 250 - 500 ms but I can’t be sure because it is hard to measure time between physical disconnect and idle callback call. It is possible disconnect can precede IDLE callback call.
The result is non-functional device after reconnect, locked device manager and finally locked system during shutdown or suspend. Ugly.
Please note I can’t make workaround and avoid sending D0 IRP when surpsise removal is detected. First, selective suspend is cancelled for any PnP IRP (well, maybe it is unnecessary but DDK samples do it) so it is already sent when surprise removal is received. Second, driver can be called in parallel another way (IOCTL) just before the first PnP IRP and this call would also cause selective suspend cancel and in turn D0 IRP.
For now, it seems as a bug in XP SP2 USB drivers. XP SP2 tries to postpone D0 IRPs sent during IDLE callback processing until callback finishes and it seems not all cases are handled correctly. There is similar issue with S3 query IRP but it can be solved using \Callback\PowerState. Surprise removal can’t be.
Best regards,
Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]