IODMACommand::setMemoryDescriptor returns kIOReturnCannotLock

I am trying to port the DMA part of a PCIe driver from the old getPhysicalAddress() to the IODMACommand API.

My problem is that IODMACommand::setMemoryDescriptor() returns kIOReturnCannotLock. I also have the following error in the system log:

(mapper-apciec0-3-0-0) IODARTMapper::iovmMapMemory:  Map request failed (0xe00002cc) iodc=<ptr>, iomd=<ptr>, length=0x10000

Here is how I allocate my memory descriptor :

ULONGLONG PhysicalMask_LL = 0xffffffffffffffffULL << PAGE_SHIFT;
                
mpCommonBuffers[BufId_UL].pBufferDescriptor = IOBufferMemoryDescriptor::inTaskWithPhysicalMask(kernel_task, kIOMemoryPhysicallyContiguous | kIODirectionIn, Size_UL, PhysicalMask_LL);

And here is how I create the DMA command :

IOMapper* pMapper_X = IOMapper::copyMapperForDevice(pProvider_O);
mpDmaCommand_X = IODMACommand::withSpecification(kIODMACommandOutputHost64,  64, 0, (IODMACommand::MappingOptions)(IODMACommand::kMapped), 0, 1, pMapper_X, NULL);

Any idea what could cause this error? Thanks.

Answered by Systems Engineer in 679360022

This error code may arise if you are calling this API while holding a spinlock, or from primary interrupt context. The operation of setting up a command is more work than belongs under a spinlock and is definitely unsafe from interrupt context. Bonus: If you have the debug= boot arg set, it will instead panic with a message for you.

Accepted Answer

This error code may arise if you are calling this API while holding a spinlock, or from primary interrupt context. The operation of setting up a command is more work than belongs under a spinlock and is definitely unsafe from interrupt context. Bonus: If you have the debug= boot arg set, it will instead panic with a message for you.

Thanks, that was the problem indeed!

IODMACommand::setMemoryDescriptor returns kIOReturnCannotLock
 
 
Q