/* 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 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); }
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; }