LeakyBucket.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /**********************************************************************
  2. * LEAKYBUCKET.C
  3. * This file contains the routines related to Leaky Bucket Algorithm.
  4. ***********************************************************************/
  5. #include "headers.h"
  6. /**
  7. * UpdateTokenCount() - Calculates the token count for each channel
  8. * and updates the same in Adapter structure
  9. * @Adapter: Pointer to the Adapter structure.
  10. *
  11. * Return: None
  12. */
  13. static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter)
  14. {
  15. ULONG liCurrentTime;
  16. INT i = 0;
  17. struct timeval tv;
  18. struct bcm_packet_info *curr_pi;
  19. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
  20. "=====>\n");
  21. if (NULL == Adapter) {
  22. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS,
  23. DBG_LVL_ALL, "Adapter found NULL!\n");
  24. return;
  25. }
  26. do_gettimeofday(&tv);
  27. for (i = 0; i < NO_OF_QUEUES; i++) {
  28. curr_pi = &Adapter->PackInfo[i];
  29. if (TRUE == curr_pi->bValid && (1 == curr_pi->ucDirection)) {
  30. liCurrentTime = ((tv.tv_sec -
  31. curr_pi->stLastUpdateTokenAt.tv_sec)*1000 +
  32. (tv.tv_usec - curr_pi->stLastUpdateTokenAt.tv_usec) /
  33. 1000);
  34. if (0 != liCurrentTime) {
  35. curr_pi->uiCurrentTokenCount += (ULONG)
  36. ((curr_pi->uiMaxAllowedRate) *
  37. ((ULONG)((liCurrentTime)))/1000);
  38. memcpy(&curr_pi->stLastUpdateTokenAt, &tv,
  39. sizeof(struct timeval));
  40. curr_pi->liLastUpdateTokenAt = liCurrentTime;
  41. if (curr_pi->uiCurrentTokenCount >=
  42. curr_pi->uiMaxBucketSize) {
  43. curr_pi->uiCurrentTokenCount =
  44. curr_pi->uiMaxBucketSize;
  45. }
  46. }
  47. }
  48. }
  49. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
  50. "<=====\n");
  51. }
  52. /**
  53. * IsPacketAllowedForFlow() - This function checks whether the given
  54. * packet from the specified queue can be allowed for transmission by
  55. * checking the token count.
  56. * @Adapter: Pointer to the Adpater structure.
  57. * @iQIndex: The queue Identifier.
  58. * @ulPacketLength: Number of bytes to be transmitted.
  59. *
  60. * Returns: The number of bytes allowed for transmission.
  61. */
  62. static ULONG GetSFTokenCount(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF)
  63. {
  64. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
  65. "IsPacketAllowedForFlow ===>");
  66. /* Validate the parameters */
  67. if (NULL == Adapter || (psSF < Adapter->PackInfo &&
  68. (uintptr_t)psSF > (uintptr_t) &Adapter->PackInfo[HiPriority])) {
  69. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
  70. "IPAFF: Got wrong Parameters:Adapter: %p, QIndex: %zd\n",
  71. Adapter, (psSF-Adapter->PackInfo));
  72. return 0;
  73. }
  74. if (false != psSF->bValid && psSF->ucDirection) {
  75. if (0 != psSF->uiCurrentTokenCount) {
  76. return psSF->uiCurrentTokenCount;
  77. } else {
  78. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS,
  79. DBG_LVL_ALL,
  80. "Not enough tokens in queue %zd Available %u\n",
  81. psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount);
  82. psSF->uiPendedLast = 1;
  83. }
  84. } else {
  85. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
  86. "IPAFF: Queue %zd not valid\n",
  87. psSF-Adapter->PackInfo);
  88. }
  89. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
  90. "IsPacketAllowedForFlow <===");
  91. return 0;
  92. }
  93. /**
  94. @ingroup tx_functions
  95. This function despatches packet from the specified queue.
  96. @return Zero(success) or Negative value(failure)
  97. */
  98. static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,/**<Logical Adapter*/
  99. struct bcm_packet_info *psSF, /**<Queue identifier*/
  100. struct sk_buff *Packet) /**<Pointer to the packet to be sent*/
  101. {
  102. INT Status = STATUS_FAILURE;
  103. UINT uiIndex = 0, PktLen = 0;
  104. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL,
  105. "=====>");
  106. if (!Adapter || !Packet || !psSF) {
  107. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL,
  108. "Got NULL Adapter or Packet");
  109. return -EINVAL;
  110. }
  111. if (psSF->liDrainCalculated == 0)
  112. psSF->liDrainCalculated = jiffies;
  113. /* send the packet to the fifo.. */
  114. PktLen = Packet->len;
  115. Status = SetupNextSend(Adapter, Packet, psSF->usVCID_Value);
  116. if (Status == 0) {
  117. for (uiIndex = 0; uiIndex < MIBS_MAX_HIST_ENTRIES; uiIndex++) {
  118. if ((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) &&
  119. (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex)))
  120. Adapter->aTxPktSizeHist[uiIndex]++;
  121. }
  122. }
  123. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL,
  124. "<=====");
  125. return Status;
  126. }
  127. static void get_data_packet(struct bcm_mini_adapter *ad,
  128. struct bcm_packet_info *ps_sf)
  129. {
  130. int packet_len;
  131. struct sk_buff *qpacket;
  132. if (!ps_sf->ucDirection)
  133. return;
  134. BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
  135. "UpdateTokenCount ");
  136. if (ad->IdleMode || ad->bPreparingForLowPowerMode)
  137. return; /* in idle mode */
  138. /* Check for Free Descriptors */
  139. if (atomic_read(&ad->CurrNumFreeTxDesc) <=
  140. MINIMUM_PENDING_DESCRIPTORS) {
  141. BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
  142. " No Free Tx Descriptor(%d) is available for Data pkt..",
  143. atomic_read(&ad->CurrNumFreeTxDesc));
  144. return;
  145. }
  146. spin_lock_bh(&ps_sf->SFQueueLock);
  147. qpacket = ps_sf->FirstTxQueue;
  148. if (qpacket) {
  149. BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
  150. "Dequeuing Data Packet");
  151. if (ps_sf->bEthCSSupport)
  152. packet_len = qpacket->len;
  153. else
  154. packet_len = qpacket->len - ETH_HLEN;
  155. packet_len <<= 3;
  156. if (packet_len <= GetSFTokenCount(ad, ps_sf)) {
  157. BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
  158. DBG_LVL_ALL, "Allowed bytes %d",
  159. (packet_len >> 3));
  160. DEQUEUEPACKET(ps_sf->FirstTxQueue, ps_sf->LastTxQueue);
  161. ps_sf->uiCurrentBytesOnHost -= (qpacket->len);
  162. ps_sf->uiCurrentPacketsOnHost--;
  163. atomic_dec(&ad->TotalPacketCount);
  164. spin_unlock_bh(&ps_sf->SFQueueLock);
  165. SendPacketFromQueue(ad, ps_sf, qpacket);
  166. ps_sf->uiPendedLast = false;
  167. } else {
  168. BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
  169. DBG_LVL_ALL, "For Queue: %zd\n",
  170. ps_sf - ad->PackInfo);
  171. BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
  172. DBG_LVL_ALL,
  173. "\nAvailable Tokens = %d required = %d\n",
  174. ps_sf->uiCurrentTokenCount,
  175. packet_len);
  176. /*
  177. this part indicates that because of
  178. non-availability of the tokens
  179. pkt has not been send out hence setting the
  180. pending flag indicating the host to send it out
  181. first next iteration.
  182. */
  183. ps_sf->uiPendedLast = TRUE;
  184. spin_unlock_bh(&ps_sf->SFQueueLock);
  185. }
  186. } else {
  187. spin_unlock_bh(&ps_sf->SFQueueLock);
  188. }
  189. }
  190. static void send_control_packet(struct bcm_mini_adapter *ad,
  191. struct bcm_packet_info *ps_sf)
  192. {
  193. char *ctrl_packet = NULL;
  194. INT status = 0;
  195. if ((atomic_read(&ad->CurrNumFreeTxDesc) > 0) &&
  196. (atomic_read(&ad->index_rd_txcntrlpkt) !=
  197. atomic_read(&ad->index_wr_txcntrlpkt))) {
  198. ctrl_packet = ad->txctlpacket
  199. [(atomic_read(&ad->index_rd_txcntrlpkt)%MAX_CNTRL_PKTS)];
  200. if (ctrl_packet) {
  201. BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
  202. DBG_LVL_ALL,
  203. "Sending Control packet");
  204. status = SendControlPacket(ad, ctrl_packet);
  205. if (STATUS_SUCCESS == status) {
  206. spin_lock_bh(&ps_sf->SFQueueLock);
  207. ps_sf->NumOfPacketsSent++;
  208. ps_sf->uiSentBytes += ((struct bcm_leader *)ctrl_packet)->PLength;
  209. ps_sf->uiSentPackets++;
  210. atomic_dec(&ad->TotalPacketCount);
  211. ps_sf->uiCurrentBytesOnHost -= ((struct bcm_leader *)ctrl_packet)->PLength;
  212. ps_sf->uiCurrentPacketsOnHost--;
  213. atomic_inc(&ad->index_rd_txcntrlpkt);
  214. spin_unlock_bh(&ps_sf->SFQueueLock);
  215. } else {
  216. BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
  217. DBG_LVL_ALL,
  218. "SendControlPacket Failed\n");
  219. }
  220. } else {
  221. BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS,
  222. DBG_LVL_ALL,
  223. " Control Pkt is not available, Indexing is wrong....");
  224. }
  225. }
  226. }
  227. /**
  228. * CheckAndSendPacketFromIndex() - This function dequeues the
  229. * data/control packet from the specified queue for transmission.
  230. * @Adapter: Pointer to the driver control structure.
  231. * @iQIndex: The queue Identifier.
  232. *
  233. * Returns: None.
  234. */
  235. static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter,
  236. struct bcm_packet_info *psSF)
  237. {
  238. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
  239. "%zd ====>", (psSF-Adapter->PackInfo));
  240. if ((psSF != &Adapter->PackInfo[HiPriority]) &&
  241. Adapter->LinkUpStatus &&
  242. atomic_read(&psSF->uiPerSFTxResourceCount)) { /* Get data packet */
  243. get_data_packet(Adapter, psSF);
  244. } else {
  245. send_control_packet(Adapter, psSF);
  246. }
  247. }
  248. /**
  249. * transmit_packets() - This function transmits the packets from
  250. * different queues, if free descriptors are available on target.
  251. * @Adapter: Pointer to the Adapter structure.
  252. *
  253. * Returns: None.
  254. */
  255. VOID transmit_packets(struct bcm_mini_adapter *Adapter)
  256. {
  257. UINT uiPrevTotalCount = 0;
  258. int iIndex = 0;
  259. bool exit_flag = TRUE;
  260. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
  261. "=====>");
  262. if (NULL == Adapter) {
  263. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
  264. "Got NULL Adapter");
  265. return;
  266. }
  267. if (Adapter->device_removed == TRUE) {
  268. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
  269. "Device removed");
  270. return;
  271. }
  272. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
  273. "\nUpdateTokenCount ====>\n");
  274. UpdateTokenCount(Adapter);
  275. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
  276. "\nPruneQueueAllSF ====>\n");
  277. PruneQueueAllSF(Adapter);
  278. uiPrevTotalCount = atomic_read(&Adapter->TotalPacketCount);
  279. for (iIndex = HiPriority; iIndex >= 0; iIndex--) {
  280. if (!uiPrevTotalCount || (TRUE == Adapter->device_removed))
  281. break;
  282. if (Adapter->PackInfo[iIndex].bValid &&
  283. Adapter->PackInfo[iIndex].uiPendedLast &&
  284. Adapter->PackInfo[iIndex].uiCurrentBytesOnHost) {
  285. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS,
  286. DBG_LVL_ALL,
  287. "Calling CheckAndSendPacketFromIndex..");
  288. CheckAndSendPacketFromIndex(Adapter,
  289. &Adapter->PackInfo[iIndex]);
  290. uiPrevTotalCount--;
  291. }
  292. }
  293. while (uiPrevTotalCount > 0 && !Adapter->device_removed) {
  294. exit_flag = TRUE;
  295. /* second iteration to parse non-pending queues */
  296. for (iIndex = HiPriority; iIndex >= 0; iIndex--) {
  297. if (!uiPrevTotalCount ||
  298. (TRUE == Adapter->device_removed))
  299. break;
  300. if (Adapter->PackInfo[iIndex].bValid &&
  301. Adapter->PackInfo[iIndex].uiCurrentBytesOnHost &&
  302. !Adapter->PackInfo[iIndex].uiPendedLast) {
  303. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX,
  304. TX_PACKETS, DBG_LVL_ALL,
  305. "Calling CheckAndSendPacketFromIndex..");
  306. CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
  307. uiPrevTotalCount--;
  308. exit_flag = false;
  309. }
  310. }
  311. if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) {
  312. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS,
  313. DBG_LVL_ALL, "In Idle Mode\n");
  314. break;
  315. }
  316. if (exit_flag == TRUE)
  317. break;
  318. } /* end of inner while loop */
  319. update_per_cid_rx(Adapter);
  320. Adapter->txtransmit_running = 0;
  321. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
  322. "<======");
  323. }