blob: f95b06713a284d90101c4e5d261ab2b77069ee3b [file] [log] [blame]
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001/**********************************************************************
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
Kevin McKinney29794602012-05-26 12:05:12 -040018static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070019{
Lilis Iskandar37c79c72013-07-28 03:34:43 +080020 ULONG liCurrentTime;
21 INT i = 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070022 struct timeval tv;
23
Ceri James89babcc2012-10-23 13:51:56 +010024 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
25 "=====>\n");
Lilis Iskandar68f4f092013-07-28 03:34:44 +080026 if (NULL == Adapter) {
Lilis Iskandar37c79c72013-07-28 03:34:43 +080027 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS,
Ceri James89babcc2012-10-23 13:51:56 +010028 DBG_LVL_ALL, "Adapter found NULL!\n");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070029 return;
30 }
31
32 do_gettimeofday(&tv);
Lilis Iskandar68f4f092013-07-28 03:34:44 +080033 for (i = 0; i < NO_OF_QUEUES; i++) {
Lilis Iskandar37c79c72013-07-28 03:34:43 +080034 if (TRUE == Adapter->PackInfo[i].bValid &&
Lilis Iskandar68f4f092013-07-28 03:34:44 +080035 (1 == Adapter->PackInfo[i].ucDirection)) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070036 liCurrentTime = ((tv.tv_sec-
37 Adapter->PackInfo[i].stLastUpdateTokenAt.tv_sec)*1000 +
38 (tv.tv_usec-Adapter->PackInfo[i].stLastUpdateTokenAt.tv_usec)/
39 1000);
Lilis Iskandar68f4f092013-07-28 03:34:44 +080040 if (0 != liCurrentTime) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070041 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;
Lilis Iskandar68f4f092013-07-28 03:34:44 +080047 if (Adapter->PackInfo[i].uiCurrentTokenCount >=
48 Adapter->PackInfo[i].uiMaxBucketSize) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070049 Adapter->PackInfo[i].uiCurrentTokenCount =
50 Adapter->PackInfo[i].uiMaxBucketSize;
51 }
52 }
53 }
54 }
Lilis Iskandar37c79c72013-07-28 03:34:43 +080055 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "<=====\n");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070056 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***********************************************************************/
Kevin McKinney29794602012-05-26 12:05:12 -040075static ULONG GetSFTokenCount(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070076{
Lilis Iskandar37c79c72013-07-28 03:34:43 +080077 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow ===>");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070078 /* Validate the parameters */
Lilis Iskandar37c79c72013-07-28 03:34:43 +080079 if (NULL == Adapter || (psSF < Adapter->PackInfo &&
Lilis Iskandar68f4f092013-07-28 03:34:44 +080080 (uintptr_t)psSF > (uintptr_t) &Adapter->PackInfo[HiPriority])) {
Lilis Iskandar37c79c72013-07-28 03:34:43 +080081 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));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070082 return 0;
83 }
84
Lisa Nguyenf70c8a92013-10-28 01:36:19 -070085 if (false != psSF->bValid && psSF->ucDirection) {
Lilis Iskandar68f4f092013-07-28 03:34:44 +080086 if (0 != psSF->uiCurrentTokenCount) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070087 return psSF->uiCurrentTokenCount;
Lilis Iskandar68f4f092013-07-28 03:34:44 +080088 } else {
Lilis Iskandar37c79c72013-07-28 03:34:43 +080089 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Not enough tokens in queue %zd Available %u\n",
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070090 psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount);
91 psSF->uiPendedLast = 1;
92 }
Lilis Iskandar68f4f092013-07-28 03:34:44 +080093 } else {
Lilis Iskandar37c79c72013-07-28 03:34:43 +080094 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Queue %zd not valid\n", psSF-Adapter->PackInfo);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070095 }
Lilis Iskandar37c79c72013-07-28 03:34:43 +080096 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow <===");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070097 return 0;
98}
99
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700100/**
101@ingroup tx_functions
102This function despatches packet from the specified queue.
103@return Zero(success) or Negative value(failure)
104*/
Kevin McKinney29794602012-05-26 12:05:12 -0400105static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,/**<Logical Adapter*/
Kevin McKinney0b3edf72012-05-26 12:05:01 -0400106 struct bcm_packet_info *psSF, /**<Queue identifier*/
Lilis Iskandarfd18e9f2013-07-28 03:34:47 +0800107 struct sk_buff *Packet) /**<Pointer to the packet to be sent*/
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700108{
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800109 INT Status = STATUS_FAILURE;
110 UINT uiIndex = 0, PktLen = 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700111
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800112 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "=====>");
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800113 if (!Adapter || !Packet || !psSF) {
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800114 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "Got NULL Adapter or Packet");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700115 return -EINVAL;
116 }
117
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800118 if (psSF->liDrainCalculated == 0)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700119 psSF->liDrainCalculated = jiffies;
Lilis Iskandarea20a1e2013-07-28 03:34:45 +0800120 /* send the packet to the fifo.. */
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700121 PktLen = Packet->len;
122 Status = SetupNextSend(Adapter, Packet, psSF->usVCID_Value);
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800123 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)))
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700126 Adapter->aTxPktSizeHist[uiIndex]++;
127 }
128 }
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800129 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "<=====");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700130 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****************************************************************************/
Kevin McKinney29794602012-05-26 12:05:12 -0400145static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700146{
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800147 struct sk_buff *QueuePacket = NULL;
148 char *pControlPacket = NULL;
149 INT Status = 0;
150 int iPacketLen = 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700151
152
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800153 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "%zd ====>", (psSF-Adapter->PackInfo));
Lilis Iskandarea20a1e2013-07-28 03:34:45 +0800154 if ((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount)) { /* Get data packet */
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800155 if (!psSF->ucDirection)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700156 return;
157
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800158 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "UpdateTokenCount ");
159 if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode)
Stephen Hemminger5cf084f2010-11-01 13:57:35 -0400160 return; /* in idle mode */
161
Lilis Iskandarea20a1e2013-07-28 03:34:45 +0800162 /* Check for Free Descriptors */
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800163 if (atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS) {
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800164 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;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700166 }
167
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700168 spin_lock_bh(&psSF->SFQueueLock);
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800169 QueuePacket = psSF->FirstTxQueue;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700170
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800171 if (QueuePacket) {
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800172 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Dequeuing Data Packet");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700173
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800174 if (psSF->bEthCSSupport)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700175 iPacketLen = QueuePacket->len;
176 else
177 iPacketLen = QueuePacket->len-ETH_HLEN;
178
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800179 iPacketLen <<= 3;
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800180 if (iPacketLen <= GetSFTokenCount(Adapter, psSF)) {
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800181 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Allowed bytes %d",
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700182 (iPacketLen >> 3));
183
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800184 DEQUEUEPACKET(psSF->FirstTxQueue, psSF->LastTxQueue);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700185 psSF->uiCurrentBytesOnHost -= (QueuePacket->len);
186 psSF->uiCurrentPacketsOnHost--;
187 atomic_dec(&Adapter->TotalPacketCount);
188 spin_unlock_bh(&psSF->SFQueueLock);
189
Lilis Iskandar0a676532013-07-28 03:34:46 +0800190 Status = SendPacketFromQueue(Adapter, psSF, QueuePacket);
Lisa Nguyenf70c8a92013-10-28 01:36:19 -0700191 psSF->uiPendedLast = false;
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800192 } else {
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800193 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",
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700195 psSF->uiCurrentTokenCount, iPacketLen);
Lilis Iskandarea20a1e2013-07-28 03:34:45 +0800196 /*
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 */
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700201 psSF->uiPendedLast = TRUE;
202 spin_unlock_bh(&psSF->SFQueueLock);
203 }
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800204 } else {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700205 spin_unlock_bh(&psSF->SFQueueLock);
206 }
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800207 } else {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700208
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800209 if ((atomic_read(&Adapter->CurrNumFreeTxDesc) > 0) &&
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800210 (atomic_read(&Adapter->index_rd_txcntrlpkt) !=
211 atomic_read(&Adapter->index_wr_txcntrlpkt))) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700212 pControlPacket = Adapter->txctlpacket
213 [(atomic_read(&Adapter->index_rd_txcntrlpkt)%MAX_CNTRL_PKTS)];
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800214 if (pControlPacket) {
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800215 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Sending Control packet");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700216 Status = SendControlPacket(Adapter, pControlPacket);
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800217 if (STATUS_SUCCESS == Status) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700218 spin_lock_bh(&psSF->SFQueueLock);
219 psSF->NumOfPacketsSent++;
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800220 psSF->uiSentBytes += ((struct bcm_leader *)pControlPacket)->PLength;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700221 psSF->uiSentPackets++;
222 atomic_dec(&Adapter->TotalPacketCount);
Kevin McKinneyff352042012-05-26 12:05:11 -0400223 psSF->uiCurrentBytesOnHost -= ((struct bcm_leader *)pControlPacket)->PLength;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700224 psSF->uiCurrentPacketsOnHost--;
225 atomic_inc(&Adapter->index_rd_txcntrlpkt);
226 spin_unlock_bh(&psSF->SFQueueLock);
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800227 } else {
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800228 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "SendControlPacket Failed\n");
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800229 }
230 } else {
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800231 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " Control Pkt is not available, Indexing is wrong....");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700232 }
Lilis Iskandar0a676532013-07-28 03:34:46 +0800233 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700234 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700235}
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********************************************************************/
Kevin McKinney29794602012-05-26 12:05:12 -0400248VOID transmit_packets(struct bcm_mini_adapter *Adapter)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700249{
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800250 UINT uiPrevTotalCount = 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700251 int iIndex = 0;
252
Lisa Nguyen3abd6f12013-10-28 01:35:59 -0700253 bool exit_flag = TRUE;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700254
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800255 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "=====>");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700256
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800257 if (NULL == Adapter) {
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800258 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Got NULL Adapter");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700259 return;
260 }
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800261 if (Adapter->device_removed == TRUE) {
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800262 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device removed");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700263 return;
264 }
265
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800266 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nUpdateTokenCount ====>\n");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700267
268 UpdateTokenCount(Adapter);
269
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800270 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nPruneQueueAllSF ====>\n");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700271
272 PruneQueueAllSF(Adapter);
273
274 uiPrevTotalCount = atomic_read(&Adapter->TotalPacketCount);
275
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800276 for (iIndex = HiPriority; iIndex >= 0; iIndex--) {
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800277 if (!uiPrevTotalCount || (TRUE == Adapter->device_removed))
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700278 break;
279
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800280 if (Adapter->PackInfo[iIndex].bValid &&
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800281 Adapter->PackInfo[iIndex].uiPendedLast &&
282 Adapter->PackInfo[iIndex].uiCurrentBytesOnHost) {
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800283 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700284 CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
285 uiPrevTotalCount--;
286 }
287 }
288
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800289 while (uiPrevTotalCount > 0 && !Adapter->device_removed) {
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800290 exit_flag = TRUE;
Lilis Iskandarea20a1e2013-07-28 03:34:45 +0800291 /* second iteration to parse non-pending queues */
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800292 for (iIndex = HiPriority; iIndex >= 0; iIndex--) {
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800293 if (!uiPrevTotalCount || (TRUE == Adapter->device_removed))
294 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700295
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800296 if (Adapter->PackInfo[iIndex].bValid &&
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800297 Adapter->PackInfo[iIndex].uiCurrentBytesOnHost &&
298 !Adapter->PackInfo[iIndex].uiPendedLast) {
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800299 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700300 CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
301 uiPrevTotalCount--;
Lisa Nguyenf70c8a92013-10-28 01:36:19 -0700302 exit_flag = false;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700303 }
304 }
305
Lilis Iskandar68f4f092013-07-28 03:34:44 +0800306 if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) {
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800307 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "In Idle Mode\n");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700308 break;
309 }
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800310 if (exit_flag == TRUE)
Lilis Iskandar0a676532013-07-28 03:34:46 +0800311 break;
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800312 } /* end of inner while loop */
Stephen Hemminger5cf084f2010-11-01 13:57:35 -0400313
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800314 update_per_cid_rx(Adapter);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700315 Adapter->txtransmit_running = 0;
Lilis Iskandar37c79c72013-07-28 03:34:43 +0800316 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<======");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700317}