Пример #1
0
/****************************************************************************
 *                  txHwQueue_AllocResources()
 ****************************************************************************
 * DESCRIPTION: 
   ============
    1.  Estimate required HW-blocks number.
    2.1  If the required blocks are not available for the link or no free descriptor, 
            return  link STOP_CURRENT  (to stop current link and requeue the packet).
    2.2  If the required blocks are not available for the queue or no free descriptor, 
            return  queue STOP_CURRENT  (to stop current queue and requeue the packet).
    3.  Resources are available so update allocated blocks and descriptors counters.
    4.1  If no link resources for another similar packet, set STOP_NEXT (to stop current link).
    4.2  If no queue resources for another similar packet, set STOP_NEXT (to stop current queue).
        Else, return SUCCESS
 ****************************************************************************/
ETxHwQueStatus txHwQueue_AllocResources (TI_HANDLE hTxHwQueue, TTxCtrlBlk *pTxCtrlBlk)
{
    TTxHwQueue *pTxHwQueue = (TTxHwQueue *)hTxHwQueue;
    TI_UINT32 uNumBlksToAlloc; /* The number of blocks required for the current packet. */
    TI_UINT32 uExcludedLength; /* The data length not included in the rough blocks calculation */
    TI_UINT32 uAvailableBlks;  /* Max blocks that are currently available for this queue. */
    TI_UINT32 uReservedBlks;   /* How many blocks are reserved for this queue before this allocation. */
    TI_UINT32 uQueueId = WMEQosTagToACTable[pTxCtrlBlk->tTxDescriptor.tid];
    TTxHwQueueInfo *pQueueInfo = &(pTxHwQueue->aTxHwQueueInfo[uQueueId]);
    ETxHwQueStatus retStatus = TX_HW_QUE_STATUS_SUCCESS;
    TI_UINT32 uHlid = pTxCtrlBlk->tTxDescriptor.hlid;
#ifdef AP_MODE_ENABLED
    TTxHwLinkInfo *pLinkInfo = &(pTxHwQueue->aTxHwLinkInfo[uHlid]);
    TI_UINT32 uAvailableLinkBlks;  /* Max blocks that are currently available for this link. */
#endif

    /***********************************************************************/
    /*  Calculate packet required HW blocks.                               */
    /***********************************************************************/

    /* Divide length by 256 instead of 252 (block size) to save CPU */
    uNumBlksToAlloc = ( pTxCtrlBlk->tTxDescriptor.length + 20 ) >> 8;

    /* The length not yet included in the uNumBlksToAlloc is the sum of:
        1) 4 bytes per block as a result of using 256 instead of 252 block size.
        2) The remainder of the division by 256. 
        3) Overhead due to header translation, security and LLC header (subtracting ethernet header).
    */
    uExcludedLength = (uNumBlksToAlloc << 2) + ((pTxCtrlBlk->tTxDescriptor.length + 20) & 0xFF) + MAX_HEADER_SIZE - 14;

    /* Add 1 or 2 blocks for the excluded length, according to its size */
    uNumBlksToAlloc += (uExcludedLength > 252) ? 2 : 1;

    /* Add extra blocks needed in case of fragmentation */
    uNumBlksToAlloc += BLKS_HW_ALLOC_SPARE;


#ifdef AP_MODE_ENABLED
    /*
     * Check LINK resources and then AC resources
     * In case of no resources for the link, return STOP CURRENT and don't continue to check AC resources
     */

    /***********************************************************************/
    /*            Check link resources                                     */
    /***********************************************************************/

    /* Find max available blocks for this link (0 could indicate no descriptors). */
    uAvailableLinkBlks = txHwQueue_CheckLinkResources (pTxHwQueue, pLinkInfo);

    /* If we need more blocks than available, return  STOP_CURRENT (stop current link and requeue packet). */
    if (uNumBlksToAlloc > uAvailableLinkBlks)
    {
        TRACE6(pTxHwQueue->hReport, REPORT_SEVERITY_INFORMATION, ": No link resources, Link=%d, ReqBlks=%d, FreeBlks=%d, UsedBlks=%d, uFwMax=%d, uAvailableLinkBlks=%d\n", 
               uHlid, uNumBlksToAlloc, pLinkInfo->uFwFree, pLinkInfo->uHostAlloc, pLinkInfo->uFwMax, uAvailableLinkBlks);
        pLinkInfo->uNumBlksCausedBusy = uNumBlksToAlloc; /* used as prediction in free resources */
        pLinkInfo->bBusy = TI_TRUE;
        return TX_HW_LINK_STATUS_STOP_CURRENT;  /**** Exit! (we should stop link and requeue packet) ****/
    }
#endif

    /***********************************************************************/
    /*            Check if the required resources are available            */
    /***********************************************************************/

    /* Find max available blocks for this queue (0 could indicate no descriptors). */
    uAvailableBlks = txHwQueue_CheckResources (pTxHwQueue, pQueueInfo);
    
    /* If we need more blocks than available, return  STOP_CURRENT (stop current queue and requeue packet). */
    if (uNumBlksToAlloc > uAvailableBlks)
    {
        TRACE6(pTxHwQueue->hReport, REPORT_SEVERITY_INFORMATION, ": No resources, Queue=%d, ReqBlks=%d, FreeBlks=%d, UsedBlks=%d, AvailBlks=%d, UsedPkts=%d\n", uQueueId, uNumBlksToAlloc, pTxHwQueue->uNumTotalBlksFree, pQueueInfo->uNumBlksUsed, uAvailableBlks, pTxHwQueue->uNumUsedDescriptors);
        pQueueInfo->uNumBlksCausedBusy = uNumBlksToAlloc;
        pQueueInfo->bQueueBusy = TI_TRUE;

        return TX_HW_QUE_STATUS_STOP_CURRENT;  /**** Exit! (we should stop queue and requeue packet) ****/
    }

    /***********************************************************************/
    /*                    Allocate required resources                      */
    /***********************************************************************/

    /* Update blocks numbers in Tx descriptor */
    pTxCtrlBlk->tTxDescriptor.extraMemBlks = BLKS_HW_ALLOC_SPARE;
    pTxCtrlBlk->tTxDescriptor.totalMemBlks = uNumBlksToAlloc;

    /* Update packet allocation info:  */
    pTxHwQueue->uNumUsedDescriptors++; /* Update number of packets in FW (for descriptors allocation check). */
    pTxHwQueue->uDrvTxPacketsCntr++;
    pQueueInfo->uAllocatedBlksCntr += uNumBlksToAlloc; /* For FW counter coordination. */
    uReservedBlks = pQueueInfo->uNumBlksReserved;

    /* If we are currently using less than the low threshold (i.e. we have some reserved blocks), 
        blocks allocation should reduce the reserved blocks number as follows:
    */
    if (uReservedBlks)
    {

        /* If adding the allocated blocks to the used blocks will pass the low-threshold,
            only the part up to the low-threshold is subtracted from the reserved blocks.
            This is because blocks are reserved for the Queue only up to its low-threshold. 
            
              0   old used                    low      new used       high
              |######|                         |          |            |
              |######|                         |          |            |
                      <------------ allocated ----------->
                      <----- old reserved ---->
                             new reserved = 0     (we passed the low threshold)
        */
        if (uNumBlksToAlloc > uReservedBlks)
        {
            pQueueInfo->uNumBlksReserved = 0;
            pTxHwQueue->uNumTotalBlksReserved -= uReservedBlks; /* reduce change from total reserved.*/
        }


        /* Else, if allocating less than reserved,
            the allocated blocks are subtracted from the reserved blocks:
            
              0   old used       new used               low      high
              |######|               |                   |        |
              |######|               |                   |        |
                      <- allocated ->
                      <--------- old reserved ---------->
                                     <-- new reserved -->
        */
        else
        {
            pQueueInfo->uNumBlksReserved -= uNumBlksToAlloc;
            pTxHwQueue->uNumTotalBlksReserved -= uNumBlksToAlloc; /* reduce change from total reserved.*/
        }
    }


    /* Update total free blocks and Queue used blocks with the allocated blocks number. */
    pTxHwQueue->uNumTotalBlksFree -= uNumBlksToAlloc;
    pQueueInfo->uNumBlksUsed += uNumBlksToAlloc;

    TRACE7(pTxHwQueue->hReport, REPORT_SEVERITY_INFORMATION, ": SUCCESS,  Link=%d, Queue=%d, Req-blks=%d , Free=%d, Used=%d, Reserved=%d, Accumulated=%d\n", uHlid, uQueueId, uNumBlksToAlloc, pTxHwQueue->uNumTotalBlksFree, pQueueInfo->uNumBlksUsed, pQueueInfo->uNumBlksReserved, pQueueInfo->uAllocatedBlksCntr);

#ifdef AP_MODE_ENABLED

    /* Update Link used blocks with the allocated blocks number. */
    pLinkInfo->uLastAllocNumBlks = uNumBlksToAlloc; /* used as prediction in free resources */
    pLinkInfo->uHostAlloc += uNumBlksToAlloc;
    /*
     * At this stage, the resources for this LINK and AC are allocated successfully
     * Need to check if there is a place for anothoer similar packet (LINK and AC resources)
     * return bitmap of STOP NEXT, for link if no link resources and for AC if no queue resources
     */

    /* If no resources for another similar packet, return STOP_NEXT (to stop current link). */
    /* Note: Current packet transmission is continued */
    if ( (uNumBlksToAlloc << 1) > uAvailableLinkBlks )
    {
        TRACE6(pTxHwQueue->hReport, REPORT_SEVERITY_INFORMATION, ": No link resources for next packet, Link=%d, ReqBlks=%d, FreeBlks=%d, UsedBlks=%d, uFwMax=%d, uAvailableLinkBlks=%d\n", 
               uHlid, uNumBlksToAlloc, pLinkInfo->uFwFree, pLinkInfo->uHostAlloc, pLinkInfo->uFwMax, uAvailableLinkBlks);
        pLinkInfo->bBusy = TI_TRUE;
        retStatus |= TX_HW_LINK_STATUS_STOP_NEXT;
    }
#endif

    /* If no resources for another similar packet, return STOP_NEXT (to stop current queue). */
    /* Note: Current packet transmission is continued */
    if ( (uNumBlksToAlloc << 1) > uAvailableBlks )
    {
        TRACE6(pTxHwQueue->hReport, REPORT_SEVERITY_INFORMATION, ": No resources for next pkt, Queue=%d, ReqBlks=%d, FreeBlks=%d, UsedBlks=%d, AvailBlks=%d, UsedPkts=%d\n", uQueueId, uNumBlksToAlloc, pTxHwQueue->uNumTotalBlksFree, pQueueInfo->uNumBlksUsed, uAvailableBlks, pTxHwQueue->uNumUsedDescriptors);
        pQueueInfo->uNumBlksCausedBusy = uNumBlksToAlloc;
        pQueueInfo->bQueueBusy = TI_TRUE;
        retStatus |= TX_HW_QUE_STATUS_STOP_NEXT;
    }

    return retStatus;
}
Пример #2
0
/****************************************************************************
 *                  txHwQueue_UpdateFreeResources()
 ****************************************************************************
 * DESCRIPTION:
   ===========
   Called by FwEvent upon Data interrupt to update freed HW-Queue resources as follows:
    1) For all queues, update blocks and descriptors numbers according to FwStatus information.
    2) For each busy queue, if now available indicate it in the backpressure bitmap.
 ****************************************************************************/
