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
UpdateTokenCount(register struct bcm_mini_adapter * Adapter)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 ***********************************************************************/
GetSFTokenCount(struct bcm_mini_adapter * Adapter,struct bcm_packet_info * psSF)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 */
SendPacketFromQueue(struct bcm_mini_adapter * Adapter,struct bcm_packet_info * psSF,struct sk_buff * Packet)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 ****************************************************************************/
CheckAndSendPacketFromIndex(struct bcm_mini_adapter * Adapter,struct bcm_packet_info * psSF)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 ********************************************************************/
transmit_packets(struct bcm_mini_adapter * Adapter)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 }
356