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 PMINI_ADAPTER Adapter)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 ***********************************************************************/
GetSFTokenCount(PMINI_ADAPTER Adapter,PacketInfo * psSF)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 */
SendPacketFromQueue(PMINI_ADAPTER Adapter,PacketInfo * psSF,struct sk_buff * Packet)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 ****************************************************************************/
CheckAndSendPacketFromIndex(PMINI_ADAPTER Adapter,PacketInfo * psSF)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 ********************************************************************/
transmit_packets(PMINI_ADAPTER Adapter)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 }
354