diff options
Diffstat (limited to 'drivers/staging/bcm/LeakyBucket.c')
| -rw-r--r-- | drivers/staging/bcm/LeakyBucket.c | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/drivers/staging/bcm/LeakyBucket.c b/drivers/staging/bcm/LeakyBucket.c new file mode 100644 index 00000000000..f95b06713a2 --- /dev/null +++ b/drivers/staging/bcm/LeakyBucket.c @@ -0,0 +1,317 @@ +/********************************************************************** +* LEAKYBUCKET.C +* This file contains the routines related to Leaky Bucket Algorithm. +***********************************************************************/ +#include "headers.h" + +/********************************************************************* +* Function - UpdateTokenCount() +* +* Description - This function calculates the token count for each +* channel and updates the same in Adapter strucuture. +* +* Parameters - Adapter: Pointer to the Adapter structure. +* +* Returns - None +**********************************************************************/ + +static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter) +{ + ULONG liCurrentTime; + INT i = 0; + struct timeval tv; + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, + "=====>\n"); + if (NULL == Adapter) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, + DBG_LVL_ALL, "Adapter found NULL!\n"); + return; + } + + do_gettimeofday(&tv); + for (i = 0; i < NO_OF_QUEUES; i++) { + if (TRUE == Adapter->PackInfo[i].bValid && + (1 == Adapter->PackInfo[i].ucDirection)) { + liCurrentTime = ((tv.tv_sec- + Adapter->PackInfo[i].stLastUpdateTokenAt.tv_sec)*1000 + + (tv.tv_usec-Adapter->PackInfo[i].stLastUpdateTokenAt.tv_usec)/ + 1000); + if (0 != liCurrentTime) { + Adapter->PackInfo[i].uiCurrentTokenCount += (ULONG) + ((Adapter->PackInfo[i].uiMaxAllowedRate) * + ((ULONG)((liCurrentTime)))/1000); + memcpy(&Adapter->PackInfo[i].stLastUpdateTokenAt, + &tv, sizeof(struct timeval)); + Adapter->PackInfo[i].liLastUpdateTokenAt = liCurrentTime; + if (Adapter->PackInfo[i].uiCurrentTokenCount >= + Adapter->PackInfo[i].uiMaxBucketSize) { + Adapter->PackInfo[i].uiCurrentTokenCount = + Adapter->PackInfo[i].uiMaxBucketSize; + } + } + } + } + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "<=====\n"); + return; + +} + + +/********************************************************************* +* Function - IsPacketAllowedForFlow() +* +* Description - This function checks whether the given packet from the +* specified queue can be allowed for transmission by +* checking the token count. +* +* Parameters - Adapter : Pointer to the Adpater structure. +* - iQIndex : The queue Identifier. +* - ulPacketLength: Number of bytes to be transmitted. +* +* Returns - The number of bytes allowed for transmission. +* +***********************************************************************/ +static ULONG GetSFTokenCount(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF) +{ + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow ===>"); + /* Validate the parameters */ + if (NULL == Adapter || (psSF < Adapter->PackInfo && + (uintptr_t)psSF > (uintptr_t) &Adapter->PackInfo[HiPriority])) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Got wrong Parameters:Adapter: %p, QIndex: %zd\n", Adapter, (psSF-Adapter->PackInfo)); + return 0; + } + + if (false != psSF->bValid && psSF->ucDirection) { + if (0 != psSF->uiCurrentTokenCount) { + return psSF->uiCurrentTokenCount; + } else { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Not enough tokens in queue %zd Available %u\n", + psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount); + psSF->uiPendedLast = 1; + } + } else { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Queue %zd not valid\n", psSF-Adapter->PackInfo); + } + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow <==="); + return 0; +} + +/** +@ingroup tx_functions +This function despatches packet from the specified queue. +@return Zero(success) or Negative value(failure) +*/ +static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,/**<Logical Adapter*/ + struct bcm_packet_info *psSF, /**<Queue identifier*/ + struct sk_buff *Packet) /**<Pointer to the packet to be sent*/ +{ + INT Status = STATUS_FAILURE; + UINT uiIndex = 0, PktLen = 0; + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "=====>"); + if (!Adapter || !Packet || !psSF) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "Got NULL Adapter or Packet"); + return -EINVAL; + } + + if (psSF->liDrainCalculated == 0) + psSF->liDrainCalculated = jiffies; + /* send the packet to the fifo.. */ + PktLen = Packet->len; + Status = SetupNextSend(Adapter, Packet, psSF->usVCID_Value); + if (Status == 0) { + for (uiIndex = 0; uiIndex < MIBS_MAX_HIST_ENTRIES; uiIndex++) { + if ((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) && (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex))) + Adapter->aTxPktSizeHist[uiIndex]++; + } + } + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "<====="); + return Status; +} + +/************************************************************************ +* Function - CheckAndSendPacketFromIndex() +* +* Description - This function dequeues the data/control packet from the +* specified queue for transmission. +* +* Parameters - Adapter : Pointer to the driver control structure. +* - iQIndex : The queue Identifier. +* +* Returns - None. +* +****************************************************************************/ +static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF) +{ + struct sk_buff *QueuePacket = NULL; + char *pControlPacket = NULL; + INT Status = 0; + int iPacketLen = 0; + + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "%zd ====>", (psSF-Adapter->PackInfo)); + if ((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount)) { /* Get data packet */ + if (!psSF->ucDirection) + return; + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "UpdateTokenCount "); + if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) + return; /* in idle mode */ + + /* Check for Free Descriptors */ + if (atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " No Free Tx Descriptor(%d) is available for Data pkt..", atomic_read(&Adapter->CurrNumFreeTxDesc)); + return; + } + + spin_lock_bh(&psSF->SFQueueLock); + QueuePacket = psSF->FirstTxQueue; + + if (QueuePacket) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Dequeuing Data Packet"); + + if (psSF->bEthCSSupport) + iPacketLen = QueuePacket->len; + else + iPacketLen = QueuePacket->len-ETH_HLEN; + + iPacketLen <<= 3; + if (iPacketLen <= GetSFTokenCount(Adapter, psSF)) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Allowed bytes %d", + (iPacketLen >> 3)); + + DEQUEUEPACKET(psSF->FirstTxQueue, psSF->LastTxQueue); + psSF->uiCurrentBytesOnHost -= (QueuePacket->len); + psSF->uiCurrentPacketsOnHost--; + atomic_dec(&Adapter->TotalPacketCount); + spin_unlock_bh(&psSF->SFQueueLock); + + Status = SendPacketFromQueue(Adapter, psSF, QueuePacket); + psSF->uiPendedLast = false; + } else { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n", + psSF->uiCurrentTokenCount, iPacketLen); + /* + this part indicates that because of non-availability of the tokens + pkt has not been send out hence setting the pending flag indicating the host to send it out + first next iteration. + */ + psSF->uiPendedLast = TRUE; + spin_unlock_bh(&psSF->SFQueueLock); + } + } else { + spin_unlock_bh(&psSF->SFQueueLock); + } + } else { + + if ((atomic_read(&Adapter->CurrNumFreeTxDesc) > 0) && + (atomic_read(&Adapter->index_rd_txcntrlpkt) != + atomic_read(&Adapter->index_wr_txcntrlpkt))) { + pControlPacket = Adapter->txctlpacket + [(atomic_read(&Adapter->index_rd_txcntrlpkt)%MAX_CNTRL_PKTS)]; + if (pControlPacket) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Sending Control packet"); + Status = SendControlPacket(Adapter, pControlPacket); + if (STATUS_SUCCESS == Status) { + spin_lock_bh(&psSF->SFQueueLock); + psSF->NumOfPacketsSent++; + psSF->uiSentBytes += ((struct bcm_leader *)pControlPacket)->PLength; + psSF->uiSentPackets++; + atomic_dec(&Adapter->TotalPacketCount); + psSF->uiCurrentBytesOnHost -= ((struct bcm_leader *)pControlPacket)->PLength; + psSF->uiCurrentPacketsOnHost--; + atomic_inc(&Adapter->index_rd_txcntrlpkt); + spin_unlock_bh(&psSF->SFQueueLock); + } else { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "SendControlPacket Failed\n"); + } + } else { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " Control Pkt is not available, Indexing is wrong...."); + } + } + } +} + + +/******************************************************************* +* Function - transmit_packets() +* +* Description - This function transmits the packets from different +* queues, if free descriptors are available on target. +* +* Parameters - Adapter: Pointer to the Adapter structure. +* +* Returns - None. +********************************************************************/ +VOID transmit_packets(struct bcm_mini_adapter *Adapter) +{ + UINT uiPrevTotalCount = 0; + int iIndex = 0; + + bool exit_flag = TRUE; + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "=====>"); + + if (NULL == Adapter) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Got NULL Adapter"); + return; + } + if (Adapter->device_removed == TRUE) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device removed"); + return; + } + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nUpdateTokenCount ====>\n"); + + UpdateTokenCount(Adapter); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nPruneQueueAllSF ====>\n"); + + PruneQueueAllSF(Adapter); + + uiPrevTotalCount = atomic_read(&Adapter->TotalPacketCount); + + for (iIndex = HiPriority; iIndex >= 0; iIndex--) { + if (!uiPrevTotalCount || (TRUE == Adapter->device_removed)) + break; + + if (Adapter->PackInfo[iIndex].bValid && + Adapter->PackInfo[iIndex].uiPendedLast && + Adapter->PackInfo[iIndex].uiCurrentBytesOnHost) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex.."); + CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]); + uiPrevTotalCount--; + } + } + + while (uiPrevTotalCount > 0 && !Adapter->device_removed) { + exit_flag = TRUE; + /* second iteration to parse non-pending queues */ + for (iIndex = HiPriority; iIndex >= 0; iIndex--) { + if (!uiPrevTotalCount || (TRUE == Adapter->device_removed)) + break; + + if (Adapter->PackInfo[iIndex].bValid && + Adapter->PackInfo[iIndex].uiCurrentBytesOnHost && + !Adapter->PackInfo[iIndex].uiPendedLast) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex.."); + CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]); + uiPrevTotalCount--; + exit_flag = false; + } + } + + if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "In Idle Mode\n"); + break; + } + if (exit_flag == TRUE) + break; + } /* end of inner while loop */ + + update_per_cid_rx(Adapter); + Adapter->txtransmit_running = 0; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<======"); +} |
