linux/drivers/staging/bcm/LeakyBucket.c
<<
>>
Prefs
   1/**********************************************************************
   2*                       LEAKYBUCKET.C
   3*       This file contains the routines related to Leaky Bucket Algorithm.
   4***********************************************************************/
   5#include "headers.h"
   6
   7/*********************************************************************
   8* Function    - UpdateTokenCount()
   9*
  10* Description - This function calculates the token count for each
  11*                               channel and updates the same in Adapter strucuture.
  12*
  13* Parameters  - Adapter: Pointer to the Adapter structure.
  14*
  15* Returns     - None
  16**********************************************************************/
  17
  18static VOID UpdateTokenCount(register PMINI_ADAPTER Adapter)
  19{
  20        ULONG   liCurrentTime;
  21        INT     i = 0;
  22        struct timeval tv;
  23
  24        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "=====>\n");
  25        if(NULL == Adapter)
  26        {
  27                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Adapter found NULL!\n");
  28                return;
  29        }
  30
  31        do_gettimeofday(&tv);
  32        for(i = 0; i < NO_OF_QUEUES; i++)
  33        {
  34                if(TRUE == Adapter->PackInfo[i].bValid &&
  35                        (1 == Adapter->PackInfo[i].ucDirection))
  36                {
  37                        liCurrentTime = ((tv.tv_sec-
  38                                Adapter->PackInfo[i].stLastUpdateTokenAt.tv_sec)*1000 +
  39                                (tv.tv_usec-Adapter->PackInfo[i].stLastUpdateTokenAt.tv_usec)/
  40                                1000);
  41                        if(0!=liCurrentTime)
  42                        {
  43                                Adapter->PackInfo[i].uiCurrentTokenCount += (ULONG)
  44                                        ((Adapter->PackInfo[i].uiMaxAllowedRate) *
  45                                        ((ULONG)((liCurrentTime)))/1000);
  46                                memcpy(&Adapter->PackInfo[i].stLastUpdateTokenAt,
  47                                        &tv, sizeof(struct timeval));
  48                                Adapter->PackInfo[i].liLastUpdateTokenAt = liCurrentTime;
  49                                if((Adapter->PackInfo[i].uiCurrentTokenCount) >=
  50                                Adapter->PackInfo[i].uiMaxBucketSize)
  51                                {
  52                                        Adapter->PackInfo[i].uiCurrentTokenCount =
  53                                                Adapter->PackInfo[i].uiMaxBucketSize;
  54                                }
  55                        }
  56                }
  57        }
  58        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "<=====\n");
  59        return;
  60
  61}
  62
  63
  64/*********************************************************************
  65* Function    - IsPacketAllowedForFlow()
  66*
  67* Description - This function checks whether the given packet from the
  68*                               specified queue can be allowed for transmission by
  69*                               checking the token count.
  70*
  71* Parameters  - Adapter       : Pointer to the Adpater structure.
  72*                         - iQIndex           : The queue Identifier.
  73*                         - ulPacketLength:     Number of bytes to be transmitted.
  74*
  75* Returns     - The number of bytes allowed for transmission.
  76*
  77***********************************************************************/
  78static ULONG GetSFTokenCount(PMINI_ADAPTER Adapter, PacketInfo *psSF)
  79{
  80        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow ===>");
  81        /* Validate the parameters */
  82        if(NULL == Adapter || (psSF < Adapter->PackInfo &&
  83                (uintptr_t)psSF > (uintptr_t) &Adapter->PackInfo[HiPriority]))
  84        {
  85                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));
  86                return 0;
  87        }
  88
  89        if(FALSE != psSF->bValid && psSF->ucDirection)
  90        {
  91                if(0 != psSF->uiCurrentTokenCount)
  92                {
  93                                return psSF->uiCurrentTokenCount;
  94                }
  95                else
  96                {
  97                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Not enough tokens in queue %zd Available %u\n",
  98                                psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount);
  99                        psSF->uiPendedLast = 1;
 100                }
 101        }
 102        else
 103        {
 104                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Queue %zd not valid\n", psSF-Adapter->PackInfo);
 105        }
 106        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow <===");
 107        return 0;
 108}
 109
 110/**
 111@ingroup tx_functions
 112This function despatches packet from the specified queue.
 113@return Zero(success) or Negative value(failure)
 114*/
 115static INT SendPacketFromQueue(PMINI_ADAPTER Adapter,/**<Logical Adapter*/
 116                               PacketInfo *psSF,                /**<Queue identifier*/
 117                               struct sk_buff*  Packet) /**<Pointer to the packet to be sent*/
 118{
 119        INT     Status=STATUS_FAILURE;
 120        UINT uiIndex =0,PktLen = 0;
 121
 122        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "=====>");
 123        if(!Adapter || !Packet || !psSF)
 124        {
 125                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "Got NULL Adapter or Packet");
 126                return -EINVAL;
 127        }
 128
 129        if(psSF->liDrainCalculated==0)
 130        {
 131                psSF->liDrainCalculated = jiffies;
 132        }
 133        ///send the packet to the fifo..
 134        PktLen = Packet->len;
 135        Status = SetupNextSend(Adapter, Packet, psSF->usVCID_Value);
 136        if(Status == 0)
 137        {
 138                for(uiIndex = 0 ; uiIndex < MIBS_MAX_HIST_ENTRIES ; uiIndex++)
 139                {       if((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) && (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex)))
 140                                Adapter->aTxPktSizeHist[uiIndex]++;
 141                }
 142        }
 143        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "<=====");
 144        return Status;
 145}
 146
 147/************************************************************************
 148* Function    - CheckAndSendPacketFromIndex()
 149*
 150* Description - This function dequeues the data/control packet from the
 151*                               specified queue for transmission.
 152*
 153* Parameters  - Adapter : Pointer to the driver control structure.
 154*                         - iQIndex : The queue Identifier.
 155*
 156* Returns     - None.
 157*
 158****************************************************************************/
 159static VOID CheckAndSendPacketFromIndex(PMINI_ADAPTER Adapter, PacketInfo *psSF)
 160{
 161        struct sk_buff  *QueuePacket=NULL;
 162        char                    *pControlPacket = NULL;
 163        INT                             Status=0;
 164        int                             iPacketLen=0;
 165
 166
 167        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "%zd ====>", (psSF-Adapter->PackInfo));
 168        if((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount))//Get data packet
 169        {
 170                if(!psSF->ucDirection )
 171                        return;
 172
 173                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "UpdateTokenCount ");
 174                if(Adapter->IdleMode || Adapter->bPreparingForLowPowerMode)
 175                        return; /* in idle mode */
 176
 177                // Check for Free Descriptors
 178                if(atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS)
 179                {
 180                        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));
 181                        return ;
 182                }
 183
 184                spin_lock_bh(&psSF->SFQueueLock);
 185                QueuePacket=psSF->FirstTxQueue;
 186
 187                if(QueuePacket)
 188                {
 189                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Dequeuing Data Packet");
 190
 191                        if(psSF->bEthCSSupport)
 192                                iPacketLen = QueuePacket->len;
 193                        else
 194                                iPacketLen = QueuePacket->len-ETH_HLEN;
 195
 196                        iPacketLen<<=3;
 197                        if(iPacketLen <= GetSFTokenCount(Adapter, psSF))
 198                        {
 199                                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Allowed bytes %d",
 200                                        (iPacketLen >> 3));
 201
 202                                DEQUEUEPACKET(psSF->FirstTxQueue,psSF->LastTxQueue);
 203                                psSF->uiCurrentBytesOnHost -= (QueuePacket->len);
 204                                psSF->uiCurrentPacketsOnHost--;
 205                                atomic_dec(&Adapter->TotalPacketCount);
 206                                spin_unlock_bh(&psSF->SFQueueLock);
 207
 208                                Status = SendPacketFromQueue(Adapter, psSF, QueuePacket);
 209                                psSF->uiPendedLast = FALSE;
 210                        }
 211                        else
 212                        {
 213                                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo);
 214                                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n",
 215                                        psSF->uiCurrentTokenCount, iPacketLen);
 216                                //this part indicates that becuase of non-availability of the tokens
 217                                //pkt has not been send out hence setting the pending flag indicating the host to send it out
 218                                //first next iteration  .
 219                                psSF->uiPendedLast = TRUE;
 220                                spin_unlock_bh(&psSF->SFQueueLock);
 221                        }
 222                }
 223                else
 224                {
 225                        spin_unlock_bh(&psSF->SFQueueLock);
 226                }
 227        }
 228        else
 229        {
 230
 231                if((atomic_read(&Adapter->CurrNumFreeTxDesc) > 0 ) &&
 232                        (atomic_read(&Adapter->index_rd_txcntrlpkt) !=
 233                         atomic_read(&Adapter->index_wr_txcntrlpkt))
 234                        )
 235                {
 236                        pControlPacket = Adapter->txctlpacket
 237                        [(atomic_read(&Adapter->index_rd_txcntrlpkt)%MAX_CNTRL_PKTS)];
 238                        if(pControlPacket)
 239                        {
 240                                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Sending Control packet");
 241                                Status = SendControlPacket(Adapter, pControlPacket);
 242                                if(STATUS_SUCCESS==Status)
 243                                {
 244                                        spin_lock_bh(&psSF->SFQueueLock);
 245                                        psSF->NumOfPacketsSent++;
 246                                        psSF->uiSentBytes+=((PLEADER)pControlPacket)->PLength;
 247                                        psSF->uiSentPackets++;
 248                                        atomic_dec(&Adapter->TotalPacketCount);
 249                                        psSF->uiCurrentBytesOnHost -= ((PLEADER)pControlPacket)->PLength;
 250                                        psSF->uiCurrentPacketsOnHost--;
 251                                        atomic_inc(&Adapter->index_rd_txcntrlpkt);
 252                                        spin_unlock_bh(&psSF->SFQueueLock);
 253                                }
 254                                else
 255                                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "SendControlPacket Failed\n");
 256                        }
 257                        else
 258                        {
 259                                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " Control Pkt is not available, Indexing is wrong....");
 260                        }
 261                }
 262        }
 263}
 264
 265
 266/*******************************************************************
 267* Function    - transmit_packets()
 268*
 269* Description - This function transmits the packets from different
 270*                               queues, if free descriptors are available on target.
 271*
 272* Parameters  - Adapter:  Pointer to the Adapter structure.
 273*
 274* Returns     - None.
 275********************************************************************/
 276VOID transmit_packets(PMINI_ADAPTER Adapter)
 277{
 278        UINT    uiPrevTotalCount = 0;
 279        int iIndex = 0;
 280
 281        BOOLEAN exit_flag = TRUE ;
 282
 283        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "=====>");
 284
 285        if(NULL == Adapter)
 286        {
 287                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX,TX_PACKETS, DBG_LVL_ALL, "Got NULL Adapter");
 288                return;
 289        }
 290        if(Adapter->device_removed == TRUE)
 291        {
 292                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device removed");
 293                return;
 294        }
 295
 296    BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nUpdateTokenCount ====>\n");
 297
 298        UpdateTokenCount(Adapter);
 299
 300    BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nPruneQueueAllSF ====>\n");
 301
 302        PruneQueueAllSF(Adapter);
 303
 304        uiPrevTotalCount = atomic_read(&Adapter->TotalPacketCount);
 305
 306        for(iIndex=HiPriority;iIndex>=0;iIndex--)
 307        {
 308                if(     !uiPrevTotalCount || (TRUE == Adapter->device_removed))
 309                                break;
 310
 311                if(Adapter->PackInfo[iIndex].bValid &&
 312                        Adapter->PackInfo[iIndex].uiPendedLast &&
 313                        Adapter->PackInfo[iIndex].uiCurrentBytesOnHost)
 314                {
 315                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
 316                        CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
 317                        uiPrevTotalCount--;
 318                }
 319        }
 320
 321        while(uiPrevTotalCount > 0 && !Adapter->device_removed)
 322        {
 323                exit_flag = TRUE ;
 324                        //second iteration to parse non-pending queues
 325                for(iIndex=HiPriority;iIndex>=0;iIndex--)
 326                {
 327                        if( !uiPrevTotalCount || (TRUE == Adapter->device_removed))
 328                                        break;
 329
 330                        if(Adapter->PackInfo[iIndex].bValid &&
 331                                Adapter->PackInfo[iIndex].uiCurrentBytesOnHost &&
 332                                !Adapter->PackInfo[iIndex].uiPendedLast )
 333                        {
 334                                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
 335                                CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
 336                                uiPrevTotalCount--;
 337                                exit_flag = FALSE;
 338                        }
 339                }
 340
 341                if(Adapter->IdleMode || Adapter->bPreparingForLowPowerMode)
 342                {
 343                        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "In Idle Mode\n");
 344                        break;
 345                }
 346                if(exit_flag == TRUE )
 347                    break ;
 348        }/* end of inner while loop */
 349
 350        update_per_cid_rx  (Adapter);
 351        Adapter->txtransmit_running = 0;
 352        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<======");
 353}
 354