ETxnStatus txHwQueue_UpdateFreeResources (TI_HANDLE hTxHwQueue, FwStatus_t *pFwStatus)
{
	TTxHwQueue *pTxHwQueue = (TTxHwQueue *)hTxHwQueue;
	TTxHwQueueInfo *pQueueInfo;
	TI_UINT32 uQueueId;
	TI_UINT32 uAvailableBlks; /* Max blocks available for current queue. */
	TI_UINT32 uNewNumUsedDescriptors;
	TI_UINT32 uBackpressure = 0;
	TI_UINT32 *pFreeBlocks = (TI_UINT32 *)pFwStatus->txReleasedBlks;
	TI_UINT32 uTempFwCounters;
	FwStatCntrs_t *pFwStatusCounters;

	/*
	 * If TxResults counter changed in FwStatus, update descriptors number according to  information
	 */
	uTempFwCounters = (ENDIAN_HANDLE_LONG(pFwStatus->counters));
	pFwStatusCounters = (FwStatCntrs_t *)&uTempFwCounters;
	if (pFwStatusCounters->txResultsCntr != pTxHwQueue->uFwTxResultsCntr) {
		pTxHwQueue->uFwTxResultsCntr = pFwStatusCounters->txResultsCntr;

		/* Calculate new number of used descriptors (the else is for wrap around case) */
		if (pTxHwQueue->uFwTxResultsCntr <= pTxHwQueue->uDrvTxPacketsCntr) {
			uNewNumUsedDescriptors = (TI_UINT32)(pTxHwQueue->uDrvTxPacketsCntr - pTxHwQueue->uFwTxResultsCntr);
		} else {
			uNewNumUsedDescriptors = 0x100 - (TI_UINT32)(pTxHwQueue->uFwTxResultsCntr - pTxHwQueue->uDrvTxPacketsCntr);
		}

		/* Update number of packets left in FW (for descriptors allocation check). */
		pTxHwQueue->uNumUsedDescriptors = uNewNumUsedDescriptors;
	}

	/*
	 * For all queues, update blocks numbers according to FwStatus information
	 */
	for (uQueueId = 0; uQueueId < MAX_NUM_OF_AC; uQueueId++) {
		pQueueInfo = &(pTxHwQueue->aTxHwQueueInfo[uQueueId]);

		/* Update per queue number of used, free and reserved blocks. */
		txHwQueue_UpdateFreeBlocks (pTxHwQueue, uQueueId, pFreeBlocks[uQueueId]);
	}

	/*
	 * For each busy queue, if now available indicate it in the backpressure bitmap
	 */
	for (uQueueId = 0; uQueueId < MAX_NUM_OF_AC; uQueueId++) {
		pQueueInfo = &(pTxHwQueue->aTxHwQueueInfo[uQueueId]);

		/* If the queue was stopped */
		if (pQueueInfo->bQueueBusy) {
			/* Find max available blocks for this queue (0 could indicate no descriptors). */
			uAvailableBlks = txHwQueue_CheckResources (pTxHwQueue, pQueueInfo);

			/* If the required blocks and a descriptor are available,
			     set the queue's backpressure bit to indicate NOT-busy! */
			if (pQueueInfo->uNumBlksCausedBusy <= uAvailableBlks) {
				SET_QUEUE_BACKPRESSURE(&uBackpressure, uQueueId); /* Start queue. */
				pQueueInfo->bQueueBusy = TI_FALSE;
			}
		}
	}

	/* If released queues map is not 0, send it to the upper layers (if CB available) */
	if ((uBackpressure > 0) && (pTxHwQueue->fUpdateBusyMapCb != NULL)) {
		pTxHwQueue->fUpdateBusyMapCb (pTxHwQueue->hUpdateBusyMapHndl, uBackpressure);
	}

	return TXN_STATUS_COMPLETE;
}
Пример #3
0
/****************************************************************************
 *                  txHwQueue_UpdateFreeResources()
 ****************************************************************************
 * DESCRIPTION:
   ===========
   Called by FwEvent upon Data interrupt to update freed HW-Queue resources as follows:
    1) For all queues, update blocks and descriptors numbers according to FwStatus information.
    2) For each busy queue, if now available indicate it in the backpressure bitmap.
 ****************************************************************************/
