blob: 877cf0b2bee1bb44a3cb86b3d71b00abd7e1401d [file] [log] [blame]
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001/**********************************************************************
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
Kevin McKinney29794602012-05-26 12:05:12 -040018static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070019{
20 ULONG liCurrentTime;
21 INT i = 0;
22 struct timeval tv;
23
Ceri James89babcc2012-10-23 13:51:56 +010024 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
25 "=====>\n");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070026 if(NULL == Adapter)
27 {
Ceri James89babcc2012-10-23 13:51:56 +010028 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS,
29 DBG_LVL_ALL, "Adapter found NULL!\n");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070030 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***********************************************************************/
Kevin McKinney29794602012-05-26 12:05:12 -040080static ULONG GetSFTokenCount(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070081{
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 &&
Arnd Bergmann9f1c75a2010-09-30 10:24:11 +020085 (uintptr_t)psSF > (uintptr_t) &Adapter->PackInfo[HiPriority]))
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070086 {
Stephen Hemmingerc5ebe222010-11-01 08:42:44 -040087 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));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070088 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 {
Stephen Hemmingerc5ebe222010-11-01 08:42:44 -040099 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Not enough tokens in queue %zd Available %u\n",
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700100 psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount);
101 psSF->uiPendedLast = 1;
102 }
103 }
104 else
105 {
Stephen Hemmingerc5ebe222010-11-01 08:42:44 -0400106 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Queue %zd not valid\n", psSF-Adapter->PackInfo);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700107 }
108 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow <===");
109 return 0;
110}
111
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700112/**
113@ingroup tx_functions
114This function despatches packet from the specified queue.
115@return Zero(success) or Negative value(failure)
116*/
Kevin McKinney29794602012-05-26 12:05:12 -0400117static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,/**<Logical Adapter*/
Kevin McKinney0b3edf72012-05-26 12:05:01 -0400118 struct bcm_packet_info *psSF, /**<Queue identifier*/
Stephen Hemminger20f48652010-10-31 23:52:36 -0400119 struct sk_buff* Packet) /**<Pointer to the packet to be sent*/
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700120{
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****************************************************************************/
Kevin McKinney29794602012-05-26 12:05:12 -0400161static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700162{
163 struct sk_buff *QueuePacket=NULL;
164 char *pControlPacket = NULL;
165 INT Status=0;
166 int iPacketLen=0;
167
168
Stephen Hemmingerc5ebe222010-11-01 08:42:44 -0400169 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "%zd ====>", (psSF-Adapter->PackInfo));
Arnd Bergmann9f1c75a2010-09-30 10:24:11 +0200170 if((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount))//Get data packet
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700171 {
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)
Stephen Hemminger5cf084f2010-11-01 13:57:35 -0400177 return; /* in idle mode */
178
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700179 // 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
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700186 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 {
Stephen Hemmingerc5ebe222010-11-01 08:42:44 -0400215 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700216 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n",
217 psSF->uiCurrentTokenCount, iPacketLen);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300218 //this part indicates that because of non-availability of the tokens
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700219 //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++;
Kevin McKinneyff352042012-05-26 12:05:11 -0400248 psSF->uiSentBytes+=((struct bcm_leader *)pControlPacket)->PLength;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700249 psSF->uiSentPackets++;
250 atomic_dec(&Adapter->TotalPacketCount);
Kevin McKinneyff352042012-05-26 12:05:11 -0400251 psSF->uiCurrentBytesOnHost -= ((struct bcm_leader *)pControlPacket)->PLength;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700252 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 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700265}
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********************************************************************/
Kevin McKinney29794602012-05-26 12:05:12 -0400278VOID transmit_packets(struct bcm_mini_adapter *Adapter)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700279{
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 */
Stephen Hemminger5cf084f2010-11-01 13:57:35 -0400351
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700352 update_per_cid_rx (Adapter);
353 Adapter->txtransmit_running = 0;
354 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<======");
355}