STATUS_WDF_TOO_FRAGMENTED Error

Greetings.

I am getting a STATUS_WDF_TOO_FRAGMENTED error returned when I call WdfDmaTransactionInitializeUsingRequest(). Here are the relevant code snippets from where the DMA enabler is setup:

#define SAMPCIE_DMA_MAX_SGE 0x00000400
#define SAMPCIE_DMA_MAX_SIZE 0x10000000

// set dma alignment
WdfDeviceSetAlignmentRequirement( wdfDevice, FILE_QUAD_ALIGNMENT );

// initialize dma enabler config
WDF_DMA_ENABLER_CONFIG_INIT( &dmaConfig,
WdfDmaProfileScatterGatherDuplex, SAMPCIE_DMA_MAX_SIZE );

// create dma enabler
status = WdfDmaEnablerCreate( wdfDevice, &dmaConfig,
WDF_NO_OBJECT_ATTRIBUTES, &pSampcieData->dmaEnabler );

// unsuccessful?
if( ! NT_SUCCESS( status ) )
{
// return status
TRACE_LOG_RET_0( status,
“WdfDmaEnablerCreate() failed.”,
wdfDevice, SAMPCIE_ERROR_DMA_ENABLER );
}

// set max sg elements
WdfDmaEnablerSetMaximumScatterGatherElements(
pSampcieData->dmaEnabler, SAMPCIE_DMA_MAX_SGE );

The S/G entiries for the DMA engine are stored in block RAM inside the FPGA, hence the 0x400 S/G element limit. The FPGA is connected to 256MB of DDR2 device memory, hence the 0x10000000 maximum transfer size.

So my question is, why is the call to WdfDmaTransactionInitializeUsingRequest() failing with STATUS_WDF_TOO_FRAGMENTED for a transfer length of 0xCF0000? ~13MB < 256MB … so what gives?

I am fairly certain there are more than 0x400 S/G elements for the request since the application’s heap is a fragmented mess and I rarely see consecutive physical pages showing up in the S/G list for DMA requests. However, I was under the impression the framework would break up the transfer and call the EvtProgramDmaFunction callback repeatedly. Is this not (at it appears to be from this example) the case?

From the WDK docs for WdfDmaTransactionDmaCompleted():

“The framework might divide a DMA transaction into several DMA transfer operations.”

The operative word being ‘might’. So I ‘might’ have misunderstood. Do I have to breakup the request into smaller (4MB - 4KB worst case for 0x400 S/G elements) ‘bite sized’ DMA morsels? Or is there a way to instruct the framework do it for me?

Many thanks!

110110101100

Unfortunately there is no way you can tell KMDF to break a transaction into multiple transfers if sufficient s/g lists are unavailable. The KMDF will break apart the transaction if its size is > max transfer size that your device can handle. You will need to break apart your transfers manually if you need to handle heavy fragmentation.

I’ll provide feedback to the doc team (you can also do this yourself via the doc webpage on MSDN) that we can be more clear about when we will break the transaction up. We will also look at how we can improve this scenario in the future.


From: xxxxx@lists.osr.com [xxxxx@lists.osr.com] on behalf of xxxxx@philips.com [xxxxx@philips.com]
Sent: Tuesday, November 24, 2009 11:09 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] STATUS_WDF_TOO_FRAGMENTED Error

Greetings.

I am getting a STATUS_WDF_TOO_FRAGMENTED error returned when I call WdfDmaTransactionInitializeUsingRequest(). Here are the relevant code snippets from where the DMA enabler is setup:

#define SAMPCIE_DMA_MAX_SGE 0x00000400
#define SAMPCIE_DMA_MAX_SIZE 0x10000000

// set dma alignment
WdfDeviceSetAlignmentRequirement( wdfDevice, FILE_QUAD_ALIGNMENT );

// initialize dma enabler config
WDF_DMA_ENABLER_CONFIG_INIT( &dmaConfig,
WdfDmaProfileScatterGatherDuplex, SAMPCIE_DMA_MAX_SIZE );

// create dma enabler
status = WdfDmaEnablerCreate( wdfDevice, &dmaConfig,
WDF_NO_OBJECT_ATTRIBUTES, &pSampcieData->dmaEnabler );

// unsuccessful?
if( ! NT_SUCCESS( status ) )
{
// return status
TRACE_LOG_RET_0( status,
“WdfDmaEnablerCreate() failed.”,
wdfDevice, SAMPCIE_ERROR_DMA_ENABLER );
}

// set max sg elements
WdfDmaEnablerSetMaximumScatterGatherElements(
pSampcieData->dmaEnabler, SAMPCIE_DMA_MAX_SGE );

The S/G entiries for the DMA engine are stored in block RAM inside the FPGA, hence the 0x400 S/G element limit. The FPGA is connected to 256MB of DDR2 device memory, hence the 0x10000000 maximum transfer size.

So my question is, why is the call to WdfDmaTransactionInitializeUsingRequest() failing with STATUS_WDF_TOO_FRAGMENTED for a transfer length of 0xCF0000? ~13MB < 256MB … so what gives?

I am fairly certain there are more than 0x400 S/G elements for the request since the application’s heap is a fragmented mess and I rarely see consecutive physical pages showing up in the S/G list for DMA requests. However, I was under the impression the framework would break up the transfer and call the EvtProgramDmaFunction callback repeatedly. Is this not (at it appears to be from this example) the case?

From the WDK docs for WdfDmaTransactionDmaCompleted():

“The framework might divide a DMA transaction into several DMA transfer operations.”

The operative word being ‘might’. So I ‘might’ have misunderstood. Do I have to breakup the request into smaller (4MB - 4KB worst case for 0x400 S/G elements) ‘bite sized’ DMA morsels? Or is there a way to instruct the framework do it for me?

Many thanks!

110110101100


NTDEV is sponsored by OSR

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