1/********************************************************************** 2* LEAKYBUCKET.C 3* This file contains the routines related to Leaky Bucket Algorithm. 4***********************************************************************/ 5#include "headers.h" 6 7/** 8 * UpdateTokenCount() - Calculates the token count for each channel 9 * and updates the same in Adapter structure 10 * @Adapter: Pointer to the Adapter structure. 11 * 12 * Return: None 13 */ 14static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter) 15{ 16 ULONG liCurrentTime; 17 INT i = 0; 18 struct timeval tv; 19 struct bcm_packet_info *curr_pi; 20 21 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, 22 "=====>\n"); 23 if (NULL == Adapter) { 24 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, 25 DBG_LVL_ALL, "Adapter found NULL!\n"); 26 return; 27 } 28 29 do_gettimeofday(&tv); 30 for (i = 0; i < NO_OF_QUEUES; i++) { 31 curr_pi = &Adapter->PackInfo[i]; 32 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) / 37 1000); 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; 49 } 50 } 51 } 52 } 53 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, 54 "<=====\n"); 55} 56 57 58/** 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. 65 * 66 * Returns: The number of bytes allowed for transmission. 67 */ 68static ULONG GetSFTokenCount(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF) 69{ 70 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, 71 "IsPacketAllowedForFlow ===>"); 72 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)); 79 return 0; 80 } 81 82 if (false != psSF->bValid && psSF->ucDirection) { 83 if (0 != psSF->uiCurrentTokenCount) { 84 return psSF->uiCurrentTokenCount; 85 } else { 86 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, 87 DBG_LVL_ALL, 88 "Not enough tokens in queue %zd Available %u\n", 89 psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount); 90 psSF->uiPendedLast = 1; 91 } 92 } else { 93 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, 94 "IPAFF: Queue %zd not valid\n", 95 psSF-Adapter->PackInfo); 96 } 97 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, 98 "IsPacketAllowedForFlow <==="); 99 return 0; 100} 101 102/** 103@ingroup tx_functions 104This function despatches packet from the specified queue. 105@return Zero(success) or Negative value(failure) 106*/ 107static 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*/ 110{ 111 INT Status = STATUS_FAILURE; 112 UINT uiIndex = 0, PktLen = 0; 113 114 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, 115 "=====>"); 116 if (!Adapter || !Packet || !psSF) { 117 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, 118 "Got NULL Adapter or Packet"); 119 return -EINVAL; 120 } 121 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); 127 if (Status == 0) { 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]++; 132 } 133 } 134 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, 135 "<====="); 136 return Status; 137} 138 139static void get_data_packet(struct bcm_mini_adapter *ad, 140 struct bcm_packet_info *ps_sf) 141{ 142 int packet_len; 143 struct sk_buff *qpacket; 144 145 if (!ps_sf->ucDirection) 146 return; 147 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 */ 152 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)); 159 return; 160 } 161 162 spin_lock_bh(&ps_sf->SFQueueLock); 163 qpacket = ps_sf->FirstTxQueue; 164 165 if (qpacket) { 166 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, 167 "Dequeuing Data Packet"); 168 169 if (ps_sf->bEthCSSupport) 170 packet_len = qpacket->len; 171 else 172 packet_len = qpacket->len - ETH_HLEN; 173 174 packet_len <<= 3; 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", 178 (packet_len >> 3)); 179 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); 185 186 SendPacketFromQueue(ad, ps_sf, qpacket); 187 ps_sf->uiPendedLast = false; 188 } else { 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, 193 DBG_LVL_ALL, 194 "\nAvailable Tokens = %d required = %d\n", 195 ps_sf->uiCurrentTokenCount, 196 packet_len); 197 /* 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. 203 */ 204 ps_sf->uiPendedLast = TRUE; 205 spin_unlock_bh(&ps_sf->SFQueueLock); 206 } 207 } else { 208 spin_unlock_bh(&ps_sf->SFQueueLock); 209 } 210} 211 212static void send_control_packet(struct bcm_mini_adapter *ad, 213 struct bcm_packet_info *ps_sf) 214{ 215 char *ctrl_packet = NULL; 216 INT status = 0; 217 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)]; 223 if (ctrl_packet) { 224 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS, 225 DBG_LVL_ALL, 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); 238 } else { 239 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS, 240 DBG_LVL_ALL, 241 "SendControlPacket Failed\n"); 242 } 243 } else { 244 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, TX_PACKETS, 245 DBG_LVL_ALL, 246 " Control Pkt is not available, Indexing is wrong...."); 247 } 248 } 249} 250 251/** 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. 256 * 257 * Returns: None. 258 */ 259static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, 260 struct bcm_packet_info *psSF) 261{ 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 */ 267 268 get_data_packet(Adapter, psSF); 269 } else { 270 send_control_packet(Adapter, psSF); 271 } 272} 273 274 275/** 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. 279 * 280 * Returns: None. 281 */ 282VOID transmit_packets(struct bcm_mini_adapter *Adapter) 283{ 284 UINT uiPrevTotalCount = 0; 285 int iIndex = 0; 286 287 bool exit_flag = TRUE; 288 289 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, 290 "=====>"); 291 292 if (NULL == Adapter) { 293 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, 294 "Got NULL Adapter"); 295 return; 296 } 297 if (Adapter->device_removed == TRUE) { 298 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, 299 "Device removed"); 300 return; 301 } 302 303 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, 304 "\nUpdateTokenCount ====>\n"); 305 306 UpdateTokenCount(Adapter); 307 308 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, 309 "\nPruneQueueAllSF ====>\n"); 310 311 PruneQueueAllSF(Adapter); 312 313 uiPrevTotalCount = atomic_read(&Adapter->TotalPacketCount); 314 315 for (iIndex = HiPriority; iIndex >= 0; iIndex--) { 316 if (!uiPrevTotalCount || (TRUE == Adapter->device_removed)) 317 break; 318 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, 323 DBG_LVL_ALL, 324 "Calling CheckAndSendPacketFromIndex.."); 325 CheckAndSendPacketFromIndex(Adapter, 326 &Adapter->PackInfo[iIndex]); 327 uiPrevTotalCount--; 328 } 329 } 330 331 while (uiPrevTotalCount > 0 && !Adapter->device_removed) { 332 exit_flag = TRUE; 333 /* second iteration to parse non-pending queues */ 334 for (iIndex = HiPriority; iIndex >= 0; iIndex--) { 335 if (!uiPrevTotalCount || 336 (TRUE == Adapter->device_removed)) 337 break; 338 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]); 346 uiPrevTotalCount--; 347 exit_flag = false; 348 } 349 } 350 351 if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) { 352 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, 353 DBG_LVL_ALL, "In Idle Mode\n"); 354 break; 355 } 356 if (exit_flag == TRUE) 357 break; 358 } /* end of inner while loop */ 359 360 update_per_cid_rx(Adapter); 361 Adapter->txtransmit_running = 0; 362 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, 363 "<======"); 364} 365