ETxnStatus txHwQueue_UpdateFreeResources (TI_HANDLE hTxHwQueue, FwStatus_t *pFwStatus)
{
    TTxHwQueue *pTxHwQueue = (TTxHwQueue *)hTxHwQueue;
    TTxHwQueueInfo *pQueueInfo;
    TI_UINT32 uQueueId;
    TI_UINT32 uAvailableBlks; /* Max blocks available for current queue. */
    TI_UINT32 uNewNumUsedDescriptors;
    TI_UINT32 uBackpressure = 0;
    TI_UINT32 uPriorityQueueBitMap = 0;
    TI_UINT32 *pFreeBlocks = (TI_UINT32 *)pFwStatus->txReleasedBlks;
    TI_UINT32 uTempFwCounters;
    FwStatCntrs_t *pFwStatusCounters;
    TI_UINT32 uNewTxTotal = (TI_UINT32)pFwStatus->txTotal;

    pTxHwQueue->iTxTotaldiff += (uNewTxTotal - pTxHwQueue->uNumTotalBlks) ;

    /*
     * If TxResults counter changed in FwStatus, update descriptors number according to  information
     */
    uTempFwCounters = (ENDIAN_HANDLE_LONG(pFwStatus->counters));
    pFwStatusCounters = (FwStatCntrs_t *)&uTempFwCounters;
    if (pFwStatusCounters->txResultsCntr != pTxHwQueue->uFwTxResultsCntr)
    {
        pTxHwQueue->uFwTxResultsCntr = pFwStatusCounters->txResultsCntr;

        /* Calculate new number of used descriptors (the else is for wrap around case) */
        if (pTxHwQueue->uFwTxResultsCntr <= pTxHwQueue->uDrvTxPacketsCntr)
        {
            uNewNumUsedDescriptors = (TI_UINT32)(pTxHwQueue->uDrvTxPacketsCntr - pTxHwQueue->uFwTxResultsCntr);
        }
        else
        {
            uNewNumUsedDescriptors = 0x100 - (TI_UINT32)(pTxHwQueue->uFwTxResultsCntr - pTxHwQueue->uDrvTxPacketsCntr);
        }

#ifdef TI_DBG   /* Sanity check: make sure we don't free more descriptors than allocated. */
        if (uNewNumUsedDescriptors >= pTxHwQueue->uNumUsedDescriptors)
        {
            TRACE2(pTxHwQueue->hReport, REPORT_SEVERITY_ERROR, ":  Used descriptors number should decrease: UsedDesc %d, NewUsedDesc %d\n", pTxHwQueue->uNumUsedDescriptors, uNewNumUsedDescriptors);
        }
#endif

        /* Update number of packets left in FW (for descriptors allocation check). */
        pTxHwQueue->uNumUsedDescriptors = uNewNumUsedDescriptors;
    }

    /* Update Total blocks*/
    pTxHwQueue->uNumTotalBlks = uNewTxTotal;
    if(pTxHwQueue->iTxTotaldiff > 0)
    {
        /* In case we have possitive difference we can add the blocks to TX poll */
        pTxHwQueue->uNumTotalBlksFree += pTxHwQueue->iTxTotaldiff;
    }
    /*
     * For all queues, update blocks numbers according to FwStatus information
     */
    for (uQueueId = 0; uQueueId < MAX_NUM_OF_AC; uQueueId++)
    {
        pQueueInfo = &(pTxHwQueue->aTxHwQueueInfo[uQueueId]);

        /* Update per queue number of used, free and reserved blocks. */
        txHwQueue_UpdateFreeBlocks (pTxHwQueue, uQueueId, pFreeBlocks[uQueueId]/*, &txTotalDiff*/);
        if(pQueueInfo->uNumBlksUsed > pQueueInfo->uNumBlksQuota)
        {
            SET_QUEUE_LOW_PRIORITY(uPriorityQueueBitMap, uQueueId);
        }
        else
        {
            SET_QUEUE_HIGH_PRIORITY(uPriorityQueueBitMap, uQueueId);
        }
    }
    if((pTxHwQueue->uPriorityBitMap != uPriorityQueueBitMap) && (pTxHwQueue->fUpdatePriorityMapCb != NULL))
    {
        pTxHwQueue->fUpdatePriorityMapCb(pTxHwQueue->hUpdatePriorityMapHndl, uPriorityQueueBitMap);
        pTxHwQueue->uPriorityBitMap = uPriorityQueueBitMap;
    }
    if(pTxHwQueue->iTxTotaldiff > 0)
    {
        pTxHwQueue->iTxTotaldiff = 0;
    }
    /*
     * For each busy queue, if now available indicate it in the backpressure bitmap
     */
    for (uQueueId = 0; uQueueId < MAX_NUM_OF_AC; uQueueId++)
    {
        pQueueInfo = &(pTxHwQueue->aTxHwQueueInfo[uQueueId]);

        /* If the queue was stopped */
        if (pQueueInfo->bQueueBusy)
        {
            /* Find max available blocks for this queue (0 could indicate no descriptors). */
            uAvailableBlks = txHwQueue_CheckResources (pTxHwQueue, pQueueInfo);

            /* If the required blocks and a descriptor are available,
                 set the queue's backpressure bit to indicate NOT-busy! */
            if (pQueueInfo->uNumBlksCausedBusy <= uAvailableBlks)
            {
                TRACE6(pTxHwQueue->hReport, REPORT_SEVERITY_INFORMATION, ": Queue Available, Queue=%d, ReqBlks=%d, FreeBlks=%d, UsedBlks=%d, AvailBlks=%d, UsedPkts=%d\n", uQueueId, pQueueInfo->uNumBlksCausedBusy, pTxHwQueue->uNumTotalBlksFree, pQueueInfo->uNumBlksUsed, uAvailableBlks, pTxHwQueue->uNumUsedDescriptors);
                SET_QUEUE_BACKPRESSURE(&uBackpressure, uQueueId); /* Start queue. */
                pQueueInfo->bQueueBusy = TI_FALSE;
            }
        }
    }

    /* If released queues map is not 0, send it to the upper layers (if CB available) */
    if ((uBackpressure > 0) && (pTxHwQueue->fUpdateBusyMapCb != NULL))
    {
        pTxHwQueue->fUpdateBusyMapCb (pTxHwQueue->hUpdateBusyMapHndl, uBackpressure);
    }

    return TXN_STATUS_COMPLETE;
}
Пример #4
0
/****************************************************************************
 *                  txHwQueue_AllocResources()
 ****************************************************************************
 * DESCRIPTION:
   ============
    1.  Estimate required HW-blocks number.
    2.  If the required blocks are not available or no free descriptor,
            return  STOP_CURRENT  (to stop current queue and requeue the packet).
    3.  Resources are available so update allocated blocks and descriptors counters.
    4.  If no resources for another similar packet, return STOP_NEXT (to stop current queue).
        Else, return SUCCESS
 ****************************************************************************/
