NDIS_STATUS VNicStopBSSHelper( _In_ PVNIC pVNic ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; ASSERT(VNicIsLocked(pVNic)); ASSERT(VNicIsActive(pVNic) && !VNicIsInReset(pVNic)); do { /* We call the hardware for starting the BSS. We need to give up our lock before calling the hardware. The context switch ref count will be decremented when we have completed the call */ // add the context switch ref count VNicAddCtxSRef(pVNic, REF_STOP_BSS); _Analysis_assume_lock_held_(pVNic->Lock.SpinLock); VNicUnlock(pVNic); Hw11StopBSS(pVNic->pvHwContext); VNicLock(pVNic); MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): Called the hardware for stopping a BSS 0x%x\n", VNIC_PORT_NO, ndisStatus)); VNicRemoveCtxSRef(pVNic, REF_STOP_BSS); } while (FALSE); return ndisStatus; }
NDIS_STATUS VNicJoinBSSHelper( _In_ PVNIC pVNic, _In_ PMP_BSS_DESCRIPTION BSSDescription, _In_ ULONG JoinFailureTimeout, _In_ PVNIC_COMPLETION_CTX pCtx ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; BOOLEAN fReferenced = FALSE; ASSERT(VNicIsLocked(pVNic)); ASSERT(VNicIsActive(pVNic) && !VNicIsInReset(pVNic)); do { /* We can call the hardware for a join. We need to give up our lock before calling the hardware. The context switch ref count will be decremented when we have completed the join */ // add the context switch ref count for the async join call to the hardware VNicAddCtxSRef(pVNic, REF_JOIN); fReferenced = TRUE; _Analysis_assume_lock_held_(pVNic->Lock.SpinLock); VNicUnlock(pVNic); ndisStatus = Hw11JoinBSS( pVNic->pvHwContext, BSSDescription, JoinFailureTimeout, VNic11JoinCompleteCallback, pCtx ); MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): Called the hardware for the Join operation 0x%x\n", VNIC_PORT_NO, ndisStatus)); VNicLock(pVNic); } while (FALSE); if (NDIS_STATUS_PENDING != ndisStatus) { // the call to the hardware completed. Remove the join ref count we added if (fReferenced) { VNicRemoveCtxSRef(pVNic, REF_JOIN); } } return ndisStatus; }
/* This function releases the lock during its processing */ VOID VNicProcessQueuedPkts( _In_ PVNIC pVNic, BOOLEAN fDispatchLevel ) { ULONG ulNumPkts = 0; PMP_TX_MSDU PacketList = NULL; BOOLEAN fFailSends = FALSE; ASSERT(VNicIsLocked(pVNic)); ASSERT(VNicIsActive(pVNic)); ASSERT(!PktQueueIsEmpty(&pVNic->TxQueue)); do { if (VNicIsInReset(pVNic)) { fFailSends = TRUE; ulNumPkts = PktQueueDepth(&pVNic->TxQueue); PacketList = DeQueuePktList(&pVNic->TxQueue); MpTrace(COMP_HVL, DBG_NORMAL, ("VNIC(%d) is in reset. Failing %d sends. \n", VNIC_PORT_NO, ulNumPkts)); break; } if (Hw11CanTransmit(pVNic->pvHwContext)) { ulNumPkts = PktQueueDepth(&pVNic->TxQueue); PacketList = DeQueuePktList(&pVNic->TxQueue); MpTrace(COMP_HVL, DBG_NORMAL, ("VNIC(%d): Processing %d queued packets \n", VNIC_PORT_NO, ulNumPkts)); VNicSendPktsToHw(pVNic, ulNumPkts, PacketList, 0); } else { MpTrace(COMP_HVL, DBG_NORMAL, ("VNIC(%d): The hardware is not yet ready to accept packets\n", VNIC_PORT_NO)); } } while (FALSE); if (fFailSends) { _Analysis_assume_lock_held_((& pVNic->Lock)->SpinLock); VNicUnlockAtDispatch(pVNic, fDispatchLevel); Port11SendCompletePackets(pVNic->pvPort, PacketList, 0); VNicLockAtDispatch(pVNic, fDispatchLevel); } return; }
VOID VNic11SendPackets( __in PVNIC pVNic, __in PMP_TX_MSDU PacketList, __in ULONG ulNumPkts, __in ULONG SendFlags ) { BOOLEAN fDispatchLevel = SendFlags & NDIS_SEND_FLAGS_DISPATCH_LEVEL ? TRUE : FALSE; BOOLEAN fFailSends = FALSE; #if DBG PMP_TX_MSDU currentPacket; ULONG myCount = 0; currentPacket = PacketList; while (currentPacket != NULL) { myCount++; currentPacket = MP_TX_MSDU_NEXT_MSDU(currentPacket); } MPASSERT(myCount == ulNumPkts); #endif VNicLockAtDispatch(pVNic, fDispatchLevel); do { if (VNicIsInReset(pVNic)) { MpTrace(COMP_HVL, DBG_NORMAL, ("VNIC(%d) is in reset. Failing %d sends. \n", VNIC_PORT_NO, ulNumPkts)); fFailSends = TRUE; break; } if (VNicIsActive(pVNic) && Hw11CanTransmit(pVNic->pvHwContext) && (0 == PktQueueDepth(&pVNic->TxQueue))) { VNicSendPktsToHw(pVNic, ulNumPkts, PacketList, SendFlags); } else { /* We are either a. not currently active or b. the packets cannot be submitted to the hardware or c. there are packets pending in the send queue already Queue the send requests internally */ VNicQueueSendRequests(pVNic, ulNumPkts, PacketList); } } while (FALSE); VNicUnlockAtDispatch(pVNic, fDispatchLevel); if (fFailSends) { Port11SendCompletePackets(pVNic->pvPort, PacketList, SendFlags); } return; }