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