Merge branch 'stable/cleanups-3.2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[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 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
112 This function despatches packet from the specified queue.
113 @return Zero(success) or Negative value(failure)
114 */
115 static 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 ****************************************************************************/
159 static 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 because 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 ********************************************************************/
276 VOID 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 }