• 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  * UpdateTokenCount() - Calculates the token count for each channel
9  * and updates the same in Adapter structure
10  * @Adapter:	Pointer to the Adapter structure.
11  *
12  * Return: None
13  */
UpdateTokenCount(register struct bcm_mini_adapter * Adapter)14 static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter)
15 {
16 	ULONG liCurrentTime;
17 	INT i = 0;
18 	struct timeval tv;
19 	struct bcm_packet_info *curr_pi;
20 
21 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
22 			"=====>\n");
23 	if (NULL == Adapter) {
24 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS,
25 				DBG_LVL_ALL, "Adapter found NULL!\n");
26 		return;
27 	}
28 
29 	do_gettimeofday(&tv);
30 	for (i = 0; i < NO_OF_QUEUES; i++) {
31 		curr_pi = &Adapter->PackInfo[i];
32 
33 		if (TRUE == curr_pi->bValid && (1 == curr_pi->ucDirection)) {
34 			liCurrentTime = ((tv.tv_sec -
35 				curr_pi->stLastUpdateTokenAt.tv_sec)*1000 +
36 				(tv.tv_usec - curr_pi->stLastUpdateTokenAt.tv_usec) /
37 				1000);
38 			if (0 != liCurrentTime) {
39 				curr_pi->uiCurrentTokenCount += (ULONG)
40 					((curr_pi->uiMaxAllowedRate) *
41 					((ULONG)((liCurrentTime)))/1000);
42 				memcpy(&curr_pi->stLastUpdateTokenAt, &tv,
43 				       sizeof(struct timeval));
44 				curr_pi->liLastUpdateTokenAt = liCurrentTime;
45 				if (curr_pi->uiCurrentTokenCount >=
46 				    curr_pi->uiMaxBucketSize) {
47 					curr_pi->uiCurrentTokenCount =
48 						curr_pi->uiMaxBucketSize;
49 				}
50 			}
51 		}
52 	}
53 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
54 			"<=====\n");
55 }
56 
57 
58 /**
59  * IsPacketAllowedForFlow() - This function checks whether the given
60  * packet from the specified queue can be allowed for transmission by
61  * checking the token count.
62  * @Adapter:		Pointer to the Adpater structure.
63  * @iQIndex:		The queue Identifier.
64  * @ulPacketLength:	Number of bytes to be transmitted.
65  *
66  * Returns: The number of bytes allowed for transmission.
67  */
GetSFTokenCount(struct bcm_mini_adapter * Adapter,struct bcm_packet_info * psSF)68 static ULONG GetSFTokenCount(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF)
69 {
70 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
71 			"IsPacketAllowedForFlow ===>");
72 
73 	/* Validate the parameters */
74 	if (NULL == Adapter || (psSF < Adapter->PackInfo &&
75 	    (uintptr_t)psSF > (uintptr_t) &Adapter->PackInfo[HiPriority])) {
76 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
77 				"IPAFF: Got wrong Parameters:Adapter: %p, QIndex: %zd\n",
78 				Adapter, (psSF-Adapter->PackInfo));
79 		return 0;
80 	}
81 
82 	if (false != psSF->bValid && psSF->ucDirection) {
83 		if (0 != psSF->uiCurrentTokenCount) {
84 			return psSF->uiCurrentTokenCount;
85 		} else {
86 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS,
87 					DBG_LVL_ALL,
88 					"Not enough tokens in queue %zd Available %u\n",
89 					psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount);
90 			psSF->uiPendedLast = 1;
91 		}
92 	} else {
93 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
94 				"IPAFF: Queue %zd not valid\n",
95 				psSF-Adapter->PackInfo);
96 	}
97 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
98 			"IsPacketAllowedForFlow <===");
99 	return 0;
100 }
101 
102 /**
103 @ingroup tx_functions
104 This function despatches packet from the specified queue.
105 @return Zero(success) or Negative value(failure)
106 */
SendPacketFromQueue(struct bcm_mini_adapter * Adapter,struct bcm_packet_info * psSF,struct sk_buff * Packet)107 static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,/**<Logical Adapter*/
108 			       struct bcm_packet_info *psSF, /**<Queue identifier*/
109 			       struct sk_buff *Packet)	/**<Pointer to the packet to be sent*/
110 {
111 	INT Status = STATUS_FAILURE;
112 	UINT uiIndex = 0, PktLen = 0;
113 
114 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL,
115 			"=====>");
116 	if (!Adapter || !Packet || !psSF) {
117 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL,
118 				"Got NULL Adapter or Packet");
119 		return -EINVAL;
120 	}
121 
122 	if (psSF->liDrainCalculated == 0)
123 		psSF->liDrainCalculated = jiffies;
124 	/* send the packet to the fifo.. */
125 	PktLen = Packet->len;
126 	Status = SetupNextSend(Adapter, Packet, psSF->usVCID_Value);
127 	if (Status == 0) {
128 		for (uiIndex = 0; uiIndex < MIBS_MAX_HIST_ENTRIES; uiIndex++) {
129 			if ((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) &&
130 			    (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex)))
131 				Adapter->aTxPktSizeHist[uiIndex]++;
132 		}
133 	}
134 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL,
135 			"<=====");
136 	return Status;
137 }
138 
get_data_packet(struct bcm_mini_adapter * ad,struct bcm_packet_info * ps_sf)139 static void get_data_packet(struct bcm_mini_adapter *ad,
140 			    struct bcm_packet_info *ps_sf)
141 {
142 	int packet_len;
143 	struct sk_buff *qpacket;
144 
145 	if (!ps_sf->ucDirection)
146 		return;
147 
148 	BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
149 			"UpdateTokenCount ");
150 	if (ad->IdleMode || ad->bPreparingForLowPowerMode)
151 		return; /* in idle mode */
152 
153 	/* Check for Free Descriptors */
154 	if (atomic_read(&ad->CurrNumFreeTxDesc) <=
155 	    MINIMUM_PENDING_DESCRIPTORS) {
156 		BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
157 				" No Free Tx Descriptor(%d) is available for Data pkt..",
158 				atomic_read(&ad->CurrNumFreeTxDesc));
159 		return;
160 	}
161 
162 	spin_lock_bh(&ps_sf->SFQueueLock);
163 	qpacket = ps_sf->FirstTxQueue;
164 
165 	if (qpacket) {
166 		BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
167 				"Dequeuing Data Packet");
168 
169 		if (ps_sf->bEthCSSupport)
170 			packet_len = qpacket->len;
171 		else
172 			packet_len = qpacket->len - ETH_HLEN;
173 
174 		packet_len <<= 3;
175 		if (packet_len <= GetSFTokenCount(ad, ps_sf)) {
176 			BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
177 					DBG_LVL_ALL, "Allowed bytes %d",
178 					(packet_len >> 3));
179 
180 			DEQUEUEPACKET(ps_sf->FirstTxQueue, ps_sf->LastTxQueue);
181 			ps_sf->uiCurrentBytesOnHost -= (qpacket->len);
182 			ps_sf->uiCurrentPacketsOnHost--;
183 				atomic_dec(&ad->TotalPacketCount);
184 			spin_unlock_bh(&ps_sf->SFQueueLock);
185 
186 			SendPacketFromQueue(ad, ps_sf, qpacket);
187 			ps_sf->uiPendedLast = false;
188 		} else {
189 			BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
190 					DBG_LVL_ALL, "For Queue: %zd\n",
191 					ps_sf - ad->PackInfo);
192 			BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
193 					DBG_LVL_ALL,
194 					"\nAvailable Tokens = %d required = %d\n",
195 					ps_sf->uiCurrentTokenCount,
196 					packet_len);
197 			/*
198 			this part indicates that because of
199 			non-availability of the tokens
200 			pkt has not been send out hence setting the
201 			pending flag indicating the host to send it out
202 			first next iteration.
203 			*/
204 			ps_sf->uiPendedLast = TRUE;
205 			spin_unlock_bh(&ps_sf->SFQueueLock);
206 		}
207 	} else {
208 		spin_unlock_bh(&ps_sf->SFQueueLock);
209 	}
210 }
211 
send_control_packet(struct bcm_mini_adapter * ad,struct bcm_packet_info * ps_sf)212 static void send_control_packet(struct bcm_mini_adapter *ad,
213 				struct bcm_packet_info *ps_sf)
214 {
215 	char *ctrl_packet = NULL;
216 	INT status = 0;
217 
218 	if ((atomic_read(&ad->CurrNumFreeTxDesc) > 0) &&
219 	    (atomic_read(&ad->index_rd_txcntrlpkt) !=
220 	     atomic_read(&ad->index_wr_txcntrlpkt))) {
221 		ctrl_packet = ad->txctlpacket
222 		[(atomic_read(&ad->index_rd_txcntrlpkt)%MAX_CNTRL_PKTS)];
223 		if (ctrl_packet) {
224 			BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
225 					DBG_LVL_ALL,
226 					"Sending Control packet");
227 			status = SendControlPacket(ad, ctrl_packet);
228 			if (STATUS_SUCCESS == status) {
229 				spin_lock_bh(&ps_sf->SFQueueLock);
230 				ps_sf->NumOfPacketsSent++;
231 				ps_sf->uiSentBytes += ((struct bcm_leader *)ctrl_packet)->PLength;
232 				ps_sf->uiSentPackets++;
233 				atomic_dec(&ad->TotalPacketCount);
234 				ps_sf->uiCurrentBytesOnHost -= ((struct bcm_leader *)ctrl_packet)->PLength;
235 				ps_sf->uiCurrentPacketsOnHost--;
236 				atomic_inc(&ad->index_rd_txcntrlpkt);
237 				spin_unlock_bh(&ps_sf->SFQueueLock);
238 			} else {
239 				BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
240 						DBG_LVL_ALL,
241 						"SendControlPacket Failed\n");
242 			}
243 		} else {
244 			BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
245 					DBG_LVL_ALL,
246 					" Control Pkt is not available, Indexing is wrong....");
247 		}
248 	}
249 }
250 
251 /**
252  * CheckAndSendPacketFromIndex() - This function dequeues the
253  * data/control packet from the specified queue for transmission.
254  * @Adapter:	Pointer to the driver control structure.
255  * @iQIndex:	The queue Identifier.
256  *
257  * Returns: None.
258  */
CheckAndSendPacketFromIndex(struct bcm_mini_adapter * Adapter,struct bcm_packet_info * psSF)259 static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter,
260 					struct bcm_packet_info *psSF)
261 {
262 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
263 			"%zd ====>", (psSF-Adapter->PackInfo));
264 	if ((psSF != &Adapter->PackInfo[HiPriority]) &&
265 	    Adapter->LinkUpStatus &&
266 	    atomic_read(&psSF->uiPerSFTxResourceCount)) { /* Get data packet */
267 
268 		get_data_packet(Adapter, psSF);
269 	} else {
270 		send_control_packet(Adapter, psSF);
271 	}
272 }
273 
274 
275 /**
276  * transmit_packets() - This function transmits the packets from
277  * different queues, if free descriptors are available on target.
278  * @Adapter:	Pointer to the Adapter structure.
279  *
280  * Returns: None.
281  */
transmit_packets(struct bcm_mini_adapter * Adapter)282 VOID transmit_packets(struct bcm_mini_adapter *Adapter)
283 {
284 	UINT uiPrevTotalCount = 0;
285 	int iIndex = 0;
286 
287 	bool exit_flag = TRUE;
288 
289 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
290 			"=====>");
291 
292 	if (NULL == Adapter) {
293 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
294 				"Got NULL Adapter");
295 		return;
296 	}
297 	if (Adapter->device_removed == TRUE) {
298 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
299 				"Device removed");
300 		return;
301 	}
302 
303 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
304 			"\nUpdateTokenCount ====>\n");
305 
306 	UpdateTokenCount(Adapter);
307 
308 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
309 			"\nPruneQueueAllSF ====>\n");
310 
311 	PruneQueueAllSF(Adapter);
312 
313 	uiPrevTotalCount = atomic_read(&Adapter->TotalPacketCount);
314 
315 	for (iIndex = HiPriority; iIndex >= 0; iIndex--) {
316 		if (!uiPrevTotalCount || (TRUE == Adapter->device_removed))
317 				break;
318 
319 		if (Adapter->PackInfo[iIndex].bValid &&
320 		    Adapter->PackInfo[iIndex].uiPendedLast &&
321 		    Adapter->PackInfo[iIndex].uiCurrentBytesOnHost) {
322 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS,
323 					DBG_LVL_ALL,
324 					"Calling CheckAndSendPacketFromIndex..");
325 			CheckAndSendPacketFromIndex(Adapter,
326 						    &Adapter->PackInfo[iIndex]);
327 			uiPrevTotalCount--;
328 		}
329 	}
330 
331 	while (uiPrevTotalCount > 0 && !Adapter->device_removed) {
332 		exit_flag = TRUE;
333 		/* second iteration to parse non-pending queues */
334 		for (iIndex = HiPriority; iIndex >= 0; iIndex--) {
335 			if (!uiPrevTotalCount ||
336 			    (TRUE == Adapter->device_removed))
337 				break;
338 
339 			if (Adapter->PackInfo[iIndex].bValid &&
340 			    Adapter->PackInfo[iIndex].uiCurrentBytesOnHost &&
341 			    !Adapter->PackInfo[iIndex].uiPendedLast) {
342 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX,
343 						TX_PACKETS, DBG_LVL_ALL,
344 						"Calling CheckAndSendPacketFromIndex..");
345 				CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
346 				uiPrevTotalCount--;
347 				exit_flag = false;
348 			}
349 		}
350 
351 		if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) {
352 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS,
353 					DBG_LVL_ALL, "In Idle Mode\n");
354 			break;
355 		}
356 		if (exit_flag == TRUE)
357 			break;
358 	} /* end of inner while loop */
359 
360 	update_per_cid_rx(Adapter);
361 	Adapter->txtransmit_running = 0;
362 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
363 			"<======");
364 }
365