Bus Driver - Static Enumeration - Reloading Child FDO

Hi

I have BUS driver that does static enumeration.
Now I need to reload my Child FDO on some soft error. I tried WdfDeviceSetFailed(WdfDeviceFailedAttemptRestart), Looks like that is only for Dynamic enumeration (along with BusDriver implementing REENUMERATE_SELF_INTERFACE_STANDARD, SurpriseRemoveAndReenumerateSelf()).

Is there any way to have my child FDO ( statically enumerated) reload itself

  • without re-creating PDO (like in disable/Enable case)
  • Any other standard QI interfaces etc for me to implement in BUSDriver to recreate PDO and reload my FDO driver automatically (preferably when WdfDeviceSetFailed(WdfDeviceFailedAttemptRestart) invoked.

Else is it my only options are

  • with static enumeration, implement own custom interface, to recreate the PDO
  • or use dynamic enumeration w/ REENUMERATE_SELF_INTERFACE_STANDARD.

Thanks

Just use dynamic enumeration for this child. You can keep static enumeration for other children if you need to. All of the data you supply for the static child you provide for the dynamic child, just in a different callback. IOW your existing could is nearly all reusable.

BTW on disable/enable, the PDO is not deleted. Only the drivers layered on top of the PDO are removed and deleted

d

Thanks Doron. Will change to dynamic enumeration.
Also I have a UMDF lower filter between my KMDF Child FDO and BudDriver, hopefully I won’t see any issues.

Yes PDO not deleted during disable/enable.

Implemented dynamic enumeration for my child FDOs’.

  1. Do I have to still implement REENUMERATE_SELF_INTERFACE_STANDARD on my PDO?

Actually my error was in one of WdfDevice callbacks (from a port driver), that happens after my PrepHw() returns and before D0Entry() is called.
-With static enumeration, once I return error, the FDO is yellow bang in device Manager immediately.
-With Dynamic enumeration, looks like PnP tried some 6 times and gave up.
-Just for test did WdfDeviceSetFailed(WdfDeviceFailedAttemptRestart) before returning error from callback, Pnp manager reloads the driver infinitely (As I never got to return Success yet)

In none of the cases above I ever got call to
a) EVT_WDF_CHILD_LIST_SCAN_FOR_CHILDREN Bus_EvtChildListScanForChildren;
b) EVT_WDF_CHILD_LIST_DEVICE_REENUMERATED Bus_EvtChildListDeviceReenumerated;
So for above case looks like I need to implement some private counter etc. to decide when I have to stop calling WdfDeviceSetFailed(WdfDeviceFailedAttemptRestart) to force PnP finally give up, in case I never recover internally (i.e. cannot return SUCCESS)

  1. I guess in above cases, at no time my PDO was destroyed and recreated (since a/b were never called)

  2. Also looks like I really do not have to provide impl. to below. Default implementations seems sufficient
    c) EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_COMPARE Bus_EvtChildListIdentificationDescriptionCompare;
    d) EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_CLEANUP Bus_EvtChildListIdentificationDescriptionCleanup;
    e) EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_DUPLICATE Bus_EvtChildListIdentificationDescriptionDuplicate;

Also after dynamic enumeration, had issues with child FDOs being visible in DeviceManager (‘Driver working properly, but device connected has HW ID issues’ msg).
EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_DUPLICATE sampl impl, wasn’t doing proper count/copy of my HW IDs. Changed my HW IDs thinking if WCHAR/UNICODE_STRING/null-chars were causing issues. But even after HWID mods and fixing count/copy, same issue. Uninstalling/deleting existing installed packages didn’t help. Went back to static enumeration which was working all along, that also encountered issue.
Had to change back to original HW IDs’ I had to have drivers install again. Looks like once different HW IDs got assigned to PDO, some check was happening with old persisted HW IDs. Was expecting whatever HWID, it would have just not installed drivers from store and instead be ready in UI to install/upgrade the driver instead of ‘Driver working properly, but device connected has HW ID issues’ msg.

