1 /**********************************************************************
3 * This file contains the routines related to Leaky Bucket Algorithm.
4 ***********************************************************************/
7 /*********************************************************************
8 * Function - UpdateTokenCount()
10 * Description - This function calculates the token count for each
11 * channel and updates the same in Adapter strucuture.
13 * Parameters - Adapter: Pointer to the Adapter structure.
16 **********************************************************************/
18 static VOID
UpdateTokenCount(register struct bcm_mini_adapter
*Adapter
)
24 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TOKEN_COUNTS
, DBG_LVL_ALL
,
26 if (NULL
== Adapter
) {
27 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TOKEN_COUNTS
,
28 DBG_LVL_ALL
, "Adapter found NULL!\n");
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
)/
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
;
55 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TOKEN_COUNTS
, DBG_LVL_ALL
, "<=====\n");
61 /*********************************************************************
62 * Function - IsPacketAllowedForFlow()
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.
68 * Parameters - Adapter : Pointer to the Adpater structure.
69 * - iQIndex : The queue Identifier.
70 * - ulPacketLength: Number of bytes to be transmitted.
72 * Returns - The number of bytes allowed for transmission.
74 ***********************************************************************/
75 static ULONG
GetSFTokenCount(struct bcm_mini_adapter
*Adapter
, struct bcm_packet_info
*psSF
)
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
));
85 if (false != psSF
->bValid
&& psSF
->ucDirection
) {
86 if (0 != psSF
->uiCurrentTokenCount
) {
87 return psSF
->uiCurrentTokenCount
;
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;
94 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TOKEN_COUNTS
, DBG_LVL_ALL
, "IPAFF: Queue %zd not valid\n", psSF
-Adapter
->PackInfo
);
96 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TOKEN_COUNTS
, DBG_LVL_ALL
, "IsPacketAllowedForFlow <===");
101 @ingroup tx_functions
102 This function despatches packet from the specified queue.
103 @return Zero(success) or Negative value(failure)
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*/
109 INT Status
= STATUS_FAILURE
;
110 UINT uiIndex
= 0, PktLen
= 0;
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");
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
);
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
]++;
129 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, SEND_QUEUE
, DBG_LVL_ALL
, "<=====");
133 /************************************************************************
134 * Function - CheckAndSendPacketFromIndex()
136 * Description - This function dequeues the data/control packet from the
137 * specified queue for transmission.
139 * Parameters - Adapter : Pointer to the driver control structure.
140 * - iQIndex : The queue Identifier.
144 ****************************************************************************/
145 static VOID
CheckAndSendPacketFromIndex(struct bcm_mini_adapter
*Adapter
, struct bcm_packet_info
*psSF
)
147 struct sk_buff
*QueuePacket
= NULL
;
148 char *pControlPacket
= NULL
;
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
)
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 */
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
));
168 spin_lock_bh(&psSF
->SFQueueLock
);
169 QueuePacket
= psSF
->FirstTxQueue
;
172 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Dequeuing Data Packet");
174 if (psSF
->bEthCSSupport
)
175 iPacketLen
= QueuePacket
->len
;
177 iPacketLen
= QueuePacket
->len
-ETH_HLEN
;
180 if (iPacketLen
<= GetSFTokenCount(Adapter
, psSF
)) {
181 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Allowed bytes %d",
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
);
190 Status
= SendPacketFromQueue(Adapter
, psSF
, QueuePacket
);
191 psSF
->uiPendedLast
= false;
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
);
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.
201 psSF
->uiPendedLast
= TRUE
;
202 spin_unlock_bh(&psSF
->SFQueueLock
);
205 spin_unlock_bh(&psSF
->SFQueueLock
);
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
);
228 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "SendControlPacket Failed\n");
231 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, " Control Pkt is not available, Indexing is wrong....");
238 /*******************************************************************
239 * Function - transmit_packets()
241 * Description - This function transmits the packets from different
242 * queues, if free descriptors are available on target.
244 * Parameters - Adapter: Pointer to the Adapter structure.
247 ********************************************************************/
248 VOID
transmit_packets(struct bcm_mini_adapter
*Adapter
)
250 UINT uiPrevTotalCount
= 0;
253 bool exit_flag
= TRUE
;
255 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "=====>");
257 if (NULL
== Adapter
) {
258 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Got NULL Adapter");
261 if (Adapter
->device_removed
== TRUE
) {
262 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Device removed");
266 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "\nUpdateTokenCount ====>\n");
268 UpdateTokenCount(Adapter
);
270 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "\nPruneQueueAllSF ====>\n");
272 PruneQueueAllSF(Adapter
);
274 uiPrevTotalCount
= atomic_read(&Adapter
->TotalPacketCount
);
276 for (iIndex
= HiPriority
; iIndex
>= 0; iIndex
--) {
277 if (!uiPrevTotalCount
|| (TRUE
== Adapter
->device_removed
))
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
]);
289 while (uiPrevTotalCount
> 0 && !Adapter
->device_removed
) {
291 /* second iteration to parse non-pending queues */
292 for (iIndex
= HiPriority
; iIndex
>= 0; iIndex
--) {
293 if (!uiPrevTotalCount
|| (TRUE
== Adapter
->device_removed
))
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
]);
306 if (Adapter
->IdleMode
|| Adapter
->bPreparingForLowPowerMode
) {
307 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "In Idle Mode\n");
310 if (exit_flag
== TRUE
)
312 } /* end of inner while loop */
314 update_per_cid_rx(Adapter
);
315 Adapter
->txtransmit_running
= 0;
316 BCM_DEBUG_PRINT(Adapter
, DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "<======");