Bi Directional Bus driver Interfaces in kmdf

I am working on project which is having bus driver, sits over hardware and child driver dynamically enumerated
I want bi directional communication between child & bus driver and realized that either it could be

–>IOCTL based (2 Ioctls - pending ioctl for reading from Child to bus driver & ioctl for sending data to Bus driver from child driver)
→ bidirectional interface - https://www.osr.com/nt-insider/2014-issue2/using-bus-interfaces-driver-driver-communication/

Ioctl based interface automatically take care of D0 exit cases bcz interface automatically
get deactivated + we can always configure queues in our own way but demerit is that at least one ioctl is always pended
and need to be completed/cancelled for graceful exit.

→ My question is

:In Stack tear condition which start from top to bottom - if child driver is going to unload or unloaded and
bus driver sent a call to child driver then it would cause blue screen – how to handle this situation??

: In power down cases if child driver already gone to D0 exit and then simultaneously call comes from bus driver
what ll happen and how to handle this ??

: what do you suggest --which interface is better - Ioctl or Bus driver

Thanks

With the bus interface you’re really just exchanging function pointers between the two modules. So, yes, you need a mechanism for coordinating the teardown of the connection between the two modules. I like using Run-Down Protection for this sort of thing, but that’s just one way to solve the problem and it may or may not be appropriate for your design.

There’s nothing inherently better about IOCTLs vs a Bus Interface. Bus Interfaces are an efficient way for one driver to make synchronous calls into another driver. Synchronous IOCTLs are also pretty efficient, but are always going to have more overhead than just making a subroutine call.

If you try to do something asynchronous through a Bus Interface then you end up creating something that looks an awful lot like the WDFREQUEST interface, in which case you’re better off using IOCTLs.

To give some examples from OSR history of when we chose one versus another:

  1. We wrote a disk filter driver A that needed to ask another driver B for some information on each and every disk I/O. We used a bus interface to reduce the overhead of the calls from A to B
  2. We wrote a bus driver for a custom protocol bus that could tunnel I2C. The children had to talk to the bus driver to read/write their devices. The operations were always asynchronous, so we used IOCTLs