Correction, I do get calls to below, so i can veto out any further re-enumeration, if excessive #fails happen w/o fwd progress.
a) EVT_WDF_CHILD_LIST_SCAN_FOR_CHILDREN ;
b) EVT_WDF_CHILD_LIST_DEVICE_REENUMERATED ;

Also induced calling WdfSetFailed(Restart) outside the context of WdfDevice callbacks, it works as expected.

Doron

if I use dynamic enumeration (WDFCHILDLIST), I do not need REENUMERATE_SELF_INTERFACE_STANDARD right?

Anyways had code for REENUMERATE_SELF_INTERFACE_STANDARD as well, so tried WdfFdoQueryForInterface(REENUMERATE_SELF_INTERFACE_STANDARD), but my query handler doesn’t get called.
But the call returns returns SUCCESS, so went ahead with interface->SurpriseRemoveAndReenumerateSelf() ! with whatever the Fx returned for SurpriseRemoveAndReenumerateSelf, it BSODS.

Looks like CHILDLIST and REENUMERATE_SELF_INTERFACE_STANDARD are exclusive or something. Of course I guess just one suffice and CHILDLIST provides default impl.

4: kd> k

Child-SP RetAddr Call Site

00 fffffb077883d628 fffff807746a9b92 nt!DbgBreakPointWithStatus
01 fffffb077883d630 fffff807746a91eb nt!KiBugCheckDebugBreak+0x12
02 fffffb077883d690 fffff807745c2437 nt!KeBugCheck2+0x95b
03 fffffb077883ddb0 fffff807745db6b0 nt!KeBugCheckEx+0x107
04 fffffb077883ddf0 fffff8077459e399 nt!PspSystemThreadStartup$filt$0+0x44
05 fffffb077883de30 fffff807745cb02f nt!_C_specific_handler+0xa9
06 fffffb077883dea0 fffff80774410890 nt!RtlpExecuteHandlerForException+0xf
07 fffffb077883ded0 fffff8077442aeda nt!RtlDispatchException+0x490
08 fffffb077883e620 fffff807745d419d nt!KiDispatchException+0x16a
09 fffffb077883ecd0 fffff807745d037f nt!KiExceptionDispatch+0x11d
0a fffffb077883eeb0 fffff8077953d838 nt!KiPageFault+0x43f
0b (Inline Function) ---------------- Wdf01000!KeGetCurrentIrql+0x4 [ddk\inc\wdm.h @ 18315] 0c (Inline Function) ---------------- Wdf01000!Mx::MxGetCurrentIrql+0x4 [minkernel\wdf\framework\shared\inc\primitives\km\mxgeneralkm.h @ 89]
0d fffffb077883f040 fffff8077d12397f ** Wdf01000!FxPkgPdo::_RemoveAndReenumerateSelf** +0x8 [minkernel\wdf\framework\shared\irphandlers\pnp\fxpkgpdo.cpp @ 1690]
0e fffffb077883f070 fffff8077d125d01

4: kd> !pcr
KPCR for Processor 4 at ffffe20018bda000:
Major 1 Minor 1
NtTib.ExceptionList: ffffe20018beffb0
NtTib.StackBase: ffffe20018bee000
NtTib.StackLimit: 0000000000000000
NtTib.SubSystemTib: ffffe20018bda000
NtTib.Version: 0000000018bda180
NtTib.UserPointer: ffffe20018bda870
NtTib.SelfTib: 000000120719f000

            SelfPcr: 0000000000000000
               Prcb: ffffe20018bda180
               Irql: 0000000000000000
                IRR: 0000000000000000
                IDR: 0000000000000000
      InterruptMode: 0000000000000000
                IDT: 0000000000000000
                GDT: 0000000000000000
                TSS: 0000000000000000

      CurrentThread: ffffcd8262808580
         NextThread: 0000000000000000
         IdleThread: ffffe20018beb240

          DpcQueue: Unable to read nt!_KDPC_DATA.DpcListHead.Flink @ ffffe20018bdcf80

You get the framework reenumerate self implementation if you enumerate the child with a WDFCHILDLIST.

d

Bent from my phone


From: msr
Sent: Monday, February 25, 2019 4:12:40 PM
To: Doron Holan
Subject: Re: [NTDEV] Bus Driver - Static Enumeration - Reloading Child FDO

