DMA larger data failed

Hey guys,
My PCIE DMA driver works well in 1/4 MB transfer size. But failed when I raise the package size to 1 MB. Here is some DMP information.

STACK_TEXT:
822447b0 8172dc73 0000000a 0a920aa5 00000002 nt!KiBugCheck2
822447b0 85689459 0000000a 0a920aa5 00000002 nt!KiTrap0E+0x1cf
822448f0 85687cee 4f5767f0 b0a89808 00001401 Wdf01000!FxDmaPacketTransaction::TransferCompleted+0xa0
82244908 8568581a 00000000 82244968 00000001 Wdf01000!FxDmaTransactionBase::DmaCompleted+0x131
82244930 80bf61a2 00000000 b0a89808 82244968 Wdf01000!imp_WdfDmaTransactionDmaCompleted+0xaf
WARNING: Frame IP not in any known module. Following frames may be wrong.
82244974 856b9c10 5a771e38 63234720 a588e21c 0x80bf61a2
82244994 856b9f6b 00000000 00000000 82225300 Wdf01000!FxInterrupt::DpcHandler+0x9c
822449a8 8165c616 a588e21c a588e1c0 a588e1c0 Wdf01000!FxInterrupt::_InterruptDpcThunk+0x3c
82244a60 8165c236 82244aa8 00000000 829af040 nt!KiExecuteAllDpcs+0x216
82244b84 8172ee30 00000000 00000000 00000000 nt!KiRetireDpcList+0xf6
82244b88 00000000 00000000 00000000 00000000 nt!KiIdleLoop+0x38

STACK_COMMAND: kb

FOLLOWUP_IP:
Wdf01000!FxDmaPacketTransaction::TransferCompleted+a0
85689459 ff5014 call dword ptr [eax+14h]

SYMBOL_STACK_INDEX: 2

SYMBOL_NAME: Wdf01000!FxDmaPacketTransaction::TransferCompleted+a0

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: Wdf01000

IMAGE_NAME: Wdf01000.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 52158f4b

BUCKET_ID_FUNC_OFFSET: a0

FAILURE_BUCKET_ID: AV_Wdf01000!FxDmaPacketTransaction::TransferCompleted

BUCKET_ID: AV_Wdf01000!FxDmaPacketTransaction::TransferCompleted

ANALYSIS_SOURCE: KM

FAILURE_ID_HASH_STRING: km:av_wdf01000!fxdmapackettransaction::transfercompleted

FAILURE_ID_HASH: {393d6cd8-c2ae-3eaa-43aa-20ab1850b51c}

I am new to WinDbg. It seems that Wdf 01000.sys crashed. But how? Thanks in advance.

Following is my DPC function

VOID
PciEvtInterruptDpc(
In WDFINTERRUPT WdfInterrupt,
In WDFOBJECT WdfDevice
)
{
PDEVICE_CONTEXT devExt;
WDFREQUEST request;
NTSTATUS status;
size_t transferred;
BOOLEAN transactionComplete;

UNREFERENCED_PARAMETER(WdfInterrupt);

devExt = DeviceGetContext(WdfDevice);

request = devExt->CurrentRequest;

if (WdfRequestIsCanceled(request)) {
KdPrint((“Aborted DMA transaction 0x%p”, request));
devExt->CurrentRequest = NULL;

(VOID)WdfDmaTransactionDmaCompletedFinal(devExt->ReadDmaTransaction, 0, &status);
WdfDmaTransactionRelease(devExt->ReadDmaTransaction);
WdfRequestCompleteWithInformation(request,status, 0);
return;
}

transactionComplete = WdfDmaTransactionDmaCompleted(devExt->ReadDmaTransaction,
&status);

if (transactionComplete) {

ASSERT(status != STATUS_MORE_PROCESSING_REQUIRED);

transferred =
WdfDmaTransactionGetBytesTransferred(devExt->ReadDmaTransaction);

KdPrint((“Bytes transfered %d”, (int)transferred));

WdfObjectDelete(devExt->ReadDmaTransaction);

devExt->CurrentRequest = NULL;

WdfRequestCompleteWithInformation(request,
status,
(NT_SUCCESS(status)) ?
transferred : 0);
}

}

xxxxx@gmail.com wrote:

Following is my DPC function

I believe your problem is simply a lack of self-protection. You never
validate that devExt->CurrentRequest and devExt->dmaReadTransaction are
not null. From the stack trace, it looks like you passed a NULL
dmaReadTransaction into WdfDmaTransactionDmaCompleted. Also, you don’t
ever check the interrupt source – you assume it is a DMA completion.
Are DMA completions the only source of interrupts on your board? There
are no other status/error interrupts?

Did you update your DMA enabler to say that you can handle 1MB at a
time? Does your hardware do scatter/gather, or are you using bounce
buffers?

Also, to make sure you don’t accidentally handle the same request twice,
I would suggest that you replace this:

request = devExt->CurrentRequest;

with this:

request = InterlockedExchange( &devExt->CurrentRequest, 0 );

That way, you take ownership of the request and make sure no one else
can. Even better, why don’t you just create a manual queue to hold this
request? That way, in the future you can even have multiple requests
outstanding at a time. That would also clean up one bug in your code.
Right now, if the request is canceled, you end up calling
WdfRequestCompleteWithInformation but the “status” value is
uninitialized. It will be random memory.


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

Enable KMDF verifier. Dump the WDF log.

I get soooo tired of telling people to do this… It’s really depressing,

Peter
OSR
@OSRDrivers