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