• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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