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