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