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.
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.