Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
/*
    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;
}
Beispiel #4
0
/*
    NOTE
    This packet gives up the VNIC lock before calling into the hardware. The VNIC state might get
    changed during the course of the call
    */
VOID
VNicSendPktsToHw(    
    _In_ PVNIC                   pVNic,
    _In_ ULONG                   ulNumPkts,
    _In_ PMP_TX_MSDU             PacketList,
    _In_ ULONG                   SendFlags
    )
{
    BOOLEAN fDispatchLevel = SendFlags & NDIS_SEND_FLAGS_DISPATCH_LEVEL ? TRUE : FALSE;
    PMP_TX_MSDU currentPacket = NULL;
    ULONG myCount = 0;

    currentPacket = PacketList;
    while (currentPacket != NULL)
    {
        myCount++;
        currentPacket = MP_TX_MSDU_NEXT_MSDU(currentPacket);
    }
    MPASSERT(myCount == ulNumPkts);

    ASSERT(VNicIsLocked(pVNic));
    ASSERT(VNicIsActive(pVNic));
    
    MpTrace(COMP_HVL, DBG_LOUD, ("VNic(%d): Sending %d packets to the hardware \n", VNIC_PORT_NO, ulNumPkts));

    /*
        We can call the hardware for sending packets. We need to increment the context 
        switch ref count to avoid becoming inactive. The context switch ref count will be 
        decremented when we receive the send completionAlso we need to give up our lock 
        before calling the hardware. 
        */
    VNicIncCtxSRef(pVNic, ulNumPkts, REF_SEND_PKTS);

    // we also need to keep track of the sends outstanding to the hardware
    VNicIncOutstandingSends(pVNic, ulNumPkts);
    
    _Analysis_assume_lock_held_((& pVNic->Lock)->SpinLock);
    VNicUnlockAtDispatch(pVNic, fDispatchLevel);
    
    Hw11SendPackets(pVNic->pvHwContext, PacketList, SendFlags);

    VNicLockAtDispatch(pVNic, fDispatchLevel);
}
Beispiel #5
0
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;
}