4.6.4  Cache Considerations for Receiving Data

If a miniport allocates cached memory, it must do the following:

·Make receive buffers cache-aligned.

·Flush the cache before starting the receive by calling NdisFlushBuffer and NdisMUpdateSharedMemory.

A miniport that manages a busmaster DMA device receives data into memory shared with the NIC. The miniport must ensure that incoming data is present in shared memory (not in processor cache) before it begins to read that data. To accomplish this, the miniport for such a DMA device must call NdisFlushBuffer and NdisMUpdateSharedMemory for instance in its MiniportHandleInterrupt function, before indicating the receive or otherwise causing a read of the data.

A miniport must also prevent cache-line tearing by allocating cache-aligned memory for receive buffers. If a miniport allocates a large block of memory from which it reallocates smaller buffers for received data, the start of each receive buffer must be cache-aligned so that the buffers do not cross cache blocks. A miniport calls NdisGetCacheFillSize during initialization and saves this value in its adapter-specific context area. The miniport uses this value to round up the size of a receive buffer to a cache-line size or a multiple of that size when it allocates such a buffer. The miniport must also use the cache block size to calculate where in the preallocated block of memory to begin allocating receive buffers.

In general, a miniport for a busmaster DMA NIC should allocate cached shared memory, a faster and more available resource. There are two cases where a miniport must use noncached memory.

·If the NIC managed by the miniport receives consecutive packets into immediately adjacent memory, the end of one packet can occupy the same cache block as the start of the next packet. Therefore, the miniport must allocate noncached memory because reading the first packet can cause stale cache data for the start of the second one.

·If releasing the buffers involves writing to them, for instance, if the receive buffer is contiguous with a header that contains an ownership bit indicating whether the buffer belongs to the adapter or to the miniport, the adapter may write to that bit before releasing the buffer. A miniport that uses such a technique must allocate these buffers from noncached memory.