4 *Copyright (C) 2010 Beceem Communications, Inc.
6 *This program is free software: you can redistribute it and/or modify
7 *it under the terms of the GNU General Public License version 2 as
8 *published by the Free Software Foundation.
10 *This program is distributed in the hope that it will be useful,but
11 *WITHOUT ANY WARRANTY; without even the implied warranty of
12 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 *See the GNU General Public License for more details.
15 *You should have received a copy of the GNU General Public License
16 *along with this program. If not, write to the Free Software Foundation, Inc.,
17 *51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 /**********************************************************************
23 * This file contains the routines related to Leaky Bucket Algorithm.
24 ***********************************************************************/
27 /*********************************************************************
28 * Function - UpdateTokenCount()
30 * Description - This function calculates the token count for each
31 * channel and updates the same in Adapter strucuture.
33 * Parameters - Adapter: Pointer to the Adapter structure.
36 **********************************************************************/
38 VOID
UpdateTokenCount(register PMINI_ADAPTER Adapter
)
42 ULONG currjiffies
= jiffies
;
45 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TOKEN_COUNTS
, DBG_LVL_ALL
, "=====>\n");
48 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TOKEN_COUNTS
, DBG_LVL_ALL
, "Adapter found NULL!\n");
52 for(i
= 0; i
< NO_OF_QUEUES
; i
++)
54 if(TRUE
== Adapter
->PackInfo
[i
].bValid
&&
55 (1 == Adapter
->PackInfo
[i
].ucDirection
))
57 liElapsedTime
= currjiffies
- Adapter
->localjiffies
;
60 Adapter
->PackInfo
[i
].uiCurrentTokenCount
+= (ULONG
)
61 (((Adapter
->PackInfo
[i
].uiMaxAllowedRate
) * liElapsedTime
)/HZ
);
63 if((Adapter
->PackInfo
[i
].uiCurrentTokenCount
) >= Adapter
->PackInfo
[i
].uiMaxBucketSize
)
65 Adapter
->PackInfo
[i
].uiCurrentTokenCount
= Adapter
->PackInfo
[i
].uiMaxBucketSize
;
70 Adapter
->localjiffies
= currjiffies
;
71 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TOKEN_COUNTS
, DBG_LVL_ALL
, "<=====\n");
77 /*********************************************************************
78 * Function - IsPacketAllowedForFlow()
80 * Description - This function checks whether the given packet from the
81 * specified queue can be allowed for transmission by
82 * checking the token count.
84 * Parameters - Adapter : Pointer to the Adpater structure.
85 * - iQIndex : The queue Identifier.
86 * - ulPacketLength: Number of bytes to be transmitted.
88 * Returns - The number of bytes allowed for transmission.
90 ***********************************************************************/
91 static __inline ULONG
GetSFTokenCount(PMINI_ADAPTER Adapter
, PacketInfo
*psSF
)
93 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TOKEN_COUNTS
, DBG_LVL_ALL
, "IsPacketAllowedForFlow ===>");
94 /* Validate the parameters */
95 if(NULL
== Adapter
|| (psSF
< Adapter
->PackInfo
&&
96 (UINT
)psSF
> (UINT
) &Adapter
->PackInfo
[HiPriority
]))
98 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TOKEN_COUNTS
, DBG_LVL_ALL
, "IPAFF: Got wrong Parameters:Adapter: %p, QIndex: %d\n", Adapter
, (psSF
-Adapter
->PackInfo
));
102 if(FALSE
!= psSF
->bValid
&& psSF
->ucDirection
)
104 if(0 != psSF
->uiCurrentTokenCount
)
106 return psSF
->uiCurrentTokenCount
;
110 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TOKEN_COUNTS
, DBG_LVL_ALL
, "Not enough tokens in queue %d Available %u\n",
111 psSF
-Adapter
->PackInfo
, psSF
->uiCurrentTokenCount
);
112 psSF
->uiPendedLast
= 1;
117 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TOKEN_COUNTS
, DBG_LVL_ALL
, "IPAFF: Queue %d not valid\n", psSF
-Adapter
->PackInfo
);
119 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TOKEN_COUNTS
, DBG_LVL_ALL
, "IsPacketAllowedForFlow <===");
123 static __inline
void RemovePacketFromQueue(PacketInfo
*pPackInfo
, struct sk_buff
*Packet
)
125 struct sk_buff
*psQueueCurrent
=NULL
, *psLastQueueNode
=NULL
;
126 psQueueCurrent
= pPackInfo
->FirstTxQueue
;
127 while(psQueueCurrent
)
129 if((UINT
)Packet
== (UINT
)psQueueCurrent
)
131 if((UINT
)psQueueCurrent
== (UINT
)pPackInfo
->FirstTxQueue
)
133 pPackInfo
->FirstTxQueue
=psQueueCurrent
->next
;
134 if((UINT
)psQueueCurrent
==(UINT
)pPackInfo
->LastTxQueue
)
135 pPackInfo
->LastTxQueue
=NULL
;
139 psLastQueueNode
->next
=psQueueCurrent
->next
;
143 psLastQueueNode
= psQueueCurrent
;
144 psQueueCurrent
=psQueueCurrent
->next
;
148 @ingroup tx_functions
149 This function despatches packet from the specified queue.
150 @return Zero(success) or Negative value(failure)
152 static __inline INT
SendPacketFromQueue(PMINI_ADAPTER Adapter
,/**<Logical Adapter*/
153 PacketInfo
*psSF
, /**<Queue identifier*/
154 struct sk_buff
* Packet
) /**<Pointer to the packet to be sent*/
156 INT Status
=STATUS_FAILURE
;
157 UINT uiIndex
=0,PktLen
= 0;
159 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, SEND_QUEUE
, DBG_LVL_ALL
, "=====>");
160 if(!Adapter
|| !Packet
|| !psSF
)
162 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, SEND_QUEUE
, DBG_LVL_ALL
, "Got NULL Adapter or Packet");
166 if(psSF
->liDrainCalculated
==0)
168 psSF
->liDrainCalculated
= jiffies
;
170 ///send the packet to the fifo..
171 PktLen
= Packet
->len
;
172 Status
= SetupNextSend(Adapter
, Packet
, psSF
->usVCID_Value
);
175 for(uiIndex
= 0 ; uiIndex
< MIBS_MAX_HIST_ENTRIES
; uiIndex
++)
176 { if((PktLen
<= MIBS_PKTSIZEHIST_RANGE
*(uiIndex
+1)) && (PktLen
> MIBS_PKTSIZEHIST_RANGE
*(uiIndex
)))
177 Adapter
->aTxPktSizeHist
[uiIndex
]++;
180 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, SEND_QUEUE
, DBG_LVL_ALL
, "<=====");
184 /************************************************************************
185 * Function - CheckAndSendPacketFromIndex()
187 * Description - This function dequeues the data/control packet from the
188 * specified queue for transmission.
190 * Parameters - Adapter : Pointer to the driver control structure.
191 * - iQIndex : The queue Identifier.
195 ****************************************************************************/
196 static __inline VOID CheckAndSendPacketFromIndex
197 (PMINI_ADAPTER Adapter
, PacketInfo
*psSF
)
199 struct sk_buff
*QueuePacket
=NULL
;
200 char *pControlPacket
= NULL
;
205 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "%d ====>", (psSF
-Adapter
->PackInfo
));
206 if(((UINT
)psSF
!= (UINT
)&Adapter
->PackInfo
[HiPriority
]) && Adapter
->LinkUpStatus
)//Get data packet
208 if(!psSF
->ucDirection
)
211 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "UpdateTokenCount ");
212 if(Adapter
->IdleMode
|| Adapter
->bPreparingForLowPowerMode
)
214 //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle Mode..Hence blocking Data Packets..\n");
217 // Check for Free Descriptors
218 if(atomic_read(&Adapter
->CurrNumFreeTxDesc
) <= MINIMUM_PENDING_DESCRIPTORS
)
220 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
));
225 PruneQueue(Adapter
,(psSF
-Adapter
->PackInfo
));
227 spin_lock_bh(&psSF
->SFQueueLock
);
228 QueuePacket
=psSF
->FirstTxQueue
;
232 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Dequeuing Data Packet");
234 if(psSF
->bEthCSSupport
)
235 iPacketLen
= QueuePacket
->len
;
237 iPacketLen
= QueuePacket
->len
-ETH_HLEN
;
240 if(iPacketLen
<= GetSFTokenCount(Adapter
, psSF
))
242 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Allowed bytes %d",
245 DEQUEUEPACKET(psSF
->FirstTxQueue
,psSF
->LastTxQueue
);
246 psSF
->uiCurrentBytesOnHost
-= (QueuePacket
->len
);
247 psSF
->uiCurrentPacketsOnHost
--;
248 atomic_dec(&Adapter
->TotalPacketCount
);
249 spin_unlock_bh(&psSF
->SFQueueLock
);
251 Status
= SendPacketFromQueue(Adapter
, psSF
, QueuePacket
);
252 psSF
->uiPendedLast
= FALSE
;
256 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "For Queue: %d\n", psSF
-Adapter
->PackInfo
);
257 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "\nAvailable Tokens = %d required = %d\n",
258 psSF
->uiCurrentTokenCount
, iPacketLen
);
259 //this part indicates that becuase of non-availability of the tokens
260 //pkt has not been send out hence setting the pending flag indicating the host to send it out
261 //first next iteration .
262 psSF
->uiPendedLast
= TRUE
;
263 spin_unlock_bh(&psSF
->SFQueueLock
);
268 spin_unlock_bh(&psSF
->SFQueueLock
);
271 else if((UINT
)psSF
== (UINT
)&Adapter
->PackInfo
[HiPriority
])
273 spin_lock_bh(&psSF
->SFQueueLock
);
274 if((atomic_read(&Adapter
->CurrNumFreeTxDesc
) > 0 ) &&
275 (atomic_read(&Adapter
->index_rd_txcntrlpkt
) !=
276 atomic_read(&Adapter
->index_wr_txcntrlpkt
))
279 pControlPacket
= Adapter
->txctlpacket
280 [(atomic_read(&Adapter
->index_rd_txcntrlpkt
)%MAX_CNTRL_PKTS
)];
283 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Sending Control packet");
284 Status
= SendControlPacket(Adapter
, pControlPacket
);
285 if(STATUS_SUCCESS
==Status
)
288 psSF
->NumOfPacketsSent
++;
289 psSF
->uiSentBytes
+=((PLEADER
)pControlPacket
)->PLength
;
290 psSF
->uiSentPackets
++;
291 atomic_dec(&Adapter
->TotalPacketCount
);
292 psSF
->uiCurrentBytesOnHost
-= ((PLEADER
)pControlPacket
)->PLength
;
293 psSF
->uiCurrentPacketsOnHost
--;
294 atomic_inc(&Adapter
->index_rd_txcntrlpkt
);
298 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "SendControlPacket Failed\n");
302 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, " Control Pkt is not available, Indexing is wrong....");
306 spin_unlock_bh(&psSF
->SFQueueLock
);
309 if(Status
!= STATUS_SUCCESS
) //Tx of data packet to device Failed
311 if(Adapter
->bcm_jiffies
== 0)
312 Adapter
->bcm_jiffies
= jiffies
;
316 Adapter
->bcm_jiffies
= 0;
318 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "<=====");
322 /*******************************************************************
323 * Function - transmit_packets()
325 * Description - This function transmits the packets from different
326 * queues, if free descriptors are available on target.
328 * Parameters - Adapter: Pointer to the Adapter structure.
331 ********************************************************************/
332 VOID
transmit_packets(PMINI_ADAPTER Adapter
)
334 UINT uiPrevTotalCount
= 0;
337 BOOLEAN exit_flag
= TRUE
;
339 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "=====>");
343 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
,TX_PACKETS
, DBG_LVL_ALL
, "Got NULL Adapter");
346 if(Adapter
->device_removed
== TRUE
)
348 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Device removed");
352 BCM_DEBUG_PRINT (Adapter
, DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "\nUpdateTokenCount ====>\n");
354 UpdateTokenCount(Adapter
);
356 BCM_DEBUG_PRINT (Adapter
, DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "\nPruneQueueAllSF ====>\n");
358 PruneQueueAllSF(Adapter
);
360 uiPrevTotalCount
= atomic_read(&Adapter
->TotalPacketCount
);
362 for(iIndex
=HiPriority
;iIndex
>=0;iIndex
--)
364 if( !uiPrevTotalCount
|| (TRUE
== Adapter
->device_removed
))
367 if(Adapter
->PackInfo
[iIndex
].bValid
&&
368 Adapter
->PackInfo
[iIndex
].uiPendedLast
&&
369 Adapter
->PackInfo
[iIndex
].uiCurrentBytesOnHost
&&
370 ((iIndex
==HiPriority
) || (atomic_read(&Adapter
->PackInfo
[iIndex
].uiPerSFTxResourceCount
)>0))
373 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Calling CheckAndSendPacketFromIndex..");
374 CheckAndSendPacketFromIndex(Adapter
, &Adapter
->PackInfo
[iIndex
]);
379 while(uiPrevTotalCount
> 0 && !Adapter
->device_removed
)
382 //second iteration to parse non-pending queues
383 for(iIndex
=HiPriority
;iIndex
>=0;iIndex
--)
385 if( !uiPrevTotalCount
|| (TRUE
== Adapter
->device_removed
))
388 if(Adapter
->PackInfo
[iIndex
].bValid
&&
389 Adapter
->PackInfo
[iIndex
].uiCurrentBytesOnHost
&&
390 !Adapter
->PackInfo
[iIndex
].uiPendedLast
&&
391 ((iIndex
==HiPriority
) || (atomic_read(&Adapter
->PackInfo
[iIndex
].uiPerSFTxResourceCount
)>0))
394 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Calling CheckAndSendPacketFromIndex..");
395 CheckAndSendPacketFromIndex(Adapter
, &Adapter
->PackInfo
[iIndex
]);
401 if(Adapter
->IdleMode
|| Adapter
->bPreparingForLowPowerMode
)
403 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "In Idle Mode\n");
406 if(exit_flag
== TRUE
)
408 }/* end of inner while loop */
409 if(Adapter
->bcm_jiffies
== 0 &&
410 atomic_read(&Adapter
->TotalPacketCount
) != 0 &&
411 uiPrevTotalCount
== atomic_read(&Adapter
->TotalPacketCount
))
413 Adapter
->bcm_jiffies
= jiffies
;
415 update_per_cid_rx (Adapter
);
416 Adapter
->txtransmit_running
= 0;
417 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "<======");