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,
28 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS,
29 DBG_LVL_ALL, "Adapter found NULL!\n");
34 for(i = 0; i < NO_OF_QUEUES; i++)
36 if(TRUE == Adapter->PackInfo[i].bValid &&
37 (1 == Adapter->PackInfo[i].ucDirection))
39 liCurrentTime = ((tv.tv_sec-
40 Adapter->PackInfo[i].stLastUpdateTokenAt.tv_sec)*1000 +
41 (tv.tv_usec-Adapter->PackInfo[i].stLastUpdateTokenAt.tv_usec)/
45 Adapter->PackInfo[i].uiCurrentTokenCount += (ULONG)
46 ((Adapter->PackInfo[i].uiMaxAllowedRate) *
47 ((ULONG)((liCurrentTime)))/1000);
48 memcpy(&Adapter->PackInfo[i].stLastUpdateTokenAt,
49 &tv, sizeof(struct timeval));
50 Adapter->PackInfo[i].liLastUpdateTokenAt = liCurrentTime;
51 if((Adapter->PackInfo[i].uiCurrentTokenCount) >=
52 Adapter->PackInfo[i].uiMaxBucketSize)
54 Adapter->PackInfo[i].uiCurrentTokenCount =
55 Adapter->PackInfo[i].uiMaxBucketSize;
60 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "<=====\n");
66 /*********************************************************************
67 * Function - IsPacketAllowedForFlow()
69 * Description - This function checks whether the given packet from the
70 * specified queue can be allowed for transmission by
71 * checking the token count.
73 * Parameters - Adapter : Pointer to the Adpater structure.
74 * - iQIndex : The queue Identifier.
75 * - ulPacketLength: Number of bytes to be transmitted.
77 * Returns - The number of bytes allowed for transmission.
79 ***********************************************************************/
80 static ULONG GetSFTokenCount(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF)
82 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow ===>");
83 /* Validate the parameters */
84 if(NULL == Adapter || (psSF < Adapter->PackInfo &&
85 (uintptr_t)psSF > (uintptr_t) &Adapter->PackInfo[HiPriority]))
87 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));
91 if(FALSE != psSF->bValid && psSF->ucDirection)
93 if(0 != psSF->uiCurrentTokenCount)
95 return psSF->uiCurrentTokenCount;
99 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Not enough tokens in queue %zd Available %u\n",
100 psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount);
101 psSF->uiPendedLast = 1;
106 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Queue %zd not valid\n", psSF-Adapter->PackInfo);
108 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow <===");
113 @ingroup tx_functions
114 This function despatches packet from the specified queue.
115 @return Zero(success) or Negative value(failure)
117 static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,/**<Logical Adapter*/
118 struct bcm_packet_info *psSF, /**<Queue identifier*/
119 struct sk_buff* Packet) /**<Pointer to the packet to be sent*/
121 INT Status=STATUS_FAILURE;
122 UINT uiIndex =0,PktLen = 0;
124 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "=====>");
125 if(!Adapter || !Packet || !psSF)
127 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "Got NULL Adapter or Packet");
131 if(psSF->liDrainCalculated==0)
133 psSF->liDrainCalculated = jiffies;
135 ///send the packet to the fifo..
136 PktLen = Packet->len;
137 Status = SetupNextSend(Adapter, Packet, psSF->usVCID_Value);
140 for(uiIndex = 0 ; uiIndex < MIBS_MAX_HIST_ENTRIES ; uiIndex++)
141 { if((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) && (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex)))
142 Adapter->aTxPktSizeHist[uiIndex]++;
145 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "<=====");
149 /************************************************************************
150 * Function - CheckAndSendPacketFromIndex()
152 * Description - This function dequeues the data/control packet from the
153 * specified queue for transmission.
155 * Parameters - Adapter : Pointer to the driver control structure.
156 * - iQIndex : The queue Identifier.
160 ****************************************************************************/
161 static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF)
163 struct sk_buff *QueuePacket=NULL;
164 char *pControlPacket = NULL;
169 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "%zd ====>", (psSF-Adapter->PackInfo));
170 if((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount))//Get data packet
172 if(!psSF->ucDirection )
175 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "UpdateTokenCount ");
176 if(Adapter->IdleMode || Adapter->bPreparingForLowPowerMode)
177 return; /* in idle mode */
179 // Check for Free Descriptors
180 if(atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS)
182 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));
186 spin_lock_bh(&psSF->SFQueueLock);
187 QueuePacket=psSF->FirstTxQueue;
191 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Dequeuing Data Packet");
193 if(psSF->bEthCSSupport)
194 iPacketLen = QueuePacket->len;
196 iPacketLen = QueuePacket->len-ETH_HLEN;
199 if(iPacketLen <= GetSFTokenCount(Adapter, psSF))
201 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Allowed bytes %d",
204 DEQUEUEPACKET(psSF->FirstTxQueue,psSF->LastTxQueue);
205 psSF->uiCurrentBytesOnHost -= (QueuePacket->len);
206 psSF->uiCurrentPacketsOnHost--;
207 atomic_dec(&Adapter->TotalPacketCount);
208 spin_unlock_bh(&psSF->SFQueueLock);
210 Status = SendPacketFromQueue(Adapter, psSF, QueuePacket);
211 psSF->uiPendedLast = FALSE;
215 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo);
216 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n",
217 psSF->uiCurrentTokenCount, iPacketLen);
218 //this part indicates that because of non-availability of the tokens
219 //pkt has not been send out hence setting the pending flag indicating the host to send it out
220 //first next iteration .
221 psSF->uiPendedLast = TRUE;
222 spin_unlock_bh(&psSF->SFQueueLock);
227 spin_unlock_bh(&psSF->SFQueueLock);
233 if((atomic_read(&Adapter->CurrNumFreeTxDesc) > 0 ) &&
234 (atomic_read(&Adapter->index_rd_txcntrlpkt) !=
235 atomic_read(&Adapter->index_wr_txcntrlpkt))
238 pControlPacket = Adapter->txctlpacket
239 [(atomic_read(&Adapter->index_rd_txcntrlpkt)%MAX_CNTRL_PKTS)];
242 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Sending Control packet");
243 Status = SendControlPacket(Adapter, pControlPacket);
244 if(STATUS_SUCCESS==Status)
246 spin_lock_bh(&psSF->SFQueueLock);
247 psSF->NumOfPacketsSent++;
248 psSF->uiSentBytes+=((struct bcm_leader *)pControlPacket)->PLength;
249 psSF->uiSentPackets++;
250 atomic_dec(&Adapter->TotalPacketCount);
251 psSF->uiCurrentBytesOnHost -= ((struct bcm_leader *)pControlPacket)->PLength;
252 psSF->uiCurrentPacketsOnHost--;
253 atomic_inc(&Adapter->index_rd_txcntrlpkt);
254 spin_unlock_bh(&psSF->SFQueueLock);
257 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "SendControlPacket Failed\n");
261 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " Control Pkt is not available, Indexing is wrong....");
268 /*******************************************************************
269 * Function - transmit_packets()
271 * Description - This function transmits the packets from different
272 * queues, if free descriptors are available on target.
274 * Parameters - Adapter: Pointer to the Adapter structure.
277 ********************************************************************/
278 VOID transmit_packets(struct bcm_mini_adapter *Adapter)
280 UINT uiPrevTotalCount = 0;
283 BOOLEAN exit_flag = TRUE ;
285 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "=====>");
289 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX,TX_PACKETS, DBG_LVL_ALL, "Got NULL Adapter");
292 if(Adapter->device_removed == TRUE)
294 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device removed");
298 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nUpdateTokenCount ====>\n");
300 UpdateTokenCount(Adapter);
302 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nPruneQueueAllSF ====>\n");
304 PruneQueueAllSF(Adapter);
306 uiPrevTotalCount = atomic_read(&Adapter->TotalPacketCount);
308 for(iIndex=HiPriority;iIndex>=0;iIndex--)
310 if( !uiPrevTotalCount || (TRUE == Adapter->device_removed))
313 if(Adapter->PackInfo[iIndex].bValid &&
314 Adapter->PackInfo[iIndex].uiPendedLast &&
315 Adapter->PackInfo[iIndex].uiCurrentBytesOnHost)
317 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
318 CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
323 while(uiPrevTotalCount > 0 && !Adapter->device_removed)
326 //second iteration to parse non-pending queues
327 for(iIndex=HiPriority;iIndex>=0;iIndex--)
329 if( !uiPrevTotalCount || (TRUE == Adapter->device_removed))
332 if(Adapter->PackInfo[iIndex].bValid &&
333 Adapter->PackInfo[iIndex].uiCurrentBytesOnHost &&
334 !Adapter->PackInfo[iIndex].uiPendedLast )
336 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
337 CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
343 if(Adapter->IdleMode || Adapter->bPreparingForLowPowerMode)
345 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "In Idle Mode\n");
348 if(exit_flag == TRUE )
350 }/* end of inner while loop */
352 update_per_cid_rx (Adapter);
353 Adapter->txtransmit_running = 0;
354 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<======");