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