Hello,
I am porting a PCI driver written with IOKit to the new PCIDriverKit framework.
I am able to perform DMA with a contiguous buffer allocated inside the dext (with IOBufferMemoryDescriptor::Create).
But I would also like to perform DMA to and from a buffer allocated by an application.
What I exactly want to do is:
Allocate an aligned buffer in the app (with e.g. posix_memalign)
Send the pointer to this buffer to the dext
In the dext, retrieve the list of pages descriptors to be able to perform DMA without copy into (or from) this buffer.
In IOKit, we can use methods such IOMemoryDescriptor::withAddressRange and IODMACommand::gen64IOVMSegments to map and retrieve the scatter gather list but I cannot find any information on how to do this in a dext with the PCIDriverKit framework.
Can anybody help me on how to do that?
Post
Replies
Boosts
Views
Activity
I am porting a PCIe driver to the new IODMACommand API (my previous post).
I currently am able to perform DMA accesses, but I cannot seem to release the DART IO mapped addresses properly. After a few thousand requests, the address range is exhausted leading to
Subsequent mapping requests fail
(mapper-apciec0-3-0-0) IODARTVMAllocatorGeneric::vmAlloc: VM exhausted
(mapper-apciec0-3-0-0) IODARTMapper::iovmMapMemory: Map request failed (0xe00002bd) ...
setMemoryDescriptor() returned kIOReturnNoMemory
The whole computer usually crashes a few seconds / minutes later with
panic(cpu 1 caller 0xfffffe00283155d8): "pmap_mark_page_as_ppl_page_internal: page is not free, " "pa=0x80fb0c000"
I do not understand what I'm doing wrong. I carefully call prepare and complete on my IODMACommand around DMA accesses.
I check the return code of every call.
I have tried
creating and releasing a new IODMACommand for each request
creating and releasing a new IOBufferMemoryDescriptor for each request
unloading and reloading my kext between each request
Whatever I do, the addresses returned by genIOVMSegments are increasing and never seem to be reused.
Thanks for your help!
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.