summaryrefslogtreecommitdiffstats
path: root/drivers/staging/bcm/LeakyBucket.c
diff options
context:
space:
mode:
authorStephen Hemminger <stephen.hemminger@vyatta.com>2010-09-08 14:46:36 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2010-09-08 21:15:06 -0700
commitf8942e07a3db9d82e8fb11d3d494876b8bae9ff9 (patch)
tree2406636a4f9a4ac6b0bfc90e07aefa8b1b18b8ff /drivers/staging/bcm/LeakyBucket.c
parent2d2f03b022186e6d7520a758abdea9c04a2969fe (diff)
downloadlinux-f8942e07a3db9d82e8fb11d3d494876b8bae9ff9.tar.bz2
staging: Beeceem USB Wimax driver
The Sprint 4G network uses a Wimax dongle with Beecem chipset. The driver is typical of out of tree drivers, but maybe useful for people, and the hardware is readily available. Here is a staging ready version (i.e warts and all) 0. Started with Rel_5.2.7.3P1_USB from Sprint4GDeveloperPack-1.1 1. Consolidated files in staging 2. Remove Dos cr/lf 3. Remove unnecessary ioctl from usbbcm_fops Applied patches that were in the developer pack, surprising there were ones for 2.6.35 already. This is compile tested only, see TODO for what still needs to be done. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/bcm/LeakyBucket.c')
-rw-r--r--drivers/staging/bcm/LeakyBucket.c399
1 files changed, 399 insertions, 0 deletions
diff --git a/drivers/staging/bcm/LeakyBucket.c b/drivers/staging/bcm/LeakyBucket.c
new file mode 100644
index 000000000000..1875c8289010
--- /dev/null
+++ b/drivers/staging/bcm/LeakyBucket.c
@@ -0,0 +1,399 @@
+/**********************************************************************
+* LEAKYBUCKET.C
+* This file contains the routines related to Leaky Bucket Algorithm.
+***********************************************************************/
+#include "headers.h"
+
+/*********************************************************************
+* Function - UpdateTokenCount()
+*
+* Description - This function calculates the token count for each
+* channel and updates the same in Adapter strucuture.
+*
+* Parameters - Adapter: Pointer to the Adapter structure.
+*
+* Returns - None
+**********************************************************************/
+
+VOID UpdateTokenCount(register PMINI_ADAPTER Adapter)
+{
+ ULONG liCurrentTime;
+ INT i = 0;
+ struct timeval tv;
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "=====>\n");
+ if(NULL == Adapter)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Adapter found NULL!\n");
+ return;
+ }
+
+ do_gettimeofday(&tv);
+ for(i = 0; i < NO_OF_QUEUES; i++)
+ {
+ if(TRUE == Adapter->PackInfo[i].bValid &&
+ (1 == Adapter->PackInfo[i].ucDirection))
+ {
+ liCurrentTime = ((tv.tv_sec-
+ Adapter->PackInfo[i].stLastUpdateTokenAt.tv_sec)*1000 +
+ (tv.tv_usec-Adapter->PackInfo[i].stLastUpdateTokenAt.tv_usec)/
+ 1000);
+ if(0!=liCurrentTime)
+ {
+ Adapter->PackInfo[i].uiCurrentTokenCount += (ULONG)
+ ((Adapter->PackInfo[i].uiMaxAllowedRate) *
+ ((ULONG)((liCurrentTime)))/1000);
+ memcpy(&Adapter->PackInfo[i].stLastUpdateTokenAt,
+ &tv, sizeof(struct timeval));
+ Adapter->PackInfo[i].liLastUpdateTokenAt = liCurrentTime;
+ if((Adapter->PackInfo[i].uiCurrentTokenCount) >=
+ Adapter->PackInfo[i].uiMaxBucketSize)
+ {
+ Adapter->PackInfo[i].uiCurrentTokenCount =
+ Adapter->PackInfo[i].uiMaxBucketSize;
+ }
+ }
+ }
+ }
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "<=====\n");
+ return;
+
+}
+
+
+/*********************************************************************
+* Function - IsPacketAllowedForFlow()
+*
+* Description - This function checks whether the given packet from the
+* specified queue can be allowed for transmission by
+* checking the token count.
+*
+* Parameters - Adapter : Pointer to the Adpater structure.
+* - iQIndex : The queue Identifier.
+* - ulPacketLength: Number of bytes to be transmitted.
+*
+* Returns - The number of bytes allowed for transmission.
+*
+***********************************************************************/
+static __inline ULONG GetSFTokenCount(PMINI_ADAPTER Adapter, PacketInfo *psSF)
+{
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow ===>");
+ /* Validate the parameters */
+ if(NULL == Adapter || (psSF < Adapter->PackInfo &&
+ (UINT)psSF > (UINT) &Adapter->PackInfo[HiPriority]))
+ {
+ 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));
+ return 0;
+ }
+
+ if(FALSE != psSF->bValid && psSF->ucDirection)
+ {
+ if(0 != psSF->uiCurrentTokenCount)
+ {
+ return psSF->uiCurrentTokenCount;
+ }
+ else
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Not enough tokens in queue %d Available %u\n",
+ psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount);
+ psSF->uiPendedLast = 1;
+ }
+ }
+ else
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Queue %d not valid\n", psSF-Adapter->PackInfo);
+ }
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow <===");
+ return 0;
+}
+
+static __inline void RemovePacketFromQueue(PacketInfo *pPackInfo , struct sk_buff *Packet)
+{
+ struct sk_buff *psQueueCurrent=NULL, *psLastQueueNode=NULL;
+ psQueueCurrent = pPackInfo->FirstTxQueue;
+ while(psQueueCurrent)
+ {
+ if((UINT)Packet == (UINT)psQueueCurrent)
+ {
+ if((UINT)psQueueCurrent == (UINT)pPackInfo->FirstTxQueue)
+ {
+ pPackInfo->FirstTxQueue=psQueueCurrent->next;
+ if((UINT)psQueueCurrent==(UINT)pPackInfo->LastTxQueue)
+ pPackInfo->LastTxQueue=NULL;
+ }
+ else
+ {
+ psLastQueueNode->next=psQueueCurrent->next;
+ }
+ break;
+ }
+ psLastQueueNode = psQueueCurrent;
+ psQueueCurrent=psQueueCurrent->next;
+ }
+}
+/**
+@ingroup tx_functions
+This function despatches packet from the specified queue.
+@return Zero(success) or Negative value(failure)
+*/
+static __inline INT SendPacketFromQueue(PMINI_ADAPTER Adapter,/**<Logical Adapter*/
+ PacketInfo *psSF, /**<Queue identifier*/
+ struct sk_buff* Packet) /**<Pointer to the packet to be sent*/
+{
+ INT Status=STATUS_FAILURE;
+ UINT uiIndex =0,PktLen = 0;
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "=====>");
+ if(!Adapter || !Packet || !psSF)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "Got NULL Adapter or Packet");
+ return -EINVAL;
+ }
+
+ if(psSF->liDrainCalculated==0)
+ {
+ psSF->liDrainCalculated = jiffies;
+ }
+ ///send the packet to the fifo..
+ PktLen = Packet->len;
+ Status = SetupNextSend(Adapter, Packet, psSF->usVCID_Value);
+ if(Status == 0)
+ {
+ for(uiIndex = 0 ; uiIndex < MIBS_MAX_HIST_ENTRIES ; uiIndex++)
+ { if((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) && (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex)))
+ Adapter->aTxPktSizeHist[uiIndex]++;
+ }
+ }
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "<=====");
+ return Status;
+}
+
+/************************************************************************
+* Function - CheckAndSendPacketFromIndex()
+*
+* Description - This function dequeues the data/control packet from the
+* specified queue for transmission.
+*
+* Parameters - Adapter : Pointer to the driver control structure.
+* - iQIndex : The queue Identifier.
+*
+* Returns - None.
+*
+****************************************************************************/
+static __inline VOID CheckAndSendPacketFromIndex
+(PMINI_ADAPTER Adapter, PacketInfo *psSF)
+{
+ struct sk_buff *QueuePacket=NULL;
+ char *pControlPacket = NULL;
+ INT Status=0;
+ int iPacketLen=0;
+
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "%d ====>", (psSF-Adapter->PackInfo));
+ if(((UINT)psSF != (UINT)&Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount))//Get data packet
+ {
+ if(!psSF->ucDirection )
+ return;
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "UpdateTokenCount ");
+ if(Adapter->IdleMode || Adapter->bPreparingForLowPowerMode)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle Mode..Hence blocking Data Packets..\n");
+ return;
+ }
+ // Check for Free Descriptors
+ if(atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS)
+ {
+ 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));
+ return ;
+ }
+
+#if 0
+ PruneQueue(Adapter,(psSF-Adapter->PackInfo));
+#endif
+ spin_lock_bh(&psSF->SFQueueLock);
+ QueuePacket=psSF->FirstTxQueue;
+
+ if(QueuePacket)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Dequeuing Data Packet");
+
+ if(psSF->bEthCSSupport)
+ iPacketLen = QueuePacket->len;
+ else
+ iPacketLen = QueuePacket->len-ETH_HLEN;
+
+ iPacketLen<<=3;
+ if(iPacketLen <= GetSFTokenCount(Adapter, psSF))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Allowed bytes %d",
+ (iPacketLen >> 3));
+
+ DEQUEUEPACKET(psSF->FirstTxQueue,psSF->LastTxQueue);
+ psSF->uiCurrentBytesOnHost -= (QueuePacket->len);
+ psSF->uiCurrentPacketsOnHost--;
+ atomic_dec(&Adapter->TotalPacketCount);
+ spin_unlock_bh(&psSF->SFQueueLock);
+
+ Status = SendPacketFromQueue(Adapter, psSF, QueuePacket);
+ psSF->uiPendedLast = FALSE;
+ }
+ else
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %d\n", psSF-Adapter->PackInfo);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n",
+ psSF->uiCurrentTokenCount, iPacketLen);
+ //this part indicates that becuase of non-availability of the tokens
+ //pkt has not been send out hence setting the pending flag indicating the host to send it out
+ //first next iteration .
+ psSF->uiPendedLast = TRUE;
+ spin_unlock_bh(&psSF->SFQueueLock);
+ }
+ }
+ else
+ {
+ spin_unlock_bh(&psSF->SFQueueLock);
+ }
+ }
+ else
+ {
+
+ if((atomic_read(&Adapter->CurrNumFreeTxDesc) > 0 ) &&
+ (atomic_read(&Adapter->index_rd_txcntrlpkt) !=
+ atomic_read(&Adapter->index_wr_txcntrlpkt))
+ )
+ {
+ pControlPacket = Adapter->txctlpacket
+ [(atomic_read(&Adapter->index_rd_txcntrlpkt)%MAX_CNTRL_PKTS)];
+ if(pControlPacket)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Sending Control packet");
+ Status = SendControlPacket(Adapter, pControlPacket);
+ if(STATUS_SUCCESS==Status)
+ {
+ spin_lock_bh(&psSF->SFQueueLock);
+ psSF->NumOfPacketsSent++;
+ psSF->uiSentBytes+=((PLEADER)pControlPacket)->PLength;
+ psSF->uiSentPackets++;
+ atomic_dec(&Adapter->TotalPacketCount);
+ psSF->uiCurrentBytesOnHost -= ((PLEADER)pControlPacket)->PLength;
+ psSF->uiCurrentPacketsOnHost--;
+ atomic_inc(&Adapter->index_rd_txcntrlpkt);
+ spin_unlock_bh(&psSF->SFQueueLock);
+ }
+ else
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "SendControlPacket Failed\n");
+ }
+ else
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " Control Pkt is not available, Indexing is wrong....");
+ }
+ }
+ }
+
+ if(Status != STATUS_SUCCESS) //Tx of data packet to device Failed
+ {
+ if(Adapter->bcm_jiffies == 0)
+ Adapter->bcm_jiffies = jiffies;
+ }
+ else
+ {
+ Adapter->bcm_jiffies = 0;
+ }
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<=====");
+}
+
+
+/*******************************************************************
+* Function - transmit_packets()
+*
+* Description - This function transmits the packets from different
+* queues, if free descriptors are available on target.
+*
+* Parameters - Adapter: Pointer to the Adapter structure.
+*
+* Returns - None.
+********************************************************************/
+VOID transmit_packets(PMINI_ADAPTER Adapter)
+{
+ UINT uiPrevTotalCount = 0;
+ int iIndex = 0;
+
+ BOOLEAN exit_flag = TRUE ;
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "=====>");
+
+ if(NULL == Adapter)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX,TX_PACKETS, DBG_LVL_ALL, "Got NULL Adapter");
+ return;
+ }
+ if(Adapter->device_removed == TRUE)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device removed");
+ return;
+ }
+
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nUpdateTokenCount ====>\n");
+
+ UpdateTokenCount(Adapter);
+
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nPruneQueueAllSF ====>\n");
+
+ PruneQueueAllSF(Adapter);
+
+ uiPrevTotalCount = atomic_read(&Adapter->TotalPacketCount);
+
+ for(iIndex=HiPriority;iIndex>=0;iIndex--)
+ {
+ if( !uiPrevTotalCount || (TRUE == Adapter->device_removed))
+ break;
+
+ if(Adapter->PackInfo[iIndex].bValid &&
+ Adapter->PackInfo[iIndex].uiPendedLast &&
+ Adapter->PackInfo[iIndex].uiCurrentBytesOnHost)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
+ CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
+ uiPrevTotalCount--;
+ }
+ }
+
+ while(uiPrevTotalCount > 0 && !Adapter->device_removed)
+ {
+ exit_flag = TRUE ;
+ //second iteration to parse non-pending queues
+ for(iIndex=HiPriority;iIndex>=0;iIndex--)
+ {
+ if( !uiPrevTotalCount || (TRUE == Adapter->device_removed))
+ break;
+
+ if(Adapter->PackInfo[iIndex].bValid &&
+ Adapter->PackInfo[iIndex].uiCurrentBytesOnHost &&
+ !Adapter->PackInfo[iIndex].uiPendedLast )
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
+ CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
+ uiPrevTotalCount--;
+ exit_flag = FALSE;
+ }
+ }
+
+ if(Adapter->IdleMode || Adapter->bPreparingForLowPowerMode)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "In Idle Mode\n");
+ break;
+ }
+ if(exit_flag == TRUE )
+ break ;
+ }/* end of inner while loop */
+ if(Adapter->bcm_jiffies == 0 &&
+ atomic_read(&Adapter->TotalPacketCount) != 0 &&
+ uiPrevTotalCount == atomic_read(&Adapter->TotalPacketCount))
+ {
+ Adapter->bcm_jiffies = jiffies;
+ }
+ update_per_cid_rx (Adapter);
+ Adapter->txtransmit_running = 0;
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<======");
+}