VOID VNic11SendCompletePackets( __in PVNIC pVNic, __in PMP_TX_MSDU PacketList, __in ULONG ulNumPkts, __in ULONG SendCompleteFlags ) { BOOLEAN fDispatchLevel = SendCompleteFlags & NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL ? TRUE : FALSE; MpTrace(COMP_HVL, DBG_LOUD, ("VNic(%d): Send completion called for %d packets \n", VNIC_PORT_NO, ulNumPkts)); Port11SendCompletePackets(pVNic->pvPort, PacketList, SendCompleteFlags); VNicLockAtDispatch(pVNic, fDispatchLevel); /* Remove the context switch ref counts that we added for these packets. Context switches can happen once it goes to zero */ VNicDecCtxSRef(pVNic, ulNumPkts, REF_SEND_PKTS); // account for the outstanding sends that have now been completed VNicDecOutstandingSends(pVNic, ulNumPkts); // also handle any sends that had been queued if (!PktQueueIsEmpty(&pVNic->TxQueue)) { VNicProcessQueuedPkts(pVNic, fDispatchLevel); } VNicUnlockAtDispatch(pVNic, fDispatchLevel); }
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); }
/* 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; }