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