Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
LeakyBucket.c
Go to the documentation of this file.
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, "=====>\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(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *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 
115 static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,
116  struct bcm_packet_info *psSF,
117  struct sk_buff* Packet)
118 {
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  }
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(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *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
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 
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
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+=((struct bcm_leader *)pControlPacket)->PLength;
247  psSF->uiSentPackets++;
248  atomic_dec(&Adapter->TotalPacketCount);
249  psSF->uiCurrentBytesOnHost -= ((struct bcm_leader *)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 ********************************************************************/
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 }