VOID MPReturnNetBufferLists( NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST NetBufferLists, ULONG ReturnFlags ) { PADAPTER adapter = (PADAPTER)MiniportAdapterContext; PMP_PORT destinationPort = NULL; PNET_BUFFER_LIST currentNetBufferList = NetBufferLists, nextNetBufferList; // // We increment the port list refcount. This would avoid a pause from finishing // while we are processing this NBL and that ensures that the port list does not // change // MP_INCREMENT_PORTLIST_REFCOUNT(adapter); // // Walk the chain of netbuffer lists // while (currentNetBufferList != NULL) { // // Currently we return 1 NET_BUFFER_LIST at a time since we may be getting // back NET_BUFFER_LISTS indicated by different ports on 1 call. // This can be optimized // nextNetBufferList = NET_BUFFER_LIST_NEXT_NBL(currentNetBufferList); NET_BUFFER_LIST_NEXT_NBL(currentNetBufferList) = NULL; destinationPort = MP_NBL_SOURCE_PORT(currentNetBufferList); MPASSERT(destinationPort != NULL); // // Pass it to the appropriate port for processing // Port11HandleReturnNetBufferLists( destinationPort, currentNetBufferList, ReturnFlags ); currentNetBufferList = nextNetBufferList; } // // We were protecting the port list only until we hand it to the port. After this point, the port // is responsible for ensuring that it does not let the port get deleted while // it has packets pending on it // MP_DECREMENT_PORTLIST_REFCOUNT(adapter); }
NDIS_STATUS BasePortTranslateRxPacketsToRxNBLs( __in PMP_PORT Port, __in PMP_RX_MSDU PacketList, __out PNET_BUFFER_LIST* NetBufferLists ) { PNET_BUFFER_LIST outputNetBufferList = NULL; PNET_BUFFER_LIST currentNetBufferList, prevNetBufferList = NULL; USHORT fragmentIndex = 0; PMP_RX_MSDU currentPacket = PacketList, nextPacket; PMP_RX_MPDU currentFragment; NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_EXTSTA_RECV_CONTEXT osRecvContext; // This is same for ExtAP & ExtSTA PMDL currentMdl, prevMdl = NULL, mdlChain = NULL; ULONG totalLength = 0; *NetBufferLists = NULL; // Convert each PACKET and FRAGMENT to OS structures while (currentPacket != NULL) { nextPacket = MP_RX_MSDU_NEXT_MSDU(currentPacket); // Go through the FRAGMENTs in this PACKET & create an MDL chain mdlChain = NULL; totalLength = 0; for (fragmentIndex = 0; fragmentIndex < MP_RX_MSDU_MPDU_COUNT(currentPacket); fragmentIndex++) { currentFragment = MP_RX_MSDU_MPDU_AT(currentPacket, fragmentIndex); totalLength += MP_RX_MPDU_LENGTH(currentFragment); // Populate the MDL with Fragment contents currentMdl = NdisAllocateMdl(Port->MiniportAdapterHandle, MP_RX_MPDU_DATA(currentFragment), MP_RX_MPDU_LENGTH(currentFragment) ); if (currentMdl == NULL) { MpTrace(COMP_RECV, DBG_SERIOUS, ("Failed to allocate MDL for a MP_RX_MPDU data\n")); ndisStatus = NDIS_STATUS_RESOURCES; break; } // Add this to the MDL chain if (mdlChain == NULL) { // Add this to the head mdlChain = currentMdl; } else { NDIS_MDL_LINKAGE(prevMdl) = currentMdl; } prevMdl = currentMdl; } if (ndisStatus != NDIS_STATUS_SUCCESS) { while (mdlChain != NULL) { currentMdl = mdlChain; mdlChain = NDIS_MDL_LINKAGE(currentMdl); // MDL was allocated NdisFreeMdl(currentMdl); } break; } // Allocate the NET_BUFFER_LIST and the NET_BUFFER currentNetBufferList = NdisAllocateNetBufferAndNetBufferList( Port->RxNetBufferListPool, 0, 0, mdlChain, 0, totalLength ); if (currentNetBufferList == NULL) { MpTrace(COMP_SEND, DBG_SERIOUS, ("Failed to allocate NET_BUFFER_LIST for MP_RX_MSDU \n")); ndisStatus = NDIS_STATUS_RESOURCES; break; } // Populate the RX_PACKET MP_NBL_WRAPPED_RX_MSDU(currentNetBufferList) = currentPacket; MP_NBL_SOURCE_PORT(currentNetBufferList) = Port; if (outputNetBufferList == NULL) { outputNetBufferList = currentNetBufferList; } else { NET_BUFFER_LIST_NEXT_NBL(prevNetBufferList) = currentNetBufferList; } // The Next PACKET's NBL would be added after the current PACKET's NBL prevNetBufferList = currentNetBufferList; osRecvContext = MP_RX_MSDU_RECV_CONTEXT(currentPacket); MP_ASSIGN_NDIS_OBJECT_HEADER(osRecvContext->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_EXTSTA_RECV_CONTEXT_REVISION_1, sizeof(DOT11_EXTSTA_RECV_CONTEXT)); MP_SET_RECEIVE_CONTEXT(currentNetBufferList, osRecvContext); currentPacket = nextPacket; } if (ndisStatus != NDIS_STATUS_SUCCESS) { if (outputNetBufferList != NULL) { BasePortFreeTranslatedRxNBLs(Port, outputNetBufferList); outputNetBufferList = NULL; } } *NetBufferLists = outputNetBufferList; return ndisStatus; }