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; }
VOID VNicCancelPendingSends( __in PVNIC pVNic ) { PMP_TX_MSDU pendingPackets = NULL; ASSERT(VNicIsLocked(pVNic)); do { if (!PktQueueIsEmpty(&pVNic->TxQueue)) { MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): Cancelling %d sends\n", VNIC_PORT_NO, PktQueueDepth(&pVNic->TxQueue))); pendingPackets = DeQueuePktList(&pVNic->TxQueue); // give up lock before calling into the port VNicUnlock(pVNic); Port11SendCompletePackets(pVNic->pvPort, pendingPackets, 0); VNicLock(pVNic); } else { MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): No sends are pending. Nothing to cancel\n", VNIC_PORT_NO)); } } while (FALSE); }
NDIS_STATUS VNic11JoinCompleteCallback( _In_ PVNIC pVNic, _In_ PVOID pvCtx, _In_ PVOID Data ) { PVNIC_COMPLETION_CTX pCtx = NULL; PORT11_GENERIC_CALLBACK_FUNC JoinCompleteHandler= NULL; NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): Hw completed Join operation \n", VNIC_PORT_NO)); pCtx = (PVNIC_COMPLETION_CTX)pvCtx; ASSERT(pCtx); JoinCompleteHandler = pCtx->CompletionFn; FREE_MEM(pCtx); VNicLock(pVNic); ndisStatus = VNicJoinComplete(pVNic, TRUE, JoinCompleteHandler, Data); VNicUnlock(pVNic); return ndisStatus; }
NDIS_STATUS VNicJoinComplete( _In_ PVNIC pVNic, _In_ BOOLEAN fReferenced, _In_ PORT11_GENERIC_CALLBACK_FUNC JoinCompleteHandler, _In_ PVOID Data ) { PVOID pvPort = NULL; NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): Completing the Join operation \n", VNIC_PORT_NO)); pvPort = pVNic->pvPort; // remove the ref count that was added for the join operation if (fReferenced) { VNicRemoveCtxSRef(pVNic, REF_JOIN); } // give up lock before calling into the port _Analysis_assume_lock_held_(pVNic->Lock.SpinLock); VNicUnlock(pVNic); // Call the completion handler in the port if (JoinCompleteHandler) { ndisStatus = JoinCompleteHandler(pvPort, Data); } VNicLock(pVNic); return ndisStatus; }
NDIS_STATUS VNic11StartBSS( _In_ PVNIC pVNic, _In_ PMP_BSS_DESCRIPTION BSSDescription, _In_ PORT11_GENERIC_CALLBACK_FUNC CompletionHandler ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; BOOLEAN fLocked = FALSE; BOOLEAN fProcessReqNow = FALSE; do { VNicLock(pVNic); fLocked = TRUE; ndisStatus = VNicCanProcessReqNow(pVNic, &fProcessReqNow); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): VNicCanProcessReqNow failed 0x%x\n", VNIC_PORT_NO, ndisStatus)); break; } if (fProcessReqNow) { ndisStatus = VNicStartBSSHelper(pVNic, BSSDescription); MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): VNicStartBSSHelper returned %!x!\n", VNIC_PORT_NO, ndisStatus)); } else { /* We are not currently active or there are pending operations. Queue the Start BSS request internally */ ndisStatus = VNicQueueStartBSSRequest( pVNic, BSSDescription, CompletionHandler ); if (NDIS_STATUS_SUCCESS == ndisStatus) { MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): Queued the start BSS request\n", VNIC_PORT_NO)); // Return pending since the request is not going to be completed synchrnously ndisStatus = NDIS_STATUS_PENDING; } else { MpTrace(COMP_HVL, DBG_SERIOUS, ("VNic(%d): VNicQueueStartBSSRequest failed 0x%x\n", VNIC_PORT_NO, ndisStatus)); } } } while (FALSE); if (fLocked) { VNicUnlock(pVNic); } 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; }
NDIS_STATUS VNic11JoinBSS( _In_ PVNIC pVNic, _In_ PMP_BSS_DESCRIPTION BSSDescription, _In_ ULONG JoinFailureTimeout, _In_ PORT11_GENERIC_CALLBACK_FUNC CompletionHandler ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; BOOLEAN fLocked = FALSE; BOOLEAN fProcessReqNow = FALSE; PVNIC_COMPLETION_CTX pCtx = NULL; do { VNicLock(pVNic); fLocked = TRUE; ndisStatus = VNicCanProcessReqNow(pVNic, &fProcessReqNow); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): VNicCanProcessReqNow failed 0x%x\n", VNIC_PORT_NO, ndisStatus)); break; } if (fProcessReqNow) { ndisStatus = ALLOC_MEM(pVNic->MiniportAdapterHandle, sizeof(VNIC_COMPLETION_CTX), &pCtx); if (NDIS_STATUS_SUCCESS != ndisStatus) { MpTrace(COMP_HVL, DBG_SERIOUS, ("VNic(%d): Failed to allocate memory for a new completion context \n", VNIC_PORT_NO)); /* Do not call the station's callback function since the station doesn't expect to be called back if there is a failure */ break; } pCtx->CompletionFn = CompletionHandler; ndisStatus = VNicJoinBSSHelper(pVNic, BSSDescription, JoinFailureTimeout, pCtx); if (NDIS_STATUS_PENDING != ndisStatus) { MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): VNicJoinBSSHelper completed synchronously %!x!\n", VNIC_PORT_NO, ndisStatus)); /* The call to the hardware completed synchronously. Do not call the station's callback function. */ FREE_MEM(pCtx); break; } } else { /* We are not currently active or there are pending operations. Queue the Join request internally */ ndisStatus = VNicQueueJoinRequest( pVNic, BSSDescription, JoinFailureTimeout, CompletionHandler ); if (NDIS_STATUS_SUCCESS == ndisStatus) { MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): Queued the join request \n", VNIC_PORT_NO)); // Return pending since the request is not going to be completed synchrnously ndisStatus = NDIS_STATUS_PENDING; } else { MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d): VNicQueueJoinRequest failed %!x!\n", VNIC_PORT_NO, ndisStatus)); } } } while (FALSE); if (fLocked) { VNicUnlock(pVNic); } return ndisStatus; }