OSR https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fcommunity.osr.com%2F&data=02|01|doron.holan%40microsoft.com|3e9aaa3c2cc741cdf2d408d69b7f1fac|72f988bf86f141af91ab2d7cd011db47|1|0|636867367634811243&sdata=%2FYvWBu4nHRt%2BQO3HadCcXJtkd15TtjVWa8d8myU%2F%2F1g%3D&reserved=0
msr commented on Bus Driver - Static Enumeration - Reloading Child FDO

Doron

if I use dynamic enumeration (WDFCHILDLIST), I do not need REENUMERATE_SELF_INTERFACE_STANDARD right?

Anyways had code for REENUMERATE_SELF_INTERFACE_STANDARD as well, so tried WdfFdoQueryForInterface(REENUMERATE_SELF_INTERFACE_STANDARD), but my query handler doesn’t get called.

But the call returns returns SUCCESS, so went ahead with interface->SurpriseRemoveAndReenumerateSelf() ! with whatever the Fx returned for SurpriseRemoveAndReenumerateSelf, it BSODS.

Looks like CHILDLIST and REENUMERATE_SELF_INTERFACE_STANDARD are exclusive or something. Of course I guess just one suffice and CHILDLIST provides default impl.

4: kd> k

# Child-SP RetAddr Call Site

00 fffffb077883d628 fffff807746a9b92 nt!DbgBreakPointWithStatus

01 fffffb077883d630 fffff807746a91eb nt!KiBugCheckDebugBreak+0x12

02 fffffb077883d690 fffff807745c2437 nt!KeBugCheck2+0x95b

03 fffffb077883ddb0 fffff807745db6b0 nt!KeBugCheckEx+0x107

04 fffffb077883ddf0 fffff8077459e399 nt!PspSystemThreadStartup$filt$0+0x44

05 fffffb077883de30 fffff807745cb02f nt!_C_specific_handler+0xa9

06 fffffb077883dea0 fffff80774410890 nt!RtlpExecuteHandlerForException+0xf

07 fffffb077883ded0 fffff8077442aeda nt!RtlDispatchException+0x490

08 fffffb077883e620 fffff807745d419d nt!KiDispatchException+0x16a

09 fffffb077883ecd0 fffff807745d037f nt!KiExceptionDispatch+0x11d

0a fffffb077883eeb0 fffff8077953d838 nt!KiPageFault+0x43f

0b (Inline Function) ---------------- Wdf01000!KeGetCurrentIrql+0x4 [ddk\inc\wdm.h @ 18315] 0c (Inline Function) ---------------- Wdf01000!Mx::MxGetCurrentIrql+0x4 [minkernel\wdf\framework\shared\inc\primitives\km\mxgeneralkm.h @ 89]

0d fffffb077883f040 fffff8077d12397f Wdf01000!FxPkgPdo::_RemoveAndReenumerateSelf +0x8 [minkernel\wdf\framework\shared\irphandlers\pnp\fxpkgpdo.cpp @ 1690]

0e fffffb077883f070 fffff8077d125d01

4: kd> !pcr

KPCR for Processor 4 at ffffe20018bda000:

Major 1 Minor 1

NtTib.ExceptionList: ffffe20018beffb0

NtTib.StackBase: ffffe20018bee000

NtTib.StackLimit: 0000000000000000

NtTib.SubSystemTib: ffffe20018bda000

NtTib.Version: 0000000018bda180

NtTib.UserPointer: ffffe20018bda870

NtTib.SelfTib: 000000120719f000

SelfPcr: 0000000000000000 Prcb: ffffe20018bda180 Irql: 0000000000000000 IRR: 0000000000000000 IDR: 0000000000000000 InterruptMode: 0000000000000000 IDT: 0000000000000000 GDT: 0000000000000000 TSS: 0000000000000000 CurrentThread: ffffcd8262808580 NextThread: 0000000000000000 IdleThread: ffffe20018beb240 DpcQueue: Unable to read nt!_KDPC_DATA.DpcListHead.Flink @ ffffe20018bdcf80