EvtProgramDma runs asynchronously?

Hi List,

I use WdfDmaTransactionExecute() at PASSIVE_LEVEL to have it create DMA
mappings (in form of a SCATTER_GATHER_LIST) and call EvtProgramDma when
done. In EvtProgramDma I use the SCATTER_GATHER_LIST to program the device.

https://msdn.microsoft.com/en-us/library/windows/hardware/ff541816(v=vs.85).aspx
tells me that EvtProgramDma runs at IRQL=DISPATCH_LEVEL. In fact I see
it running at PASSIVE_LEVEL most of the time (*), and only
occasionally at DISPATCH_LEVEL.

(*) As for “occasionally”: I used to take a WDFWAITLOCK in
EvtProgramDma which succeeded most of the time - I conclude that
EvtProgramDma was running at PASSIVE_LEVEL in these cases. It
complained/bluescreened on me once, saying that I tried to take it at
DISPATCH_LEVEL, understandably. (Fix: found a different solution, not
taking a WDFWAITLOCK, clearly.)

What is the reason for EvtProgramDma to run at DISPATCH_LEVEL?

I mean, the entire process of creating DMA mapping is a *synchronous*
one, and I expect it to be done at PASSIVE_LEVEL, by
WdfDmaTransactionExecute(). Why isn’t EvtProgramDma called always at
PASSIVE_LEVEL? Or, respectively, the one level that I call
WdfDmaTransactionExecute() from?

Thanks in advance,
Jörg

That would be the wrong conclusion.

Call KeGetCurrentIrql() in your EvtProgramDma callback. I bet you’re being called at IRQL DISPATCH_LEVEL every time.

In terms of the IRQL you 're actually called at, it doesn’t really matter in any case. The contract is that you’re called at IRQL DISPATCH_LEVEL. And the contract with the use of WDFWAITLOCKs requires IRQL PASSIVE_LEVEL. So, no matter what, your use of WDFWAITLOCK is wrong… and it sounds like you fixed it.

Well, the *real* reason is that the underlying WDM function is called at IRQL DISPATCH_LEVEL.

Well, you see… I’m not sure how you concluded this, but you’re wrong.

The callback *can* be either synchronous or asynchronous. In terms of the Windows DMA Abstraction, “Mapping Registers” are allowed to be a scarce resource. When physical “mapping registers” are required, and when sufficient mapping registers happen to NOT be available for your specific transfer, your callback will be queued awaiting the availability of these mapping registers.

Soooo… asynchronous.

Peter
OSR
@OSRDrivers

On 07/30/2015 07:45 PM, xxxxx@osr.com wrote:

[quote] I mean, the entire process of creating DMA mapping is a
*synchronous* one, [/quote]

Well, you see… I’m not sure how you concluded this, but you’re
wrong.

The callback *can* be either synchronous or asynchronous. In terms
of the Windows DMA Abstraction, “Mapping Registers” are allowed to be
a scarce resource. When physical “mapping registers” are required,
and when sufficient mapping registers happen to NOT be available for
your specific transfer, your callback will be queued awaiting the
availability of these mapping registers.

Soooo… asynchronous.

This explains pretty much everything, thanks a lot.

Jörg

The allocation of mapping registers (which are most commonly just bounce buffers) may be asynchronous, but that wouldn’t necessarily preclude your EvtProgramDma callback from being run at passive level.

However consider when most drivers are going to return map registers to the pool. They’ll probably be doing it in response to an IO completion, which most commonly happens within a DPC (either the driver’s DPC or in a completion routine triggered by a lower driver completing a request in its DPC).

If the EvtProgramDma callback were guaranteed to run at PASSIVE level then in that common case the DMA engine would have to post work to a queue and signal a worker thread to invoke your callback. Let’s assume that’s not desirable, and so we wouldn’t want to guarantee that you run at passive level.

If we don’t guarantee that you’re running at passive level, if it’s going to be dispatch sometimes and passive other times, then we might as well just force the processor to dispatch level before making the call.

-p

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@osr.com
Sent: Thursday, July 30, 2015 10:45 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] EvtProgramDma runs asynchronously?



That would be the wrong conclusion.

Call KeGetCurrentIrql() in your EvtProgramDma callback. I bet you’re being called at IRQL DISPATCH_LEVEL every time.

In terms of the IRQL you 're actually called at, it doesn’t really matter in any case. The contract is that you’re called at IRQL DISPATCH_LEVEL. And the contract with the use of WDFWAITLOCKs requires IRQL PASSIVE_LEVEL. So, no matter what, your use of WDFWAITLOCK is wrong… and it sounds like you fixed it.



Well, the real reason is that the underlying WDM function is called at IRQL DISPATCH_LEVEL.



Well, you see… I’m not sure how you concluded this, but you’re wrong.

The callback can be either synchronous or asynchronous. In terms of the Windows DMA Abstraction, “Mapping Registers” are allowed to be a scarce resource. When physical “mapping registers” are required, and when sufficient mapping registers happen to NOT be available for your specific transfer, your callback will be queued awaiting the availability of these mapping registers.

Soooo… asynchronous.

Peter
OSR
@OSRDrivers


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer