/** 
 * \fn     txMgmtQ_QueuesNotEmpty
 * \brief  Context-Engine Callback
 * 
 * Context-Engine Callback for processing queues in driver's context.
 * Called after driver's context scheduling was requested in txMgmtQ_Xmit().
 * Calls the SM with QUEUES_NOT_EMPTY event.
 * 
 * \note   
 * \param  hTxMgmtQ - The module's object                                          
 * \return void 
 * \sa     txMgmtQ_Xmit
 */ 
void txMgmtQ_QueuesNotEmpty (TI_HANDLE hTxMgmtQ)
{
    TTxMgmtQ  *pTxMgmtQ = (TTxMgmtQ *)hTxMgmtQ;

    /* Call the SM with QUEUES_NOT_EMPTY event. */
    mgmtQueuesSM(pTxMgmtQ, SM_EVENT_QUEUES_NOT_EMPTY);
}
/** 
 * \fn     txMgmtQ_SetConnState
 * \brief  Enable all queues transmission
 * 
 * Called by the connection SM and updates the connection state from Tx perspective 
 *   (i.e. which packet types are permitted).
*               Calls the local SM to handle this state change.
*
 * \note   
 * \param  hTxMgmtQ     - The module's object                                          
 * \param  eTxConnState - The new Tx connection state                                          
 * \return void 
 * \sa     mgmtQueuesSM
 */ 
void txMgmtQ_SetConnState (TI_HANDLE hTxMgmtQ, ETxConnState eTxConnState)
{
    TTxMgmtQ *pTxMgmtQ = (TTxMgmtQ *)hTxMgmtQ;

	pTxMgmtQ->eTxConnState = eTxConnState;

	/* Call the SM with the current event. */
	switch (eTxConnState)
	{
		case TX_CONN_STATE_CLOSE:	mgmtQueuesSM(pTxMgmtQ, SM_EVENT_CLOSE);		break;
		case TX_CONN_STATE_MGMT:	mgmtQueuesSM(pTxMgmtQ, SM_EVENT_MGMT);		break;
		case TX_CONN_STATE_EAPOL:	mgmtQueuesSM(pTxMgmtQ, SM_EVENT_EAPOL);		break;
		case TX_CONN_STATE_OPEN:	mgmtQueuesSM(pTxMgmtQ, SM_EVENT_OPEN);		break;

		default:
TRACE1(pTxMgmtQ->hReport, REPORT_SEVERITY_ERROR, ": Unknown eTxConnState = %d\n", eTxConnState);
	}
}
/** 
 * \fn     txMgmtQ_Xmit
 * \brief  Insert non-data packet for transmission
 * 
 * This function is used by the driver applications to send Tx packets other than the 
 *   regular data traffic, including the following packet types:
*				- Management
*				- EAPOL
*				- NULL
*				- IAPP
 * The managment packets are enqueued to the Mgmt-queue and the others to the Eapol-queue.
 * EAPOL packets may be inserted from the network stack context, so it requires switching 
 *   to the driver's context (after the packet is enqueued).
 * If the selected queue was empty before the packet insertion, the SM is called 
 *   with QUEUES_NOT_EMPTY event (in case of external context, only after the context switch).
 *
 * \note   
 * \param  hTxMgmtQ         - The module's object                                          
 * \param  pPktCtrlBlk      - Pointer to the packet CtrlBlk                                         
 * \param  bExternalContext - Indicates if called from non-driver context                                           
 * \return TI_OK - if the packet was queued, TI_NOK - if the packet was dropped. 
 * \sa     txMgmtQ_QueuesNotEmpty
 */ 
TI_STATUS txMgmtQ_Xmit (TI_HANDLE hTxMgmtQ, TTxCtrlBlk *pPktCtrlBlk, TI_BOOL bExternalContext)
{
    TTxMgmtQ *pTxMgmtQ = (TTxMgmtQ *)hTxMgmtQ;
	TI_STATUS eStatus;
	TI_UINT32 uQueId;
    TI_UINT32 uQueSize;

	/* Always set highest TID for mgmt-queues packets. */
	pPktCtrlBlk->tTxDescriptor.tid = MGMT_QUEUES_TID; 

    /* Select queue asccording to the packet type */
	uQueId = (pPktCtrlBlk->tTxPktParams.uPktType == TX_PKT_TYPE_MGMT) ? QUEUE_TYPE_MGMT : QUEUE_TYPE_EAPOL ;

    /* Enter critical section to protect queue access */
    context_EnterCriticalSection (pTxMgmtQ->hContext);

	/* Enqueue the packet in the appropriate Queue */
    eStatus = que_Enqueue (pTxMgmtQ->aQueues[uQueId], (TI_HANDLE)pPktCtrlBlk);

    /* Get number of packets in current queue */
    uQueSize = que_Size (pTxMgmtQ->aQueues[uQueId]);

    /* Leave critical section */
    context_LeaveCriticalSection (pTxMgmtQ->hContext);

	/* If packet enqueued successfully */
	if (eStatus == TI_OK)
	{
		pTxMgmtQ->tDbgCounters.aEnqueuePackets[uQueId]++;

        /* If selected queue was empty before packet insertion */
        if (uQueSize == 1) 
        {
            /* If called from external context (EAPOL from network), request switch to the driver's context. */
            if (bExternalContext) 
            {
                context_RequestSchedule (pTxMgmtQ->hContext, pTxMgmtQ->uContextId);
            }

            /* If already in the driver's context, call the SM with QUEUES_NOT_EMPTY event. */
            else 
            {
                mgmtQueuesSM(pTxMgmtQ, SM_EVENT_QUEUES_NOT_EMPTY);
            }
        }
	}

	else
    {
        /* If the packet can't be queued so drop it */
        txCtrl_FreePacket (pTxMgmtQ->hTxCtrl, pPktCtrlBlk, TI_NOK);
		pTxMgmtQ->tDbgCounters.aDroppedPackets[uQueId]++;
    }

    return eStatus;
}
Beispiel #4
0
/** 
 * \fn     txMgmtQ_SetConnState
 * \brief  Enable all queues transmission
 * 
 * Called by the connection SM and updates the connection state from Tx perspective 
 *   (i.e. which packet types are permitted).
*               Calls the local SM to handle this state change.
*
 * \note   
 * \param  hTxMgmtQ     - The module's object                                          
 * \param  eTxConnState - The new Tx connection state                                          
 * \return void 
 * \sa     mgmtQueuesSM
 */ 
void txMgmtQ_SetConnState (TI_HANDLE hTxMgmtQ, ETxConnState eTxConnState)
{
    TTxMgmtQ *pTxMgmtQ = (TTxMgmtQ *)hTxMgmtQ;
    TMgmtLinkQ *pLinkQ;
    TI_UINT32 uHlid = 0; /* TODO[ilanb]: move to parameter, this API is for STA */

    pLinkQ = &pTxMgmtQ->aMgmtLinkQ[uHlid]; /* Link queues */

	pLinkQ->eTxConnState = eTxConnState;

	/* Call the SM with the current event. */
	switch (eTxConnState)
	{
		case TX_CONN_STATE_CLOSE:	mgmtQueuesSM(pTxMgmtQ, uHlid, SM_EVENT_CLOSE);		break;
		case TX_CONN_STATE_MGMT:	mgmtQueuesSM(pTxMgmtQ, uHlid, SM_EVENT_MGMT);		break;
		case TX_CONN_STATE_EAPOL:	mgmtQueuesSM(pTxMgmtQ, uHlid, SM_EVENT_EAPOL);		break;
		case TX_CONN_STATE_OPEN:	mgmtQueuesSM(pTxMgmtQ, uHlid, SM_EVENT_OPEN);		break;

		default:
TRACE1(pTxMgmtQ->hReport, REPORT_SEVERITY_ERROR, ": Unknown eTxConnState = %d\n", eTxConnState);
	}
}
/** 
 * \fn     runSchedulerNotFromSm
 * \brief  Run scheduler due to other events then from SM (static function)
 * 
 * To comply with the SM behavior, this function is used for any case where the
 *    Mgmt-Queues scheduler may have work to do due to events external to the SM.
 * If the queues are not empty, this function runs the scheduler.
*				If the scheduler emptied the queues, update the SM.
 * 
 * \note   
 * \param  pTxMgmtQ - The module's object                                          
 * \return void 
 * \sa     
 */ 
static void runSchedulerNotFromSm (TTxMgmtQ *pTxMgmtQ)
{
	/* If the queues are not empty, run the scheduler. */
	if ( !ARE_ALL_MGMT_QUEUES_EMPTY(pTxMgmtQ->aQueues) )
	{
		runScheduler (pTxMgmtQ);
		
		/* If the queues are now both empty, call the SM with QUEUES_EMPTY event. */
		if ( ARE_ALL_MGMT_QUEUES_EMPTY(pTxMgmtQ->aQueues) )
        {
			mgmtQueuesSM (pTxMgmtQ, SM_EVENT_QUEUES_EMPTY);
        }
	}
}
Beispiel #6
0
/** 
 * \fn     txMgmtQ_SetLinkState
 * \brief  set link state (enable/not)
 * 
 * \note   
 * \param  hTxMgmtQ     - The module's object                                          
 * \param  uHlid        - link id                                          
 * \param  eTxConnState - The new Tx connection state                                          
 * \return void 
 * \sa     mgmtQueuesSM
 */ 
TI_STATUS txMgmtQ_SetLinkState (TI_HANDLE hTxMgmtQ, TI_UINT32 uHlid, ETxConnState eTxConnState)
{
    TTxMgmtQ *pTxMgmtQ = (TTxMgmtQ *)hTxMgmtQ;
    TMgmtLinkQ *pLinkQ;

    pLinkQ = &pTxMgmtQ->aMgmtLinkQ[uHlid]; /* Link queues */
    pLinkQ->eTxConnState = eTxConnState;

	TRACE4(pTxMgmtQ->hReport, REPORT_SEVERITY_INFORMATION,"%s: link %d, LinkState %d, ConnState %d\n", __FUNCTION__, uHlid, pLinkQ->eState, pLinkQ->eTxConnState);

    /* Call the SM with the current event. */
    switch (eTxConnState)
    {
        case TX_CONN_STATE_CLOSE:	mgmtQueuesSM(pTxMgmtQ, uHlid, SM_EVENT_CLOSE);		break;
        case TX_CONN_STATE_MGMT:	mgmtQueuesSM(pTxMgmtQ, uHlid, SM_EVENT_MGMT);		break;
        case TX_CONN_STATE_EAPOL:	mgmtQueuesSM(pTxMgmtQ, uHlid, SM_EVENT_EAPOL);		break;
        case TX_CONN_STATE_OPEN:	mgmtQueuesSM(pTxMgmtQ, uHlid, SM_EVENT_OPEN);		break;

        default:
            TRACE2(pTxMgmtQ->hReport, REPORT_SEVERITY_ERROR, ": Unknown eTxConnState = %d, for link %d\n", eTxConnState, uHlid);
    }

    return TI_OK;
}
Beispiel #7
0
/** 
 * \fn     txMgmtQ_QueuesNotEmpty
 * \brief  Context-Engine Callback
 * 
 * Context-Engine Callback for processing queues in driver's context.
 * Called after driver's context scheduling was requested in txMgmtQ_Xmit().
 * Calls the SM with QUEUES_NOT_EMPTY event.
 * 
 * \note   
 * \param  hTxMgmtQ - The module's object                                          
 * \return void 
 * \sa     txMgmtQ_Xmit
 */ 
void txMgmtQ_QueuesNotEmpty (TI_HANDLE hTxMgmtQ)
{
    TTxMgmtQ  *pTxMgmtQ = (TTxMgmtQ *)hTxMgmtQ;
    TI_UINT32 uHlid;

    /* Call the SM with QUEUES_NOT_EMPTY event. */
    for (uHlid=0; uHlid<WLANLINKS_MAX_LINKS; uHlid++)
    {
        /* Call every link that is not in CLOSE state */
        if (pTxMgmtQ->aMgmtLinkQ[uHlid].bSendEvent_NotEmpty) 
        {
            /* reset bSendEvent_NotEmpty flag to use in driver context */
            pTxMgmtQ->aMgmtLinkQ[uHlid].bSendEvent_NotEmpty = TI_FALSE;

            /* handle the event in the link state machine */
            mgmtQueuesSM(pTxMgmtQ, uHlid, SM_EVENT_QUEUES_NOT_EMPTY);
        }
    }
}
Beispiel #8
0
/** 
 * \fn     runSchedulerNotFromSm
 * \brief  Run scheduler due to other events then from SM (static function)
 * 
 * To comply with the SM behavior, this function is used for any case where the
 *    Mgmt-Queues scheduler may have work to do due to events external to the SM.
 * If the queues are not empty, this function runs the scheduler.
*				If the scheduler emptied the queues, update the SM.
 * 
 * \note   
 * \param  pTxMgmtQ - The module's object                                          
 * \return void 
 * \sa     
 */ 
static void runSchedulerNotFromSm (TTxMgmtQ *pTxMgmtQ)
{
	TMgmtLinkQ *pLinkQ;
	TI_UINT32 uHlid;

	for (uHlid=0; uHlid<WLANLINKS_MAX_LINKS; uHlid++)
	{
		pLinkQ = &pTxMgmtQ->aMgmtLinkQ[uHlid]; /* Link queues */

		/* If the queues are not empty, run the scheduler. */
		if ( !ARE_LINK_MGMT_QUEUES_EMPTY(pLinkQ->aQueues) )
		{
			runScheduler (pTxMgmtQ);
		
			/* If the queues are now both empty, call the SM with QUEUES_EMPTY event. */
			if ( ARE_LINK_MGMT_QUEUES_EMPTY(pLinkQ->aQueues) )
			{
				mgmtQueuesSM (pTxMgmtQ, uHlid, SM_EVENT_QUEUES_EMPTY);
			}
        }
	}
}
Beispiel #9
0
/** 
 * \fn     txMgmtQ_Xmit
 * \brief  Insert non-data packet for transmission
 * 
 * This function is used by the driver applications to send Tx packets other than the 
 *   regular data traffic, including the following packet types:
*				- Management
*				- EAPOL
*				- NULL
*				- IAPP
 * The managment packets are enqueued to the Mgmt-queue and the others to the Eapol-queue.
 * EAPOL packets may be inserted from the network stack context, so it requires switching 
 *   to the driver's context (after the packet is enqueued).
 * If the selected queue was empty before the packet insertion, the SM is called 
 *   with QUEUES_NOT_EMPTY event (in case of external context, only after the context switch).
 *
 * \note   
 * \param  hTxMgmtQ         - The module's object                                          
 * \param  pPktCtrlBlk      - Pointer to the packet CtrlBlk                                         
 * \param  bExternalContext - Indicates if called from non-driver context                                           
 * \return TI_OK - if the packet was queued, TI_NOK - if the packet was dropped. 
 * \sa     txMgmtQ_QueuesNotEmpty
 */ 