ETxHwQueStatus txHwQueue_AllocResources (TI_HANDLE hTxHwQueue, TTxCtrlBlk *pTxCtrlBlk)
{
	TTxHwQueue *pTxHwQueue = (TTxHwQueue *)hTxHwQueue;
	TI_UINT32 uNumBlksToAlloc; /* The number of blocks required for the current packet. */
	TI_UINT32 uExcludedLength; /* The data length not included in the rough blocks calculation */
	TI_UINT32 uAvailableBlks;  /* Max blocks that are currently available for this queue. */
	TI_UINT32 uReservedBlks;   /* How many blocks are reserved for this queue before this allocation. */
	TI_UINT32 uQueueId = WMEQosTagToACTable[pTxCtrlBlk->tTxDescriptor.tid];
	TTxHwQueueInfo *pQueueInfo = &(pTxHwQueue->aTxHwQueueInfo[uQueueId]);


	/***********************************************************************/
	/*  Calculate packet required HW blocks.                               */
	/***********************************************************************/

	/* Divide length by 256 instead of 252 (block size) to save CPU */
	uNumBlksToAlloc = ( pTxCtrlBlk->tTxDescriptor.length + 20 ) >> 8;

	/* The length not yet included in the uNumBlksToAlloc is the sum of:
	    1) 4 bytes per block as a result of using 256 instead of 252 block size.
	    2) The remainder of the division by 256.
	    3) Overhead due to header translation, security and LLC header (subtracting ethernet header).
	*/
	uExcludedLength = (uNumBlksToAlloc << 2) + ((pTxCtrlBlk->tTxDescriptor.length + 20) & 0xFF) + MAX_HEADER_SIZE - 14;

	/* Add 1 or 2 blocks for the excluded length, according to its size */
	uNumBlksToAlloc += (uExcludedLength > 252) ? 2 : 1;

	/* Add extra blocks needed in case of fragmentation */
	uNumBlksToAlloc += BLKS_HW_ALLOC_SPARE;

	/***********************************************************************/
	/*            Check if the required resources are available            */
	/***********************************************************************/

	/* Find max available blocks for this queue (0 could indicate no descriptors). */
	uAvailableBlks = txHwQueue_CheckResources (pTxHwQueue, pQueueInfo);

	/* If we need more blocks than available, return  STOP_CURRENT (stop current queue and requeue packet). */
	if (uNumBlksToAlloc > uAvailableBlks) {
		pQueueInfo->uNumBlksCausedBusy = uNumBlksToAlloc;
		pQueueInfo->bQueueBusy = TI_TRUE;

		return TX_HW_QUE_STATUS_STOP_CURRENT;  /**** Exit! (we should stop queue and requeue packet) ****/
	}

	/***********************************************************************/
	/*                    Allocate required resources                      */
	/***********************************************************************/

	/* Update blocks numbers in Tx descriptor */
	pTxCtrlBlk->tTxDescriptor.extraMemBlks = BLKS_HW_ALLOC_SPARE;
	pTxCtrlBlk->tTxDescriptor.totalMemBlks = uNumBlksToAlloc;

	/* Update packet allocation info:  */
	pTxHwQueue->uNumUsedDescriptors++; /* Update number of packets in FW (for descriptors allocation check). */
	pTxHwQueue->uDrvTxPacketsCntr++;
	pQueueInfo->uAllocatedBlksCntr += uNumBlksToAlloc; /* For FW counter coordination. */
	uReservedBlks = pQueueInfo->uNumBlksReserved;

	/* If we are currently using less than the low threshold (i.e. we have some reserved blocks),
	    blocks allocation should reduce the reserved blocks number as follows:
	*/
	if (uReservedBlks) {

		/* If adding the allocated blocks to the used blocks will pass the low-threshold,
		    only the part up to the low-threshold is subtracted from the reserved blocks.
		    This is because blocks are reserved for the Queue only up to its low-threshold.

		      0   old used                    low      new used       high
		      |######|                         |          |            |
		      |######|                         |          |            |
		              <------------ allocated ----------->
		              <----- old reserved ---->
		                     new reserved = 0     (we passed the low threshold)
		*/
		if (uNumBlksToAlloc > uReservedBlks) {
			pQueueInfo->uNumBlksReserved = 0;
			pTxHwQueue->uNumTotalBlksReserved -= uReservedBlks; /* reduce change from total reserved.*/
		}


		/* Else, if allocating less than reserved,
		    the allocated blocks are subtracted from the reserved blocks:

		      0   old used       new used               low      high
		      |######|               |                   |        |
		      |######|               |                   |        |
		              <- allocated ->
		              <--------- old reserved ---------->
		                             <-- new reserved -->
		*/
		else {
			pQueueInfo->uNumBlksReserved -= uNumBlksToAlloc;
			pTxHwQueue->uNumTotalBlksReserved -= uNumBlksToAlloc; /* reduce change from total reserved.*/
		}
	}


	/* Update total free blocks and Queue used blocks with the allocated blocks number. */
	pTxHwQueue->uNumTotalBlksFree -= uNumBlksToAlloc;
	pQueueInfo->uNumBlksUsed += uNumBlksToAlloc;


	/* If no resources for another similar packet, return STOP_NEXT (to stop current queue). */
	/* Note: Current packet transmission is continued */
	if ( (uNumBlksToAlloc << 1) > uAvailableBlks ) {
		pQueueInfo->uNumBlksCausedBusy = uNumBlksToAlloc;
		pQueueInfo->bQueueBusy = TI_TRUE;
		return TX_HW_QUE_STATUS_STOP_NEXT;
	}

	/* Return SUCCESS (resources are available). */
	return TX_HW_QUE_STATUS_SUCCESS;
}
Пример #5
0
/****************************************************************************
 *                  txHwQueue_AllocResources()
 ****************************************************************************
 * DESCRIPTION:
   ============
    1.  Estimate required HW-blocks number.
    2.  If the required blocks are not available or no free descriptor,
            return  STOP_CURRENT  (to stop current queue and requeue the packet).
    3.  Resources are available so update allocated blocks and descriptors counters.
    4.  If no resources for another similar packet, return STOP_NEXT (to stop current queue).
        Else, return SUCCESS
 ****************************************************************************/
