Enable Caching to Improve NDIS 6.0 DMA Performance (Compact 2013)
3/26/2014
When your miniport driver allocates shared memory by using the NdisMAllocateSharedMemory function, we recommend that, if possible, you call this function with Cached set to TRUE to enable caching.
The following code example illustrates a call to NdisMAllocateSharedMemory with caching enabled.
Important
For readability, the following code sample does not contain security checking or error handling. Do not use the following code in a production environment.
NdisMAllocateSharedMemory(
pMyAdapter->AdapterHandle,
pMyAdapter->RecvBufAllocSize,
TRUE, // Cached memory
&pMyAdapter->RecvBufVirtAddr,
&pMyAdapter->RecvBufPhysAddr);
In the preceding example, NdisMAllocateSharedMemory allocates a shared memory receive buffer of the size specified in pMyAdapter->RecvBufAllocSize
. The call to NdisMAllocateSharedMemory saves the virtual address (the address in your miniport driver's address space) to pMyAdapter->RecvBufVirtAddr
and it saves the physical address (the address seen by the network adapter) to pMyAdapter->RecvBufPhysAddr
. Because the Cached parameter is set to TRUE, the shared memory area is allocated from cached memory.
The Windows Embedded Compact 2013 implementation of NDIS includes the CachedSharedMem registry setting, which you can use to force shared memory caching. You can enable CachedSharedMem to force a network miniport driver on an x86 platform to use cached shared memory buffers, regardless of how that driver calls NdisMAllocateSharedMemory. For more information about CachedSharedMem, see Network Driver Registry Settings. If possible, we recommend that you modify your network driver code to call NdisMAllocateSharedMemory with Cached always set to TRUE rather than use the CachedSharedMem registry setting to force caching.
Most platforms (such as x86 platforms) maintain DMA cache coherency without the need for special miniport driver code to flush the cache. However, you must take explicit steps in your miniport driver to guarantee DMA cache coherency when you enable caching on platforms with cache-incoherent DMA (such as ARM platforms). An asynchronous DMA read or write operation accesses data in memory, not in the processor cache. Unless you have explicitly flushed the processor cache just before a write, the data in this cache might be more up-to-date than the copy in memory. Unless you have explicitly flushed this cache just before a read, the data transferred into system memory by the DMA operation could be overwritten with stale data if the processor cache is flushed later.
To flush the processor cache on DMA write transfers
Write data into the shared memory area.
Call NdisFlushBuffer with WriteToDevice set to TRUE to write back cached data.
Begin the DMA transfer operation from shared memory.
Note that the function NdisMAllocateNetBufferSGList implicitly calls NdisFlushBuffer, so you do not have to call NdisFlushBuffer if your miniport driver uses NdisMAllocateNetBufferSGList to allocate memory for DMA write transfers.
To flush the processor cache on DMA receive transfers
Call NdisFlushBuffer with WriteToDevice set to TRUE to write back cached data.
Begin the DMA transfer operation into shared memory and wait until it completes.
Call NdisFlushBuffer with WriteToDevice set to FALSE to discard cached data that is present due to speculative read of memory into the cache.
Read data from the shared memory area.