WdfDmaTransactionInitialize returns STATUS_WDF_TOO_FRAGMENTED for unlimited SG size

Hello,

I am writing a DMA routine for a bus driver based off the Microsoft provided document here:
http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/dma.docx

The code we have written is very similar to what is contained in the Microsoft documentation. When we try to use the driver with our device to do control transfers, everything works; however, when we attempt BULK transfers, the WdfDmaTransactionInitialize call fails with STATUS_WDF_TOO_FRAGMENTED. Consulting MSDN, I see the following:

“The number of scatter/gather elements that was needed to handle the transaction was greater than the value that the driver’s call to WdfDmaEnablerSetMaximumScatterGatherElements specified.”

Further notes from MSDN specify:
“If the buffer that the driver specifies is too fragmented (that is, it requires more scatter/gather elements than the device can handle), WdfDmaTransactionInitialize returns STATUS_WDF_TOO_FRAGMENTED. The driver can specify a smaller memory buffer and call WdfDmaTransactionInitialize again.”

The function fails immediately and the EvtProgramDma function we pass in never gets called.

We are never calling WdfDmaEnablerSetMaximumScatterGatherElements anywhere in our code. According to MSDN, in this case the following is true:

“If your driver does not call WdfDmaEnablerSetMaximumScatterGatherElements, the framework uses a default value of WDF_DMA_ENABLER_UNLIMITED_FRAGMENTS, which means that there is no limit to the number of scatter/gather elements.”

Can anyone offer any pointers? Are there any possible WDF calls or anything that would implicitly limit the number of maximum scatter gather elements?

Might this error be indicative of a different problem?

Thanks,
R

xxxxx@gmail.com wrote:

The code we have written is very similar to what is contained in the Microsoft documentation. When we try to use the driver with our device to do control transfers, everything works; however, when we attempt BULK transfers, the WdfDmaTransactionInitialize call fails with STATUS_WDF_TOO_FRAGMENTED.

Are you writing a USB Host Controller Driver? I can’t think of any
other reason you would need to talk about doing DMA with control and
bulk transfers. If so, why?

The function fails immediately and the EvtProgramDma function we pass in never gets called.

How large is the transfer? Does your PCI hardware handle 64-bit
addresses? What were the parameters when you created your DMA enabler?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Suffice it to say, we are indeed writing a USB host controller driver for a number of reasons I can’t fully elaborate on that involve how our device will eventually work with the controller.

The transfer is ~2MB, and the PCI hardware does handle 64-bit addresses.

The DMA enabler is quite straightforward as well and is created in the following way:

#define MAXIMUM_TRANSFER_LENGTH 0x4000000



{
WDF_DMA_ENABLER_CONFIG dmaConfig;

WDF_DMA_ENABLER_CONFIG_INIT( &dmaConfig,
WdfDmaProfileScatterGather64,
MAXIMUM_TRANSFER_LENGTH );

status = WdfDmaEnablerCreate( DevExt->Device,
&dmaConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&DevExt->DmaEnabler );
if (!NT_SUCCESS (status))
{
TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, “WdfDmaEnablerCreate failed: %!STATUS!”, status);
return status;
}
}

Hi,

It’s not expected to see status_wdf_too_fragmented if the SG limit size isn’t specified. Could you please share out the IFR log for the driver after this failure? You’d need to execute !wdflogdump from the kernel debugger. For more information about WDF debugger extension please check out http://msdn.microsoft.com/en-us/library/windows/hardware/ff565805(v=vs.85).aspx

Thanks,
Neslihan

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Monday, July 22, 2013 3:07 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] WdfDmaTransactionInitialize returns STATUS_WDF_TOO_FRAGMENTED for unlimited SG size

Hello,

I am writing a DMA routine for a bus driver based off the Microsoft provided document here:
http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/dma.docx

The code we have written is very similar to what is contained in the Microsoft documentation. When we try to use the driver with our device to do control transfers, everything works; however, when we attempt BULK transfers, the WdfDmaTransactionInitialize call fails with STATUS_WDF_TOO_FRAGMENTED. Consulting MSDN, I see the following:

“The number of scatter/gather elements that was needed to handle the transaction was greater than the value that the driver’s call to WdfDmaEnablerSetMaximumScatterGatherElements specified.”

Further notes from MSDN specify:
“If the buffer that the driver specifies is too fragmented (that is, it requires more scatter/gather elements than the device can handle), WdfDmaTransactionInitialize returns STATUS_WDF_TOO_FRAGMENTED. The driver can specify a smaller memory buffer and call WdfDmaTransactionInitialize again.”

The function fails immediately and the EvtProgramDma function we pass in never gets called.

We are never calling WdfDmaEnablerSetMaximumScatterGatherElements anywhere in our code. According to MSDN, in this case the following is true:

“If your driver does not call WdfDmaEnablerSetMaximumScatterGatherElements, the framework uses a default value of WDF_DMA_ENABLER_UNLIMITED_FRAGMENTS, which means that there is no limit to the number of scatter/gather elements.”

Can anyone offer any pointers? Are there any possible WDF calls or anything that would implicitly limit the number of maximum scatter gather elements?

Might this error be indicative of a different problem?

Thanks,
R


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