ETxHwQueStatus txHwQueue_AllocResources (TI_HANDLE hTxHwQueue, TTxCtrlBlk *pTxCtrlBlk)
{
    TTxHwQueue *pTxHwQueue = (TTxHwQueue *)hTxHwQueue;
    TI_UINT32 uTotalLength;    /* The current packet length plus overhead due to header translation */
    TI_UINT32 uNumBlksToAlloc; /* The number of blocks required for the current packet. */
    TI_UINT32 uExcludedLength; /* The data length not included in the rough blocks calculation */
    TI_UINT32 uAvailableBlks;  /* Max blocks that are currently available for this queue. */
    TI_UINT32 uReservedBlks;   /* How many blocks are reserved for this queue before this allocation. */
    TI_UINT32 uQueueId = WMEQosTagToACTable[pTxCtrlBlk->tTxDescriptor.tid];
    TTxHwQueueInfo *pQueueInfo = &(pTxHwQueue->aTxHwQueueInfo[uQueueId]);


    /***********************************************************************/
    /*  Calculate packet required HW blocks.                               */
    /***********************************************************************/

    uTotalLength = pTxCtrlBlk->tTxDescriptor.length + 20 + MAX_HEADER_SIZE - ETHERNET_HDR_LEN;
#ifdef TNETW1283
    if (pTxHwQueue->uHostIfCfgBitmap & HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK)
    {
        TI_UINT32 uBlockMask = ((1 << pTxHwQueue->uSdioBlkSizeShift) - 1);
        uTotalLength = (uTotalLength + uBlockMask) & (~uBlockMask);
    }
#endif
    /* Divide length by 256 instead of 252 (block size) to save CPU */
    uNumBlksToAlloc = uTotalLength >> 8;

    /* The length not yet included in the uNumBlksToAlloc is the sum of:
        1) 4 bytes per block as a result of using 256 instead of 252 block size.
        2) The remainder of the division by 256.
        3) Overhead due to header translation, security and LLC header (subtracting ethernet header).
    */
    uExcludedLength = (uNumBlksToAlloc << 2) + (uTotalLength & 0xFF);

    /* Add 1 or 2 blocks for the excluded length, according to its size */
    uNumBlksToAlloc += (uExcludedLength > 252) ? 2 : 1;

    /* Add extra blocks needed in case of fragmentation */
    uNumBlksToAlloc += pTxHwQueue->uExtraHwBlocks;

    /***********************************************************************/
    /*            Check if the required resources are available            */
    /***********************************************************************/

    /* Find max available blocks for this queue (0 could indicate no descriptors). */
    uAvailableBlks = txHwQueue_CheckResources (pTxHwQueue, pQueueInfo);

    /* If we need more blocks than available, return  STOP_CURRENT (stop current queue and requeue packet). */
    if (uNumBlksToAlloc > uAvailableBlks)
    {
        TRACE6(pTxHwQueue->hReport, REPORT_SEVERITY_INFORMATION, ": No resources, Queue=%d, ReqBlks=%d, FreeBlks=%d, UsedBlks=%d, AvailBlks=%d, UsedPkts=%d\n", uQueueId, uNumBlksToAlloc, pTxHwQueue->uNumTotalBlksFree, pQueueInfo->uNumBlksUsed, uAvailableBlks, pTxHwQueue->uNumUsedDescriptors);
        pQueueInfo->uNumBlksCausedBusy = uNumBlksToAlloc;
        pQueueInfo->bQueueBusy = TI_TRUE;

        return TX_HW_QUE_STATUS_STOP_CURRENT;  /**** Exit! (we should stop queue and requeue packet) ****/
    }

    /***********************************************************************/
    /*                    Allocate required resources                      */
    /***********************************************************************/

    /* Update blocks numbers in Tx descriptor */
#ifdef TNETW1283
    /* in 1283, no need of extra mem blocks setting to the hardware */
    /* set total blocks in the extra blocks field, FW will deliver only total blocks */

    /* !!!!!!!!!!!!!just for test - swap fields - OK for HW, fw will have the value on other field */
    pTxCtrlBlk->tTxDescriptor.totalMemBlks = uNumBlksToAlloc;
#else
    pTxCtrlBlk->tTxDescriptor.extraMemBlks = pTxHwQueue->uExtraHwBlocks;
    pTxCtrlBlk->tTxDescriptor.totalMemBlks = uNumBlksToAlloc;
#endif

    /* Update packet allocation info:  */
    pTxHwQueue->uNumUsedDescriptors++; /* Update number of packets in FW (for descriptors allocation check). */
    pTxHwQueue->uDrvTxPacketsCntr++;
    pQueueInfo->uAllocatedBlksCntr += uNumBlksToAlloc; /* For FW counter coordination. */
    uReservedBlks = pQueueInfo->uNumBlksReserved;

    /* If we are currently using less than the low threshold (i.e. we have some reserved blocks),
        blocks allocation should reduce the reserved blocks number as follows:
    */
    if (uReservedBlks)
    {

        /* If adding the allocated blocks to the used blocks will pass the low-threshold,
            only the part up to the low-threshold is subtracted from the reserved blocks.
            This is because blocks are reserved for the Queue only up to its low-threshold.

              0   old used                    low      new used       high
              |######|                         |          |            |
              |######|                         |          |            |
                      <------------ allocated ----------->
                      <----- old reserved ---->
                             new reserved = 0     (we passed the low threshold)
        */
        if (uNumBlksToAlloc > uReservedBlks)
        {
            pQueueInfo->uNumBlksReserved = 0;
            pTxHwQueue->uNumTotalBlksReserved -= uReservedBlks; /* reduce change from total reserved.*/
        }


        /* Else, if allocating less than reserved,
            the allocated blocks are subtracted from the reserved blocks:

              0   old used       new used               low      high
              |######|               |                   |        |
              |######|               |                   |        |
                      <- allocated ->
                      <--------- old reserved ---------->
                                     <-- new reserved -->
        */
        else
        {
            pQueueInfo->uNumBlksReserved -= uNumBlksToAlloc;
            pTxHwQueue->uNumTotalBlksReserved -= uNumBlksToAlloc; /* reduce change from total reserved.*/
        }
    }


    /* Update total free blocks and Queue used blocks with the allocated blocks number. */
    pTxHwQueue->uNumTotalBlksFree -= uNumBlksToAlloc;
    pQueueInfo->uNumBlksUsed += uNumBlksToAlloc;

    TRACE6(pTxHwQueue->hReport, REPORT_SEVERITY_INFORMATION, ": SUCCESS,  Queue=%d, Req-blks=%d , Free=%d, Used=%d, Reserved=%d, Accumulated=%d\n", uQueueId, uNumBlksToAlloc, pTxHwQueue->uNumTotalBlksFree, pQueueInfo->uNumBlksUsed, pQueueInfo->uNumBlksReserved, pQueueInfo->uAllocatedBlksCntr);

    /* If no resources for another similar packet, return STOP_NEXT (to stop current queue). */
    /* Note: Current packet transmission is continued */
    if ( (uNumBlksToAlloc << 1) > uAvailableBlks )
    {
        TRACE6(pTxHwQueue->hReport, REPORT_SEVERITY_INFORMATION, ": No resources for next pkt, Queue=%d, ReqBlks=%d, FreeBlks=%d, UsedBlks=%d, AvailBlks=%d, UsedPkts=%d\n", uQueueId, uNumBlksToAlloc, pTxHwQueue->uNumTotalBlksFree, pQueueInfo->uNumBlksUsed, uAvailableBlks, pTxHwQueue->uNumUsedDescriptors);
        pQueueInfo->uNumBlksCausedBusy = uNumBlksToAlloc;
        pQueueInfo->bQueueBusy = TI_TRUE;
        return TX_HW_QUE_STATUS_STOP_NEXT;
    }

    /* Return SUCCESS (resources are available). */
    return TX_HW_QUE_STATUS_SUCCESS;
}