Merge tag 'v3.18-rc1' into v4l_for_linus
[cascardo/linux.git] / drivers / staging / bcm / LeakyBucket.c
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  */
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  */
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 */
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
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
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  */
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  */
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 }