TI_STATUS txMgmtQ_Xmit (TI_HANDLE hTxMgmtQ, TTxCtrlBlk *pPktCtrlBlk, TI_BOOL bExternalContext)
{
    TTxMgmtQ *pTxMgmtQ = (TTxMgmtQ *)hTxMgmtQ;
    TI_STATUS eStatus;
    TI_UINT32 uQueId;
    TI_UINT32 uQueSize;
    TI_UINT32 uHlid;
    TMgmtLinkQ *pLinkQ;

    /* Find link id by destination MAC address, if not found use global link id */
    if (pPktCtrlBlk->tTxPktParams.uPktType == TX_PKT_TYPE_MGMT)
    {
        /* MGMT packet, use destination MAC address from WLAN header, aBuf[0] is the WLAN header */
        if ((txDataQ_LinkMacFind( pTxMgmtQ->hTxDataQ, &uHlid ,((dot11_header_t *)(pPktCtrlBlk->tTxnStruct.aBuf[0]))->address1 )) != TI_OK)
        {
            uHlid = pTxMgmtQ->uGlobalHlid;
        }
    }
    else
    {
        /* EAPOL packet, use destination MAC address from ETHERNET header, aBuf[0] is the ETHERNET header */
        if ((txDataQ_LinkMacFind( pTxMgmtQ->hTxDataQ, &uHlid, ((TEthernetHeader *)(pPktCtrlBlk->tTxnStruct.aBuf[0]))->dst)) != TI_OK)
        {
            uHlid = pTxMgmtQ->uGlobalHlid;
        }
    }
    pPktCtrlBlk->tTxDescriptor.hlid = uHlid;

    pLinkQ = &pTxMgmtQ->aMgmtLinkQ[uHlid]; /* Link queues */

    /* Always set highest TID for mgmt-queues packets. */
    pPktCtrlBlk->tTxDescriptor.tid = MGMT_QUEUES_TID; 

    if ((pLinkQ->bEncrypt)&& (pPktCtrlBlk->tTxPktParams.uPktType == TX_PKT_TYPE_EAPOL)) 
    {
        SET_PKT_TYPE_ENCRYPT(pPktCtrlBlk);
    }

    /* Select queue asccording to the packet type */
    uQueId = (pPktCtrlBlk->tTxPktParams.uPktType == TX_PKT_TYPE_MGMT) ? QUEUE_TYPE_MGMT : QUEUE_TYPE_EAPOL ;

    /* Enter critical section to protect queue access */
    context_EnterCriticalSection (pTxMgmtQ->hContext);

    /* Check resources per LINK and per MGMT AC (VOICE)*/
    if (txDataQ_AllocCheckResources( pTxMgmtQ->hTxDataQ, pPktCtrlBlk) != TI_OK)
    {
        pLinkQ->tDbgCounters.aDroppedPackets[uQueId]++;
        pLinkQ->tDbgCounters.uNoResourcesCount++;
        /* Leave critical section */
        context_LeaveCriticalSection (pTxMgmtQ->hContext);

        /* If the packet can't be queued drop it */
        /* !!! This call should be out of the critical section */
        txCtrl_FreePacket (pTxMgmtQ->hTxCtrl, pPktCtrlBlk, TI_NOK);
        return TI_NOK;
    }

    /* Enqueue the packet in the appropriate Queue */
    eStatus = que_Enqueue (pLinkQ->aQueues[uQueId], (TI_HANDLE)pPktCtrlBlk);

    /* Get number of packets in current queue */
    uQueSize = que_Size (pLinkQ->aQueues[uQueId]);

    /* Leave critical section */
    context_LeaveCriticalSection (pTxMgmtQ->hContext);

    /* If packet enqueued successfully */
    if (eStatus == TI_OK)
    {
        pLinkQ->tDbgCounters.aEnqueuePackets[uQueId]++;

        /* If selected queue was empty before packet insertion */
        if (uQueSize == 1 ) 
        if (uQueSize ) 
        {
            /* If called from external context (EAPOL from network), request switch to the driver's context. */
            if (bExternalContext) 
            {
                /* Set bSendEvent_NotEmpty flag to use in driver context */
                pLinkQ->bSendEvent_NotEmpty = TI_TRUE;
                context_RequestSchedule (pTxMgmtQ->hContext, pTxMgmtQ->uContextId);
            }

            /* If already in the driver's context, call the SM with QUEUES_NOT_EMPTY event. */
            else 
            {
                mgmtQueuesSM(pTxMgmtQ, uHlid, SM_EVENT_QUEUES_NOT_EMPTY);
            }
        }
    }

    else
    {
        /* If the packet can't be queued so drop it */
        txCtrl_FreePacket (pTxMgmtQ->hTxCtrl, pPktCtrlBlk, TI_NOK);
        pLinkQ->tDbgCounters.aDroppedPackets[uQueId]++;
    }

    return eStatus;
}