Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
[pandora-kernel.git] / drivers / staging / bcm / LeakyBucket.c
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
18 static 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 ***********************************************************************/
78 static __inline 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: %ld\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 %ld 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 %ld 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 static __inline void RemovePacketFromQueue(PacketInfo *pPackInfo , struct sk_buff *Packet)
111 {
112         struct sk_buff *psQueueCurrent=NULL, *psLastQueueNode=NULL;
113         psQueueCurrent = pPackInfo->FirstTxQueue;
114         while(psQueueCurrent)
115         {
116                 if(Packet == psQueueCurrent)
117                 {
118                         if(psQueueCurrent == pPackInfo->FirstTxQueue)
119                         {
120                                 pPackInfo->FirstTxQueue=psQueueCurrent->next;
121                                 if(psQueueCurrent==pPackInfo->LastTxQueue)
122                                         pPackInfo->LastTxQueue=NULL;
123                         }
124                         else
125                         {
126                                 psLastQueueNode->next=psQueueCurrent->next;
127                         }
128                         break;
129                 }
130                 psLastQueueNode = psQueueCurrent;
131                 psQueueCurrent=psQueueCurrent->next;
132         }
133 }
134 /**
135 @ingroup tx_functions
136 This function despatches packet from the specified queue.
137 @return Zero(success) or Negative value(failure)
138 */
139 static __inline INT SendPacketFromQueue(PMINI_ADAPTER Adapter,/**<Logical Adapter*/
140                                                                 PacketInfo *psSF,               /**<Queue identifier*/
141                                                                 struct sk_buff*  Packet)        /**<Pointer to the packet to be sent*/
142 {
143         INT     Status=STATUS_FAILURE;
144         UINT uiIndex =0,PktLen = 0;
145
146         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "=====>");
147         if(!Adapter || !Packet || !psSF)
148         {
149                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "Got NULL Adapter or Packet");
150                 return -EINVAL;
151         }
152
153         if(psSF->liDrainCalculated==0)
154         {
155                 psSF->liDrainCalculated = jiffies;
156         }
157         ///send the packet to the fifo..
158         PktLen = Packet->len;
159         Status = SetupNextSend(Adapter, Packet, psSF->usVCID_Value);
160         if(Status == 0)
161         {
162                 for(uiIndex = 0 ; uiIndex < MIBS_MAX_HIST_ENTRIES ; uiIndex++)
163                 {       if((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) && (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex)))
164                                 Adapter->aTxPktSizeHist[uiIndex]++;
165                 }
166         }
167         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "<=====");
168         return Status;
169 }
170
171 /************************************************************************
172 * Function    - CheckAndSendPacketFromIndex()
173 *
174 * Description - This function dequeues the data/control packet from the
175 *                               specified queue for transmission.
176 *
177 * Parameters  - Adapter : Pointer to the driver control structure.
178 *                         - iQIndex : The queue Identifier.
179 *
180 * Returns     - None.
181 *
182 ****************************************************************************/
183 static __inline VOID CheckAndSendPacketFromIndex
184 (PMINI_ADAPTER Adapter, PacketInfo *psSF)
185 {
186         struct sk_buff  *QueuePacket=NULL;
187         char                    *pControlPacket = NULL;
188         INT                             Status=0;
189         int                             iPacketLen=0;
190
191
192         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "%ld ====>", (psSF-Adapter->PackInfo));
193         if((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount))//Get data packet
194         {
195                 if(!psSF->ucDirection )
196                         return;
197
198                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "UpdateTokenCount ");
199                 if(Adapter->IdleMode || Adapter->bPreparingForLowPowerMode)
200                 {
201                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle Mode..Hence blocking Data Packets..\n");
202                         return;
203                 }
204                 // Check for Free Descriptors
205                 if(atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS)
206                 {
207                         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));
208                         return ;
209                 }
210
211 #if 0
212                 PruneQueue(Adapter,(psSF-Adapter->PackInfo));
213 #endif
214                 spin_lock_bh(&psSF->SFQueueLock);
215                 QueuePacket=psSF->FirstTxQueue;
216
217                 if(QueuePacket)
218                 {
219                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Dequeuing Data Packet");
220
221                         if(psSF->bEthCSSupport)
222                                 iPacketLen = QueuePacket->len;
223                         else
224                                 iPacketLen = QueuePacket->len-ETH_HLEN;
225
226                         iPacketLen<<=3;
227                         if(iPacketLen <= GetSFTokenCount(Adapter, psSF))
228                         {
229                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Allowed bytes %d",
230                                         (iPacketLen >> 3));
231
232                                 DEQUEUEPACKET(psSF->FirstTxQueue,psSF->LastTxQueue);
233                                 psSF->uiCurrentBytesOnHost -= (QueuePacket->len);
234                                 psSF->uiCurrentPacketsOnHost--;
235                                 atomic_dec(&Adapter->TotalPacketCount);
236                                 spin_unlock_bh(&psSF->SFQueueLock);
237
238                                 Status = SendPacketFromQueue(Adapter, psSF, QueuePacket);
239                                 psSF->uiPendedLast = FALSE;
240                         }
241                         else
242                         {
243                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %ld\n", psSF-Adapter->PackInfo);
244                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n",
245                                         psSF->uiCurrentTokenCount, iPacketLen);
246                                 //this part indicates that becuase of non-availability of the tokens
247                                 //pkt has not been send out hence setting the pending flag indicating the host to send it out
248                                 //first next iteration  .
249                                 psSF->uiPendedLast = TRUE;
250                                 spin_unlock_bh(&psSF->SFQueueLock);
251                         }
252                 }
253                 else
254                 {
255                         spin_unlock_bh(&psSF->SFQueueLock);
256                 }
257         }
258         else
259         {
260
261                 if((atomic_read(&Adapter->CurrNumFreeTxDesc) > 0 ) &&
262                         (atomic_read(&Adapter->index_rd_txcntrlpkt) !=
263                          atomic_read(&Adapter->index_wr_txcntrlpkt))
264                         )
265                 {
266                         pControlPacket = Adapter->txctlpacket
267                         [(atomic_read(&Adapter->index_rd_txcntrlpkt)%MAX_CNTRL_PKTS)];
268                         if(pControlPacket)
269                         {
270                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Sending Control packet");
271                                 Status = SendControlPacket(Adapter, pControlPacket);
272                                 if(STATUS_SUCCESS==Status)
273                                 {
274                                         spin_lock_bh(&psSF->SFQueueLock);
275                                         psSF->NumOfPacketsSent++;
276                                         psSF->uiSentBytes+=((PLEADER)pControlPacket)->PLength;
277                                         psSF->uiSentPackets++;
278                                         atomic_dec(&Adapter->TotalPacketCount);
279                                         psSF->uiCurrentBytesOnHost -= ((PLEADER)pControlPacket)->PLength;
280                                         psSF->uiCurrentPacketsOnHost--;
281                                         atomic_inc(&Adapter->index_rd_txcntrlpkt);
282                                         spin_unlock_bh(&psSF->SFQueueLock);
283                                 }
284                                 else
285                                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "SendControlPacket Failed\n");
286                         }
287                         else
288                         {
289                                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " Control Pkt is not available, Indexing is wrong....");
290                         }
291                 }
292         }
293
294         if(Status != STATUS_SUCCESS)    //Tx of data packet to device Failed
295         {
296                 if(Adapter->bcm_jiffies == 0)
297                         Adapter->bcm_jiffies = jiffies;
298         }
299         else
300         {
301                 Adapter->bcm_jiffies = 0;
302         }
303         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<=====");
304 }
305
306
307 /*******************************************************************
308 * Function    - transmit_packets()
309 *
310 * Description - This function transmits the packets from different
311 *                               queues, if free descriptors are available on target.
312 *
313 * Parameters  - Adapter:  Pointer to the Adapter structure.
314 *
315 * Returns     - None.
316 ********************************************************************/
317 VOID transmit_packets(PMINI_ADAPTER Adapter)
318 {
319         UINT    uiPrevTotalCount = 0;
320         int iIndex = 0;
321
322         BOOLEAN exit_flag = TRUE ;
323
324         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "=====>");
325
326         if(NULL == Adapter)
327         {
328                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX,TX_PACKETS, DBG_LVL_ALL, "Got NULL Adapter");
329                 return;
330         }
331         if(Adapter->device_removed == TRUE)
332         {
333                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device removed");
334                 return;
335         }
336
337     BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nUpdateTokenCount ====>\n");
338
339         UpdateTokenCount(Adapter);
340
341     BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nPruneQueueAllSF ====>\n");
342
343         PruneQueueAllSF(Adapter);
344
345         uiPrevTotalCount = atomic_read(&Adapter->TotalPacketCount);
346
347         for(iIndex=HiPriority;iIndex>=0;iIndex--)
348         {
349                 if(     !uiPrevTotalCount || (TRUE == Adapter->device_removed))
350                                 break;
351
352                 if(Adapter->PackInfo[iIndex].bValid &&
353                         Adapter->PackInfo[iIndex].uiPendedLast &&
354                         Adapter->PackInfo[iIndex].uiCurrentBytesOnHost)
355                 {
356                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
357                         CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
358                         uiPrevTotalCount--;
359                 }
360         }
361
362         while(uiPrevTotalCount > 0 && !Adapter->device_removed)
363         {
364                 exit_flag = TRUE ;
365                         //second iteration to parse non-pending queues
366                 for(iIndex=HiPriority;iIndex>=0;iIndex--)
367                 {
368                         if( !uiPrevTotalCount || (TRUE == Adapter->device_removed))
369                                         break;
370
371                         if(Adapter->PackInfo[iIndex].bValid &&
372                                 Adapter->PackInfo[iIndex].uiCurrentBytesOnHost &&
373                                 !Adapter->PackInfo[iIndex].uiPendedLast )
374                         {
375                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
376                                 CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
377                                 uiPrevTotalCount--;
378                                 exit_flag = FALSE;
379                         }
380                 }
381
382                 if(Adapter->IdleMode || Adapter->bPreparingForLowPowerMode)
383                 {
384                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "In Idle Mode\n");
385                         break;
386                 }
387                 if(exit_flag == TRUE )
388                     break ;
389         }/* end of inner while loop */
390         if(Adapter->bcm_jiffies == 0 &&
391                 atomic_read(&Adapter->TotalPacketCount) != 0 &&
392                 uiPrevTotalCount == atomic_read(&Adapter->TotalPacketCount))
393         {
394                 Adapter->bcm_jiffies = jiffies;
395         }
396         update_per_cid_rx  (Adapter);
397         Adapter->txtransmit_running = 0;
398         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<======");
399 }