Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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}