Exemple #1
0
VOID
HvlDeletePendingOperation(
    _In_  PHVL                        pHvl,
    _In_  PHVL_PENDING_OP             pPendingOp
    )
{
    switch (pPendingOp->Type)
    {
        case HVL_PENDING_OP_EX_ACCESS:
        {
            PHVL_EX_ACCESS_REQ pExReq = (PHVL_EX_ACCESS_REQ)pPendingOp->pvOpData;
            HvlDeleteExAccessRequest(pHvl, pExReq);
        }
        break;            
    }

    if (&pHvl->PnpPendingOp != pPendingOp)
    {
        FREE_MEM(pPendingOp);
    }
}
Exemple #2
0
NDIS_STATUS
HvlQueueExAccessRequest(
    _In_  PHVL                    pHvl,
    _In_  PVNIC                   pVNic,
    _In_  BOOLEAN                 fPnpOperation
    )
{
    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
    PHVL_EX_ACCESS_REQ pExReq = NULL, pPnpExReq = NULL;
    PHVL_PENDING_OP pPendingOp = NULL;

    ASSERT(HvlIsLocked(pHvl));
    
    do
    {
        // All requests by the helper port are considered different
        if (!HvlIsHelperVNic(pHvl, pVNic))
        {
            /*
                Does an exclusive access request for this VNIC already exist?
                */
            pExReq = HvlGetNextReqForVNic(pHvl, pVNic, FALSE);
        }

        if (NULL != pExReq)
        {
            /*
                There is already an exclusive access request existing for this VNIC. 
                */

            /*
                If the request is not a PnP request simply ref-up
                */
            if (!HvlIsPreAllocatedRequest(pHvl, pExReq))
            {
                pExReq->ulRefCount++;
                MpTrace(COMP_HVL, DBG_NORMAL, ("VNIC (%d): Incremented refcount for an exclusive access requet. New ref = %d \n", VNIC_PORT_NO, pExReq->ulRefCount));
            }
            else
            {
                /*
                    a request already exists. However it is the PnP request. Make sure we do 
                    not use it for non-Pnp operation. If we did, we might get another PnP 
                    operation after this PnP operation is done but we won't be able to use the
                    pre-allocated request. Instead try to allocate a new request now
                    */

                // pnp operations must be serialized
                ASSERT(!fPnpOperation);

                pPnpExReq = pExReq;
                pExReq = NULL;

                // allocate exclusive access request                
                ndisStatus = ALLOC_MEM(pHvl->MiniportAdapterHandle, sizeof(HVL_EX_ACCESS_REQ), &pExReq);
                if (NDIS_STATUS_SUCCESS != ndisStatus)
                {
                    MpTrace(COMP_HVL, DBG_SERIOUS, ("Failed to allocate memory for a new exclusive access request\n"));
                    break;
                }

                // allocate pending operation
                ndisStatus = ALLOC_MEM(pHvl->MiniportAdapterHandle, sizeof(HVL_PENDING_OP), &pPendingOp);
                if (NDIS_STATUS_SUCCESS != ndisStatus)
                {
                    MpTrace(COMP_HVL, DBG_SERIOUS, ("Failed to allocate memory for a new pending operation"));
                    break;
                }
                
                pExReq->pVNic = pVNic;
                pExReq->ulRefCount = pPnpExReq->ulRefCount + 1;

                pPendingOp->Type = HVL_PENDING_OP_EX_ACCESS;
                pPendingOp->pvOpData= pExReq;

                // now insert this new request in the same place as the old request
                pPendingOp->Link.Flink = pHvl->PnpPendingOp.Link.Flink;
                pPendingOp->Link.Blink = pHvl->PnpPendingOp.Link.Blink;
                pHvl->PnpPendingOp.Link.Flink->Blink = &pPendingOp->Link;
                pHvl->PnpPendingOp.Link.Blink->Flink = &pPendingOp->Link;

                // re-init the pre-allocated request since we are no longer using it
                HvlInitPreAllocatedOp(pHvl);
            }
        }
        else
        {
            /*
                This is the only exclusive access request for the HVL. Create a new request
                */
            if (fPnpOperation)
            {
                ASSERT(pHvl->PnpPendingOp.Link.Blink == NULL && pHvl->PnpPendingOp.Link.Flink == NULL);
                
                pExReq = pHvl->pPnpOpExReq;
            }
            else
            {
                ndisStatus = ALLOC_MEM(pHvl->MiniportAdapterHandle, sizeof(HVL_EX_ACCESS_REQ), &pExReq);
                if (NDIS_STATUS_SUCCESS != ndisStatus)
                {
                    MpTrace(COMP_HVL, DBG_SERIOUS, ("Failed to allocate memory for a new exclusive access request\n"));
                    break;
                }
            }
            
            pExReq->pVNic = pVNic;
            pExReq->ulRefCount = 1;

            ndisStatus = HvlQueuePendingOperation(pHvl, HVL_PENDING_OP_EX_ACCESS, pExReq, fPnpOperation);
            if (NDIS_STATUS_SUCCESS != ndisStatus)
            {
                MpTrace(COMP_HVL, DBG_SERIOUS, ("HvlQueuePendingOperation failed 0x%x\n", ndisStatus));
                break;
            }
            
            MpTrace(COMP_HVL, DBG_NORMAL, ("Queued an exclusive access requet for VNIC (%d)\n", VNIC_PORT_NO));
        }
    } while (FALSE);

    if (NDIS_FAILURE(ndisStatus))
    {
        if (pExReq && !fPnpOperation)
        {
            HvlDeleteExAccessRequest(pHvl, pExReq);
        }

        if (pPendingOp)
        {
            FREE_MEM(pPendingOp);
        }
    }
    
    return ndisStatus;
}
Exemple #3
0
NDIS_STATUS
Hvl11ReleaseExAccess(PHVL pHvl, PVNIC pVNic)
{
    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
    PVNIC pExVNic = NULL;
    PHVL_EX_ACCESS_REQ pExReq = NULL;
    
    MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d) releasing exclusive access\n", VNIC_PORT_NO));

    HvlLock(pHvl);

    pExReq = HvlDequeueNextReqForVNic(pHvl, pVNic);
    
    if (pExReq && 0 == pExReq->ulRefCount)
    {
        /*
            This is the last release by this VNIC. Actually take away exclusive access if this is 
            the current owner of exclusive access
            */
        pExVNic = HvlGetExAccessVNic(pHvl);
        
        if (pExVNic == pVNic)
        {
            MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d) currently owns exclusive access. Giving it up and removing it from the queue\n", VNIC_PORT_NO));
            
            HvlReleaseExAccess(pHvl, pVNic);    

            // set the event so that some other VNIC waiting for access can now get it
            KeSetEvent(&pHvl->ExAccessEvent, 0, FALSE);   
        }
        else
        {
            /*
                The VNIC is releasing exclusive access even when it doesn't own it. This can
                happen - take for example the following
                1. There is a helper port and an extensible station port
                2. A Pause is happening and the helper port has exclusive access.
                3. The station asks its VNIC to perform a dot11 reset
                4. The station's VNIC requests exclusive access. Since the helper port has it, its request is queued
                5. The helper port activates the station as part of its Pause processing
                6. The station VNIC's CtxSToVNic is called and the VNIC learns it has exclusive access
                7. The station VNIC completes its reset operation and asks Hvl to release exclusive access
                8. The calls comes into the HVL and we would land up in this else clause.

                The correct thing to do here is to simply remove the station VNIC's request from
                the queue which is what we have done here
                */
            MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d) doesn't own exclusive access currently. Just removing it from the queue\n", VNIC_PORT_NO));

            if (NULL == pExVNic)
            {
                //no one has exclusive access right now. set the event so that some other 
                //VNIC waiting for access can now get it
                KeSetEvent(&pHvl->ExAccessEvent, 0, FALSE);
            }
        }

        // delete the request
        if (HvlIsPreAllocatedRequest(pHvl, pExReq))
        {
            // it is a pre-allocated request - simply reset it
            HvlInitPreAllocatedOp(pHvl);
        }
        else
        {
            HvlDeleteExAccessRequest(pHvl, pExReq);        
        }
    }
    else
    {
        ASSERT(!HvlIsHelperVNic(pHvl, pVNic));
        
        /*
            This VNIC has more requests for exclusive access pending
            */
        MpTrace(COMP_HVL, DBG_NORMAL, ("VNic(%d) has %d more exclusive access requests. Decremented the refcount. Not removing it from the queue\n", VNIC_PORT_NO, pExReq ? pExReq->ulRefCount : -1));
        ndisStatus = NDIS_STATUS_PENDING;        
    }
    
    HvlUnlock(pHvl);

    return ndisStatus;
}