A while ago, I earned the coveted PeterGV “the most interesting post on
NTDEV in 3 weeks” award by asking about searching WDFQUEUEs for requests,
since the docs clearly say that it’s not kosher to simply call
WdfIoQueueRetrieveFoundRequest() without first calling
WdfIoQueueFindRequest(). Since we have a fixed hardware capacity, and the
tag is essentially the index into the array of hardware resources, an array
of requests is the most natural structure to use for our requests that are
inflight on the hardware. In all of the back and forth, Doron gave me our
current arrangement, which is described below.
We ended up with two queues, the default Q that all IO goes through, which
we configure as parallel, so we can have maximal parallel pre-processing
(BuildSGL, translate to HBA-specific form) as we implement the KMDF version
of Extreme DMA, and a “ReadyForTheHardwareQ” (RFHQ) that is also parallel,
which has a single EvtIoDefault callback that marks the request
cancellable, then hangs it on the hardware. All of this works great, until
we get to the state that the hardware is almost full, and the app sends
more IO than will fit into the hardware.
An example of this, SATA NCQ has the capacity of 32 tagged commands, and
let’s suppose we get to 31 running, and 3 more arrive from the host app.
Since my RFHQ is parallel, all three pop out at *about* the same time, and
the first one to grab the lock wins. The other two invocations of
EvtIoDefault have no place to put their requests, since I can’t put them
back on the RFHQ they came out of, since it’s parallel, and all the docs
say WdfRequestRequeue is only valid on a manual Q.
Since I am using a parallel queue for the RFHQ, it appears my options are
to either forward any excess (no room at the inn) IOs to a manual holding
queue, which I would then have to poll. If I’m going to do that, I might
as well make the RFHQ a manual queue, and be done with it.
Alternatively, I could stop the RFHQ by calling WdfIoQueueStop(), then
forward them back into the RFHQ, and restart it by calling
WdfIoQueueStart() when there is room on the hardware, but that puts the
deferred requests at the tail of the Q, and I can easily imagine a
pathological case where some IO(s) get(s) stuck in a loop like that if the
timing and phase of the moon are correct.
Question #1: Do I understand the usage and limitations of parallel
WDFQUEUEs correctly at this point? Is my overcapacity scenario correct?
KMDF enhancement request #1. Add WdfRequestRequeue capability to WDFQUEUES
configured as parallel. It wouldn’t be burdensome to require that the
queue be stopped first, in order to avoid the busy looping and potential
recursion of repeated requeues.
Question #2: Given that I have a fixed hardware limit, is my conclusion
that a manual Q is the right thing for the RFHQ the correct conclusion, or
have I missed something?
I mentioned that we’ve approximated the KMDF version of Extreme DMA. We’re
diving to WDM for the DMA Adapter and using BuildScatterGatherList to fill
a pre-allocated SGL. This doesn’t appear to be possible within KMDF. The
reason this doesn’t appear to be possible is that the EvtProgramDma
callback is supposed to return TRUE when it starts the IO on the hardware,
and FALSE otherwise. I had a lot less discomfort calling BuildSGL, because
the callback for that one is a VOID function, so there was no need to be
dishonest when disconnecting the callback from the act of starting it on
the hardware. I would probably be willing to trade the pre-allocated SGL
for the if I could defer the hardware start (hang it on my RFHQ) in
EvtProgramDma.
Question #3: Do I understand the KMDF DMA contract right? It isn’t kosher
to say TRUE when I may cancel or abort the IO without actually starting the
DMA on the hardware?
KMDF enhancement request #2: Allow pre-allocated SGLs.
KMDF enhancement request #3: Allow decoupling the SGL construction from
the DMA start.
I really do like the KMDF a lot. But I’m also pushing the limits of
“playing nice”, because I’m doing a lab harness, not a production driver,
so I recognize that my needs may not be consistent with some KMDF design
requirements.
Phil
Philip D. Barila
Seagate Technology LLC
(720) 684-1842