1 /**********************************************************************
3 * This file contains the routines related to Leaky Bucket Algorithm.
4 ***********************************************************************/
8 * UpdateTokenCount() - Calculates the token count for each channel
9 * and updates the same in Adapter structure
10 * @Adapter: Pointer to the Adapter structure.
14 static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter)
19 struct bcm_packet_info *curr_pi;
21 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
23 if (NULL == Adapter) {
24 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS,
25 DBG_LVL_ALL, "Adapter found NULL!\n");
30 for (i = 0; i < NO_OF_QUEUES; i++) {
31 curr_pi = &Adapter->PackInfo[i];
33 if (TRUE == curr_pi->bValid && (1 == curr_pi->ucDirection)) {
34 liCurrentTime = ((tv.tv_sec -
35 curr_pi->stLastUpdateTokenAt.tv_sec)*1000 +
36 (tv.tv_usec - curr_pi->stLastUpdateTokenAt.tv_usec) /
38 if (0 != liCurrentTime) {
39 curr_pi->uiCurrentTokenCount += (ULONG)
40 ((curr_pi->uiMaxAllowedRate) *
41 ((ULONG)((liCurrentTime)))/1000);
42 memcpy(&curr_pi->stLastUpdateTokenAt, &tv,
43 sizeof(struct timeval));
44 curr_pi->liLastUpdateTokenAt = liCurrentTime;
45 if (curr_pi->uiCurrentTokenCount >=
46 curr_pi->uiMaxBucketSize) {
47 curr_pi->uiCurrentTokenCount =
48 curr_pi->uiMaxBucketSize;
53 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
59 * IsPacketAllowedForFlow() - This function checks whether the given
60 * packet from the specified queue can be allowed for transmission by
61 * checking the token count.
62 * @Adapter: Pointer to the Adpater structure.
63 * @iQIndex: The queue Identifier.
64 * @ulPacketLength: Number of bytes to be transmitted.
66 * Returns: The number of bytes allowed for transmission.
68 static ULONG GetSFTokenCount(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF)
70 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
71 "IsPacketAllowedForFlow ===>");
73 /* Validate the parameters */
74 if (NULL == Adapter || (psSF < Adapter->PackInfo &&
75 (uintptr_t)psSF > (uintptr_t) &Adapter->PackInfo[HiPriority])) {
76 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
77 "IPAFF: Got wrong Parameters:Adapter: %p, QIndex: %zd\n",
78 Adapter, (psSF-Adapter->PackInfo));
82 if (false != psSF->bValid && psSF->ucDirection) {
83 if (0 != psSF->uiCurrentTokenCount) {
84 return psSF->uiCurrentTokenCount;
86 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS,
88 "Not enough tokens in queue %zd Available %u\n",
89 psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount);
90 psSF->uiPendedLast = 1;
93 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
94 "IPAFF: Queue %zd not valid\n",
95 psSF-Adapter->PackInfo);
97 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
98 "IsPacketAllowedForFlow <===");
103 @ingroup tx_functions
104 This function despatches packet from the specified queue.
105 @return Zero(success) or Negative value(failure)
107 static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,/**<Logical Adapter*/
108 struct bcm_packet_info *psSF, /**<Queue identifier*/
109 struct sk_buff *Packet) /**<Pointer to the packet to be sent*/
111 INT Status = STATUS_FAILURE;
112 UINT uiIndex = 0, PktLen = 0;
114 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL,
116 if (!Adapter || !Packet || !psSF) {
117 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL,
118 "Got NULL Adapter or Packet");
122 if (psSF->liDrainCalculated == 0)
123 psSF->liDrainCalculated = jiffies;
124 /* send the packet to the fifo.. */
125 PktLen = Packet->len;
126 Status = SetupNextSend(Adapter, Packet, psSF->usVCID_Value);
128 for (uiIndex = 0; uiIndex < MIBS_MAX_HIST_ENTRIES; uiIndex++) {
129 if ((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) &&
130 (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex)))
131 Adapter->aTxPktSizeHist[uiIndex]++;
134 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL,
139 static void get_data_packet(struct bcm_mini_adapter *ad,
140 struct bcm_packet_info *ps_sf)
143 struct sk_buff *qpacket;
145 if (!ps_sf->ucDirection)
148 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
149 "UpdateTokenCount ");
150 if (ad->IdleMode || ad->bPreparingForLowPowerMode)
151 return; /* in idle mode */
153 /* Check for Free Descriptors */
154 if (atomic_read(&ad->CurrNumFreeTxDesc) <=
155 MINIMUM_PENDING_DESCRIPTORS) {
156 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
157 " No Free Tx Descriptor(%d) is available for Data pkt..",
158 atomic_read(&ad->CurrNumFreeTxDesc));
162 spin_lock_bh(&ps_sf->SFQueueLock);
163 qpacket = ps_sf->FirstTxQueue;
166 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
167 "Dequeuing Data Packet");
169 if (ps_sf->bEthCSSupport)
170 packet_len = qpacket->len;
172 packet_len = qpacket->len - ETH_HLEN;
175 if (packet_len <= GetSFTokenCount(ad, ps_sf)) {
176 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
177 DBG_LVL_ALL, "Allowed bytes %d",
180 DEQUEUEPACKET(ps_sf->FirstTxQueue, ps_sf->LastTxQueue);
181 ps_sf->uiCurrentBytesOnHost -= (qpacket->len);
182 ps_sf->uiCurrentPacketsOnHost--;
183 atomic_dec(&ad->TotalPacketCount);
184 spin_unlock_bh(&ps_sf->SFQueueLock);
186 SendPacketFromQueue(ad, ps_sf, qpacket);
187 ps_sf->uiPendedLast = false;
189 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
190 DBG_LVL_ALL, "For Queue: %zd\n",
191 ps_sf - ad->PackInfo);
192 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
194 "\nAvailable Tokens = %d required = %d\n",
195 ps_sf->uiCurrentTokenCount,
198 this part indicates that because of
199 non-availability of the tokens
200 pkt has not been send out hence setting the
201 pending flag indicating the host to send it out
202 first next iteration.
204 ps_sf->uiPendedLast = TRUE;
205 spin_unlock_bh(&ps_sf->SFQueueLock);
208 spin_unlock_bh(&ps_sf->SFQueueLock);
212 static void send_control_packet(struct bcm_mini_adapter *ad,
213 struct bcm_packet_info *ps_sf)
215 char *ctrl_packet = NULL;
218 if ((atomic_read(&ad->CurrNumFreeTxDesc) > 0) &&
219 (atomic_read(&ad->index_rd_txcntrlpkt) !=
220 atomic_read(&ad->index_wr_txcntrlpkt))) {
221 ctrl_packet = ad->txctlpacket
222 [(atomic_read(&ad->index_rd_txcntrlpkt)%MAX_CNTRL_PKTS)];
224 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
226 "Sending Control packet");
227 status = SendControlPacket(ad, ctrl_packet);
228 if (STATUS_SUCCESS == status) {
229 spin_lock_bh(&ps_sf->SFQueueLock);
230 ps_sf->NumOfPacketsSent++;
231 ps_sf->uiSentBytes += ((struct bcm_leader *)ctrl_packet)->PLength;
232 ps_sf->uiSentPackets++;
233 atomic_dec(&ad->TotalPacketCount);
234 ps_sf->uiCurrentBytesOnHost -= ((struct bcm_leader *)ctrl_packet)->PLength;
235 ps_sf->uiCurrentPacketsOnHost--;
236 atomic_inc(&ad->index_rd_txcntrlpkt);
237 spin_unlock_bh(&ps_sf->SFQueueLock);
239 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
241 "SendControlPacket Failed\n");
244 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
246 " Control Pkt is not available, Indexing is wrong....");
252 * CheckAndSendPacketFromIndex() - This function dequeues the
253 * data/control packet from the specified queue for transmission.
254 * @Adapter: Pointer to the driver control structure.
255 * @iQIndex: The queue Identifier.
259 static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter,
260 struct bcm_packet_info *psSF)
262 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
263 "%zd ====>", (psSF-Adapter->PackInfo));
264 if ((psSF != &Adapter->PackInfo[HiPriority]) &&
265 Adapter->LinkUpStatus &&
266 atomic_read(&psSF->uiPerSFTxResourceCount)) { /* Get data packet */
268 get_data_packet(Adapter, psSF);
270 send_control_packet(Adapter, psSF);
276 * transmit_packets() - This function transmits the packets from
277 * different queues, if free descriptors are available on target.
278 * @Adapter: Pointer to the Adapter structure.
282 VOID transmit_packets(struct bcm_mini_adapter *Adapter)
284 UINT uiPrevTotalCount = 0;
287 bool exit_flag = TRUE;
289 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
292 if (NULL == Adapter) {
293 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
297 if (Adapter->device_removed == TRUE) {
298 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
303 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
304 "\nUpdateTokenCount ====>\n");
306 UpdateTokenCount(Adapter);
308 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
309 "\nPruneQueueAllSF ====>\n");
311 PruneQueueAllSF(Adapter);
313 uiPrevTotalCount = atomic_read(&Adapter->TotalPacketCount);
315 for (iIndex = HiPriority; iIndex >= 0; iIndex--) {
316 if (!uiPrevTotalCount || (TRUE == Adapter->device_removed))
319 if (Adapter->PackInfo[iIndex].bValid &&
320 Adapter->PackInfo[iIndex].uiPendedLast &&
321 Adapter->PackInfo[iIndex].uiCurrentBytesOnHost) {
322 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS,
324 "Calling CheckAndSendPacketFromIndex..");
325 CheckAndSendPacketFromIndex(Adapter,
326 &Adapter->PackInfo[iIndex]);
331 while (uiPrevTotalCount > 0 && !Adapter->device_removed) {
333 /* second iteration to parse non-pending queues */
334 for (iIndex = HiPriority; iIndex >= 0; iIndex--) {
335 if (!uiPrevTotalCount ||
336 (TRUE == Adapter->device_removed))
339 if (Adapter->PackInfo[iIndex].bValid &&
340 Adapter->PackInfo[iIndex].uiCurrentBytesOnHost &&
341 !Adapter->PackInfo[iIndex].uiPendedLast) {
342 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX,
343 TX_PACKETS, DBG_LVL_ALL,
344 "Calling CheckAndSendPacketFromIndex..");
345 CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
351 if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) {
352 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS,
353 DBG_LVL_ALL, "In Idle Mode\n");
356 if (exit_flag == TRUE)
358 } /* end of inner while loop */
360 update_per_cid_rx(Adapter);
361 Adapter->txtransmit_running = 0;
362 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,