/drivers/net/wireless/sd8797/mlan/mlan_wmm.c
C | 2521 lines | 1609 code | 319 blank | 593 comment | 217 complexity | 023668abc83217137f2911e85c46548b MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
Large files files are truncated, but you can click here to view the full file
1/** @file mlan_wmm.c 2 * 3 * @brief This file contains functions for WMM. 4 * 5 * Copyright (C) 2008-2011, Marvell International Ltd. 6 * 7 * This software file (the "File") is distributed by Marvell International 8 * Ltd. under the terms of the GNU General Public License Version 2, June 1991 9 * (the "License"). You may use, redistribute and/or modify this File in 10 * accordance with the terms and conditions of the License, a copy of which 11 * is available by writing to the Free Software Foundation, Inc., 12 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 13 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 14 * 15 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 17 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 18 * this warranty disclaimer. 19 */ 20 21/******************************************************** 22Change log: 23 10/24/2008: initial version 24********************************************************/ 25 26#include "mlan.h" 27#ifdef STA_SUPPORT 28#include "mlan_join.h" 29#endif 30#include "mlan_util.h" 31#include "mlan_fw.h" 32#include "mlan_main.h" 33#include "mlan_wmm.h" 34#include "mlan_11n.h" 35#include "mlan_sdio.h" 36 37/******************************************************** 38 Local Variables 39********************************************************/ 40 41/** Maximum value FW can accept for driver delay in packet transmission */ 42#define DRV_PKT_DELAY_TO_FW_MAX 512 43 44/* 45 * Upper and Lower threshold for packet queuing in the driver 46 47 * - When the number of packets queued reaches the upper limit, 48 * the driver will stop the net queue in the app/kernel space. 49 50 * - When the number of packets drops beneath the lower limit after 51 * having reached the upper limit, the driver will restart the net 52 * queue. 53 */ 54 55/** Lower threshold for packet queuing in the driver. 56 * When the number of packets drops beneath the lower limit after having 57 * reached the upper limit, the driver will restart the net queue. 58 */ 59#define WMM_QUEUED_PACKET_LOWER_LIMIT 180 60 61/** Upper threshold for packet queuing in the driver. 62 * When the number of packets queued reaches the upper limit, the driver 63 * will stop the net queue in the app/kernel space. 64 */ 65#define WMM_QUEUED_PACKET_UPPER_LIMIT 200 66 67/** Offset for TOS field in the IP header */ 68#define IPTOS_OFFSET 5 69 70/** WMM information IE */ 71static const t_u8 wmm_info_ie[] = { WMM_IE, 0x07, 72 0x00, 0x50, 0xf2, 0x02, 73 0x00, 0x01, 0x00 74}; 75 76/** 77 * AC Priorities go from AC_BK to AC_VO. The ACI enumeration for AC_BK (1) 78 * is higher than the enumeration for AC_BE (0); hence the needed 79 * mapping conversion for wmm AC to priority Queue Index 80 */ 81static const t_u8 wmm_aci_to_qidx_map[] = { WMM_AC_BE, 82 WMM_AC_BK, 83 WMM_AC_VI, 84 WMM_AC_VO 85}; 86 87/** 88 * This table will be used to store the tid values based on ACs. 89 * It is initialized to default values per TID. 90 */ 91t_u8 tos_to_tid[] = { 92 /* TID DSCP_P2 DSCP_P1 DSCP_P0 WMM_AC */ 93 0x01, /* 0 1 0 AC_BK */ 94 0x02, /* 0 0 0 AC_BK */ 95 0x00, /* 0 0 1 AC_BE */ 96 0x03, /* 0 1 1 AC_BE */ 97 0x04, /* 1 0 0 AC_VI */ 98 0x05, /* 1 0 1 AC_VI */ 99 0x06, /* 1 1 0 AC_VO */ 100 0x07 /* 1 1 1 AC_VO */ 101}; 102 103/** 104 * This table inverses the tos_to_tid operation to get a priority 105 * which is in sequential order, and can be compared. 106 * Use this to compare the priority of two different TIDs. 107 */ 108t_u8 tos_to_tid_inv[] = { 0x02, /* from tos_to_tid[2] = 0 */ 109 0x00, /* from tos_to_tid[0] = 1 */ 110 0x01, /* from tos_to_tid[1] = 2 */ 111 0x03, 112 0x04, 113 0x05, 114 0x06, 115 0x07 116}; 117 118/** 119 * This table will provide the tid value for given ac. This table does not 120 * change and will be used to copy back the default values to tos_to_tid in 121 * case of disconnect. 122 */ 123const t_u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} }; 124 125/* Map of TOS UP values to WMM AC */ 126static const mlan_wmm_ac_e tos_to_ac[] = { WMM_AC_BE, 127 WMM_AC_BK, 128 WMM_AC_BK, 129 WMM_AC_BE, 130 WMM_AC_VI, 131 WMM_AC_VI, 132 WMM_AC_VO, 133 WMM_AC_VO 134}; 135 136raListTbl *wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid, 137 t_u8 * ra_addr); 138 139/******************************************************** 140 Local Functions 141********************************************************/ 142#ifdef DEBUG_LEVEL2 143/** 144 * @brief Debug print function to display the priority parameters for a WMM AC 145 * 146 * @param pac_param Pointer to the AC parameters to display 147 * 148 * @return N/A 149 */ 150static void 151wlan_wmm_ac_debug_print(const IEEEtypes_WmmAcParameters_t * pac_param) 152{ 153 const char *ac_str[] = { "BK", "BE", "VI", "VO" }; 154 155 ENTER(); 156 157 PRINTM(MINFO, "WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, " 158 "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n", 159 ac_str[wmm_aci_to_qidx_map[pac_param->aci_aifsn.aci]], 160 pac_param->aci_aifsn.aci, pac_param->aci_aifsn.acm, 161 pac_param->aci_aifsn.aifsn, pac_param->ecw.ecw_min, 162 pac_param->ecw.ecw_max, wlan_le16_to_cpu(pac_param->tx_op_limit)); 163 164 LEAVE(); 165} 166 167/** Print the WMM AC for debug purpose */ 168#define PRINTM_AC(pac_param) wlan_wmm_ac_debug_print(pac_param) 169#else 170/** Print the WMM AC for debug purpose */ 171#define PRINTM_AC(pac_param) 172#endif 173 174/** 175 * @brief Allocate route address 176 * 177 * @param pmadapter Pointer to the mlan_adapter structure 178 * @param ra Pointer to the route address 179 * 180 * @return ra_list 181 */ 182static raListTbl * 183wlan_wmm_allocate_ralist_node(pmlan_adapter pmadapter, t_u8 * ra) 184{ 185 raListTbl *ra_list = MNULL; 186 187 ENTER(); 188 189 if (pmadapter->callbacks. 190 moal_malloc(pmadapter->pmoal_handle, sizeof(raListTbl), MLAN_MEM_DEF, 191 (t_u8 **) & ra_list)) { 192 PRINTM(MERROR, "Fail to allocate ra_list\n"); 193 goto done; 194 } 195 util_init_list((pmlan_linked_list) ra_list); 196 util_init_list_head((t_void *) pmadapter->pmoal_handle, 197 &ra_list->buf_head, MFALSE, 198 pmadapter->callbacks.moal_init_lock); 199 200 memcpy(pmadapter, ra_list->ra, ra, MLAN_MAC_ADDR_LENGTH); 201 202 ra_list->total_pkts = 0; 203 ra_list->tx_pause = 0; 204 PRINTM(MINFO, "RAList: Allocating buffers for TID %p\n", ra_list); 205 done: 206 LEAVE(); 207 return ra_list; 208} 209 210/** 211 * @brief Map ACs to TID 212 * 213 * @param priv Pointer to the mlan_private driver data struct 214 * @param queue_priority Queue_priority structure 215 * 216 * @return N/A 217 */ 218static void 219wlan_wmm_queue_priorities_tid(pmlan_private priv, t_u8 queue_priority[]) 220{ 221 int i; 222 223 ENTER(); 224 225 for (i = 0; i < 4; ++i) { 226 tos_to_tid[7 - (i * 2)] = ac_to_tid[queue_priority[i]][1]; 227 tos_to_tid[6 - (i * 2)] = ac_to_tid[queue_priority[i]][0]; 228 } 229 230 for (i = 0; i < MAX_NUM_TID; i++) { 231 tos_to_tid_inv[tos_to_tid[i]] = (t_u8) i; 232 } 233 234 /* in case priorities have changed, force highest priority so next packet 235 will check from top to re-establish the highest */ 236 util_scalar_write(priv->adapter->pmoal_handle, 237 &priv->wmm.highest_queued_prio, 238 HIGH_PRIO_TID, 239 priv->adapter->callbacks.moal_spin_lock, 240 priv->adapter->callbacks.moal_spin_unlock); 241 242 LEAVE(); 243} 244 245/** 246 * @brief Evaluate whether or not an AC is to be downgraded 247 * 248 * @param priv Pointer to the mlan_private driver data struct 249 * @param eval_ac AC to evaluate for downgrading 250 * 251 * @return WMM AC The eval_ac traffic is to be sent on. 252 */ 253static mlan_wmm_ac_e 254wlan_wmm_eval_downgrade_ac(pmlan_private priv, mlan_wmm_ac_e eval_ac) 255{ 256 int down_ac; 257 mlan_wmm_ac_e ret_ac; 258 WmmAcStatus_t *pac_status; 259 260 ENTER(); 261 262 pac_status = &priv->wmm.ac_status[eval_ac]; 263 264 if (pac_status->disabled == MFALSE) { 265 LEAVE(); 266 /* Okay to use this AC, its enabled */ 267 return eval_ac; 268 } 269 270 /* Setup a default return value of the lowest priority */ 271 ret_ac = WMM_AC_BK; 272 273 /* 274 * Find the highest AC that is enabled and does not require admission 275 * control. The spec disallows downgrading to an AC, which is enabled 276 * due to a completed admission control. Unadmitted traffic is not 277 * to be sent on an AC with admitted traffic. 278 */ 279 for (down_ac = WMM_AC_BK; down_ac < eval_ac; down_ac++) { 280 pac_status = &priv->wmm.ac_status[down_ac]; 281 282 if ((pac_status->disabled == MFALSE) 283 && (pac_status->flow_required == MFALSE)) 284 /* AC is enabled and does not require admission control */ 285 ret_ac = (mlan_wmm_ac_e) down_ac; 286 } 287 288 LEAVE(); 289 return ret_ac; 290} 291 292/** 293 * @brief Convert the IP TOS field to an WMM AC Queue assignment 294 * 295 * @param pmadapter A pointer to mlan_adapter structure 296 * @param tos IP TOS field 297 * 298 * @return WMM AC Queue mapping of the IP TOS field 299 */ 300static mlan_wmm_ac_e INLINE 301wlan_wmm_convert_tos_to_ac(pmlan_adapter pmadapter, t_u32 tos) 302{ 303 ENTER(); 304 305 if (tos >= NELEMENTS(tos_to_ac)) { 306 LEAVE(); 307 return WMM_AC_BE; 308 } 309 310 LEAVE(); 311 return tos_to_ac[tos]; 312} 313 314/** 315 * @brief Evaluate a given TID and downgrade it to a lower TID if the 316 * WMM Parameter IE received from the AP indicates that the AP 317 * is disabled (due to call admission control (ACM bit). Mapping 318 * of TID to AC is taken care internally 319 * 320 * @param priv Pointer to the mlan_private data struct 321 * @param tid tid to evaluate for downgrading 322 * 323 * @return Same tid as input if downgrading not required or 324 * the tid the traffic for the given tid should be downgraded to 325 */ 326static t_u8 INLINE 327wlan_wmm_downgrade_tid(pmlan_private priv, t_u32 tid) 328{ 329 mlan_wmm_ac_e ac_down; 330 pmlan_adapter pmadapter = priv->adapter; 331 332 ENTER(); 333 334 ac_down = 335 priv->wmm.ac_down_graded_vals[wlan_wmm_convert_tos_to_ac(pmadapter, 336 tid)]; 337 LEAVE(); 338 /* 339 * Send the index to tid array, picking from the array will be 340 * taken care by dequeuing function 341 */ 342 if (tid == 1 || tid == 2) 343 return ac_to_tid[ac_down][(tid + 1) % 2]; 344 else if (tid >= MAX_NUM_TID) 345 return ac_to_tid[ac_down][0]; 346 else 347 return ac_to_tid[ac_down][tid % 2]; 348} 349 350/** 351 * @brief Delete packets in RA node 352 * 353 * @param priv Pointer to the mlan_private driver data struct 354 * @param ra_list Pointer to raListTbl 355 * 356 * @return N/A 357 */ 358static INLINE void 359wlan_wmm_del_pkts_in_ralist_node(pmlan_private priv, raListTbl * ra_list) 360{ 361 pmlan_buffer pmbuf; 362 pmlan_adapter pmadapter = priv->adapter; 363 364 ENTER(); 365 while ((pmbuf = 366 (pmlan_buffer) util_peek_list(pmadapter->pmoal_handle, 367 &ra_list->buf_head, MNULL, MNULL))) { 368 util_unlink_list(pmadapter->pmoal_handle, &ra_list->buf_head, 369 (pmlan_linked_list) pmbuf, MNULL, MNULL); 370 wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE); 371 } 372 util_free_list_head((t_void *) pmadapter->pmoal_handle, &ra_list->buf_head, 373 pmadapter->callbacks.moal_free_lock); 374 375 LEAVE(); 376} 377 378/** 379 * @brief Delete packets in RA list 380 * 381 * @param priv Pointer to the mlan_private driver data struct 382 * @param ra_list_head ra list header 383 * 384 * @return N/A 385 */ 386static INLINE void 387wlan_wmm_del_pkts_in_ralist(pmlan_private priv, mlan_list_head * ra_list_head) 388{ 389 raListTbl *ra_list; 390 391 ENTER(); 392 393 ra_list = 394 (raListTbl *) util_peek_list(priv->adapter->pmoal_handle, ra_list_head, 395 MNULL, MNULL); 396 397 while (ra_list && ra_list != (raListTbl *) ra_list_head) { 398 wlan_wmm_del_pkts_in_ralist_node(priv, ra_list); 399 400 ra_list = ra_list->pnext; 401 } 402 403 LEAVE(); 404} 405 406/** 407 * @brief Clean up the wmm queue 408 * 409 * @param priv Pointer to the mlan_private driver data struct 410 * 411 * @return N/A 412 */ 413static void 414wlan_wmm_cleanup_queues(pmlan_private priv) 415{ 416 int i; 417 418 ENTER(); 419 420 for (i = 0; i < MAX_NUM_TID; i++) { 421 wlan_wmm_del_pkts_in_ralist(priv, &priv->wmm.tid_tbl_ptr[i].ra_list); 422 priv->wmm.pkts_queued[i] = 0; 423 } 424 util_scalar_write(priv->adapter->pmoal_handle, &priv->wmm.tx_pkts_queued, 0, 425 MNULL, MNULL); 426 util_scalar_write(priv->adapter->pmoal_handle, 427 &priv->wmm.highest_queued_prio, HIGH_PRIO_TID, MNULL, 428 MNULL); 429 430 LEAVE(); 431} 432 433/** 434 * @brief Delete all route address from RA list 435 * 436 * @param priv Pointer to the mlan_private driver data struct 437 * 438 * @return N/A 439 */ 440static void 441wlan_wmm_delete_all_ralist(pmlan_private priv) 442{ 443 raListTbl *ra_list; 444 int i; 445 pmlan_adapter pmadapter = priv->adapter; 446 447 ENTER(); 448 449 for (i = 0; i < MAX_NUM_TID; ++i) { 450 PRINTM(MINFO, "RAList: Freeing buffers for TID %d\n", i); 451 while ((ra_list = (raListTbl *) util_peek_list(pmadapter->pmoal_handle, 452 &priv->wmm. 453 tid_tbl_ptr[i].ra_list, 454 MNULL, MNULL))) { 455 util_unlink_list(pmadapter->pmoal_handle, 456 &priv->wmm.tid_tbl_ptr[i].ra_list, 457 (pmlan_linked_list) ra_list, MNULL, MNULL); 458 459 pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle, 460 (t_u8 *) ra_list); 461 } 462 463 util_init_list((pmlan_linked_list) 464 & priv->wmm.tid_tbl_ptr[i].ra_list); 465 priv->wmm.tid_tbl_ptr[i].ra_list_curr = MNULL; 466 } 467 468 LEAVE(); 469} 470 471/** 472 * @brief Get queue RA pointer 473 * 474 * @param priv Pointer to the mlan_private driver data struct 475 * @param tid TID 476 * @param ra_addr Pointer to the route address 477 * 478 * @return ra_list 479 */ 480static raListTbl * 481wlan_wmm_get_queue_raptr(pmlan_private priv, t_u8 tid, t_u8 * ra_addr) 482{ 483 raListTbl *ra_list; 484#if defined(UAP_SUPPORT) 485 t_u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 486#endif 487 488 ENTER(); 489 ra_list = wlan_wmm_get_ralist_node(priv, tid, ra_addr); 490 if (ra_list) { 491 LEAVE(); 492 return ra_list; 493 } 494#if defined(UAP_SUPPORT) 495 if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) && 496 (0 != memcmp(priv->adapter, ra_addr, bcast_addr, sizeof(bcast_addr)))) { 497 if (MNULL == wlan_get_station_entry(priv, ra_addr)) { 498 PRINTM(MDATA, "Drop packets to unknown station\n"); 499 LEAVE(); 500 return MNULL; 501 } 502 } 503#endif 504 wlan_ralist_add(priv, ra_addr); 505 506 ra_list = wlan_wmm_get_ralist_node(priv, tid, ra_addr); 507 LEAVE(); 508 return ra_list; 509} 510 511#ifdef STA_SUPPORT 512/** 513 * @brief Sends wmmac host event 514 * 515 * @param priv Pointer to the mlan_private driver data struct 516 * @param typeStr Type of host event 517 * @param srcAddr Pointer to the source Address 518 * @param tid TID 519 * @param up User priority 520 * @param status Status code or Reason code 521 * 522 * @return N/A 523 */ 524static void 525wlan_send_wmmac_host_event(pmlan_private priv, 526 char *typeStr, 527 t_u8 * srcAddr, t_u8 tid, t_u8 up, t_u8 status) 528{ 529 t_u8 event_buf[100]; 530 mlan_event *pevent; 531 t_u8 *pOutBuf; 532 533 ENTER(); 534 535 /* Format one of the following two output strings: ** - 536 TSPEC:ADDTS_RSP:[<status code>]:TID=X:UP=Y ** - TSPEC:DELTS_RX:[<reason 537 code>]:TID=X:UP=Y */ 538 pevent = (mlan_event *) event_buf; 539 pOutBuf = pevent->event_buf; 540 541 memcpy(priv->adapter, pOutBuf, (t_u8 *) "TSPEC:", 6); 542 pOutBuf += 6; 543 544 memcpy(priv->adapter, pOutBuf, (t_u8 *) typeStr, wlan_strlen(typeStr)); 545 pOutBuf += wlan_strlen(typeStr); 546 547 *pOutBuf++ = ':'; 548 *pOutBuf++ = '['; 549 550 if (status >= 100) { 551 *pOutBuf++ = (status / 100) + '0'; 552 status = (status % 100); 553 } 554 555 if (status >= 10) { 556 *pOutBuf++ = (status / 10) + '0'; 557 status = (status % 10); 558 } 559 560 *pOutBuf++ = status + '0'; 561 562 memcpy(priv->adapter, pOutBuf, (t_u8 *) "]:TID", 5); 563 pOutBuf += 5; 564 *pOutBuf++ = tid + '0'; 565 566 memcpy(priv->adapter, pOutBuf, (t_u8 *) ":UP", 3); 567 pOutBuf += 3; 568 *pOutBuf++ = up + '0'; 569 570 *pOutBuf = '\0'; 571 572 pevent->bss_index = priv->bss_index; 573 pevent->event_id = MLAN_EVENT_ID_DRV_REPORT_STRING; 574 pevent->event_len = wlan_strlen((const t_s8 *) (pevent->event_buf)); 575 576 wlan_recv_event(priv, MLAN_EVENT_ID_DRV_REPORT_STRING, pevent); 577 LEAVE(); 578} 579#endif /* STA_SUPPORT */ 580 581/** 582 * @brief This function gets the highest priority list pointer 583 * 584 * @param pmadapter A pointer to mlan_adapter 585 * @param priv A pointer to mlan_private 586 * @param tid A pointer to return tid 587 * 588 * @return raListTbl 589 */ 590static raListTbl * 591wlan_wmm_get_highest_priolist_ptr(pmlan_adapter pmadapter, 592 pmlan_private * priv, int *tid) 593{ 594 pmlan_private priv_tmp; 595 raListTbl *ptr, *head; 596 mlan_bssprio_node *bssprio_node, *bssprio_head; 597 tid_tbl_t *tid_ptr; 598 int i, j; 599 int next_prio = 0; 600 int next_tid = 0; 601 ENTER(); 602 603 PRINTM(MDAT_D, "POP\n"); 604 for (j = pmadapter->priv_num - 1; j >= 0; --j) { 605 if (!(util_peek_list(pmadapter->pmoal_handle, 606 &pmadapter->bssprio_tbl[j].bssprio_head, 607 pmadapter->callbacks.moal_spin_lock, 608 pmadapter->callbacks.moal_spin_unlock))) 609 continue; 610 611 if (pmadapter->bssprio_tbl[j].bssprio_cur == (mlan_bssprio_node *) 612 & pmadapter->bssprio_tbl[j].bssprio_head) { 613 pmadapter->bssprio_tbl[j].bssprio_cur = 614 pmadapter->bssprio_tbl[j].bssprio_cur->pnext; 615 } 616 617 bssprio_head = bssprio_node = pmadapter->bssprio_tbl[j].bssprio_cur; 618 619 do { 620 priv_tmp = bssprio_node->priv; 621 622 if ((priv_tmp->port_ctrl_mode == MTRUE) 623 && (priv_tmp->port_open == MFALSE)) { 624 PRINTM(MINFO, "get_highest_prio_ptr(): " 625 "PORT_CLOSED Ignore pkts from BSS%d\n", 626 priv_tmp->bss_index); 627 /* Ignore data pkts from a BSS if port is closed */ 628 goto next_intf; 629 } 630 631 pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, 632 priv_tmp->wmm.ra_list_spinlock); 633 634 for (i = util_scalar_read(pmadapter->pmoal_handle, 635 &priv_tmp->wmm.highest_queued_prio, 636 MNULL, MNULL); i >= LOW_PRIO_TID; --i) { 637 638 tid_ptr = &(priv_tmp)->wmm.tid_tbl_ptr[tos_to_tid[i]]; 639 if (!util_peek_list 640 (pmadapter->pmoal_handle, &tid_ptr->ra_list, MNULL, MNULL)) 641 continue; 642 643 /* 644 * Always choose the next ra we transmitted 645 * last time, this way we pick the ra's in 646 * round robin fashion. 647 */ 648 head = ptr = tid_ptr->ra_list_curr->pnext; 649 if (ptr == (raListTbl *) & tid_ptr->ra_list) 650 head = ptr = ptr->pnext; 651 652 do { 653 if (!ptr->tx_pause && 654 util_peek_list(pmadapter->pmoal_handle, &ptr->buf_head, 655 MNULL, MNULL)) { 656 657 /* Because WMM only support BK/BE/VI/VO, we have 8 tid 658 We should balance the traffic of the same AC */ 659 if (i % 2) 660 next_prio = i - 1; 661 else 662 next_prio = i + 1; 663 next_tid = tos_to_tid[next_prio]; 664 if (priv_tmp->wmm.pkts_queued[next_tid]) 665 util_scalar_write(pmadapter->pmoal_handle, 666 &priv_tmp->wmm. 667 highest_queued_prio, next_prio, 668 MNULL, MNULL); 669 else 670 /* if highest_queued_prio > i, set it to i */ 671 util_scalar_conditional_write(pmadapter-> 672 pmoal_handle, 673 &priv_tmp->wmm. 674 highest_queued_prio, 675 MLAN_SCALAR_COND_GREATER_THAN, 676 i, i, MNULL, MNULL); 677 *priv = priv_tmp; 678 *tid = tos_to_tid[i]; 679 /* hold priv->ra_list_spinlock to maintain ptr */ 680 PRINTM(MDAT_D, "get highest prio ptr %p, tid %d\n", 681 ptr, *tid); 682 LEAVE(); 683 return ptr; 684 } 685 686 if ((ptr = ptr->pnext) == (raListTbl *) & tid_ptr->ra_list) 687 ptr = ptr->pnext; 688 } while (ptr != head); 689 } 690 691 /* No packet at any TID for this priv. Mark as such to skip 692 checking TIDs for this priv (until pkt is added). */ 693 util_scalar_write(pmadapter->pmoal_handle, 694 &priv_tmp->wmm.highest_queued_prio, 695 NO_PKT_PRIO_TID, MNULL, MNULL); 696 697 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, 698 priv_tmp->wmm. 699 ra_list_spinlock); 700 701 next_intf: 702 if ((bssprio_node = bssprio_node->pnext) == (mlan_bssprio_node *) 703 & pmadapter->bssprio_tbl[j].bssprio_head) 704 bssprio_node = bssprio_node->pnext; 705 } while (bssprio_node != bssprio_head); 706 } 707 708 LEAVE(); 709 return MNULL; 710} 711 712/** 713 * @brief This function gets the number of packets in the Tx queue 714 * 715 * @param priv A pointer to mlan_private 716 * @param ptr A pointer to RA list table 717 * @param maxBufSize Maximum buffer size 718 * 719 * @return Packet count 720 */ 721static int 722wlan_num_pkts_in_txq(mlan_private * priv, raListTbl * ptr, int maxBufSize) 723{ 724 int count = 0, total_size = 0; 725 pmlan_buffer pmbuf; 726 727 ENTER(); 728 729 for (pmbuf = (pmlan_buffer) ptr->buf_head.pnext; 730 pmbuf != (pmlan_buffer) (&ptr->buf_head); pmbuf = pmbuf->pnext) { 731 732 total_size += pmbuf->data_len; 733 if (total_size < maxBufSize) 734 ++count; 735 else 736 break; 737 } 738 739 LEAVE(); 740 return count; 741} 742 743/** 744 * @brief This function sends a single packet 745 * 746 * @param priv A pointer to mlan_private 747 * @param ptr A pointer to RA list table 748 * @param ptrindex ptr's TID index 749 * 750 * @return N/A 751 */ 752static void INLINE 753wlan_send_single_packet(pmlan_private priv, raListTbl * ptr, int ptrindex) 754{ 755 pmlan_buffer pmbuf; 756 pmlan_buffer pmbuf_next; 757 mlan_tx_param tx_param; 758 pmlan_adapter pmadapter = priv->adapter; 759 mlan_status status = MLAN_STATUS_SUCCESS; 760 761 ENTER(); 762 763 if ((pmbuf = (pmlan_buffer) util_dequeue_list(pmadapter->pmoal_handle, 764 &ptr->buf_head, 765 MNULL, MNULL))) { 766 PRINTM(MINFO, "Dequeuing the packet %p %p\n", ptr, pmbuf); 767 priv->wmm.pkts_queued[ptrindex]--; 768 util_scalar_decrement(pmadapter->pmoal_handle, 769 &priv->wmm.tx_pkts_queued, MNULL, MNULL); 770 ptr->total_pkts--; 771 pmbuf_next = (pmlan_buffer) util_peek_list(pmadapter->pmoal_handle, 772 &ptr->buf_head, 773 MNULL, MNULL); 774 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, 775 priv->wmm.ra_list_spinlock); 776 777 tx_param.next_pkt_len = ((pmbuf_next) 778 ? pmbuf_next->data_len + sizeof(TxPD) : 0); 779 status = wlan_process_tx(priv, pmbuf, &tx_param); 780 781 if (status == MLAN_STATUS_RESOURCE) { 782 /** Queue the packet back at the head */ 783 PRINTM(MDAT_D, "Queuing pkt back to raList %p %p\n", ptr, pmbuf); 784 pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, 785 priv->wmm.ra_list_spinlock); 786 787 if (!wlan_is_ralist_valid(priv, ptr, ptrindex)) { 788 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, 789 priv->wmm. 790 ra_list_spinlock); 791 wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE); 792 LEAVE(); 793 return; 794 } 795 priv->wmm.pkts_queued[ptrindex]++; 796 util_scalar_increment(pmadapter->pmoal_handle, 797 &priv->wmm.tx_pkts_queued, MNULL, MNULL); 798 util_enqueue_list_head(pmadapter->pmoal_handle, &ptr->buf_head, 799 (pmlan_linked_list) pmbuf, MNULL, MNULL); 800 801 ptr->total_pkts++; 802 pmbuf->flags |= MLAN_BUF_FLAG_REQUEUED_PKT; 803 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, 804 priv->wmm.ra_list_spinlock); 805 } else { 806 pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, 807 priv->wmm.ra_list_spinlock); 808 if (wlan_is_ralist_valid(priv, ptr, ptrindex)) { 809 priv->wmm.packets_out[ptrindex]++; 810 priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr = ptr; 811 } 812 pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur = 813 pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur->pnext; 814 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, 815 priv->wmm.ra_list_spinlock); 816 } 817 } else { 818 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, 819 priv->wmm.ra_list_spinlock); 820 PRINTM(MINFO, "Nothing to send\n"); 821 } 822 823 LEAVE(); 824} 825 826/** 827 * @brief This function checks if this mlan_buffer is already processed. 828 * 829 * @param priv A pointer to mlan_private 830 * @param ptr A pointer to RA list table 831 * 832 * @return MTRUE or MFALSE 833 */ 834static int INLINE 835wlan_is_ptr_processed(mlan_private * priv, raListTbl * ptr) 836{ 837 pmlan_buffer pmbuf; 838 839 if ((pmbuf = (pmlan_buffer) util_peek_list(priv->adapter->pmoal_handle, 840 &ptr->buf_head, MNULL, MNULL)) 841 && (pmbuf->flags & MLAN_BUF_FLAG_REQUEUED_PKT)) 842 return MTRUE; 843 844 return MFALSE; 845} 846 847/** 848 * @brief This function sends a single packet that has been processed 849 * 850 * @param priv A pointer to mlan_private 851 * @param ptr A pointer to RA list table 852 * @param ptrindex ptr's TID index 853 * 854 * @return N/A 855 */ 856static void INLINE 857wlan_send_processed_packet(pmlan_private priv, raListTbl * ptr, int ptrindex) 858{ 859 pmlan_buffer pmbuf_next; 860 mlan_tx_param tx_param; 861 pmlan_buffer pmbuf; 862 pmlan_adapter pmadapter = priv->adapter; 863 mlan_status ret = MLAN_STATUS_FAILURE; 864 865 if ((pmbuf = (pmlan_buffer) util_dequeue_list(pmadapter->pmoal_handle, 866 &ptr->buf_head, 867 MNULL, MNULL))) { 868 pmbuf_next = 869 (pmlan_buffer) util_peek_list(pmadapter->pmoal_handle, 870 &ptr->buf_head, MNULL, MNULL); 871 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, 872 priv->wmm.ra_list_spinlock); 873 tx_param.next_pkt_len = 874 ((pmbuf_next) ? pmbuf_next->data_len + sizeof(TxPD) : 0); 875 ret = 876 wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA, pmbuf, &tx_param); 877 switch (ret) { 878 case MLAN_STATUS_RESOURCE: 879 PRINTM(MINFO, "MLAN_STATUS_RESOURCE is returned\n"); 880 pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, 881 priv->wmm.ra_list_spinlock); 882 883 if (!wlan_is_ralist_valid(priv, ptr, ptrindex)) { 884 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, 885 priv->wmm. 886 ra_list_spinlock); 887 wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE); 888 LEAVE(); 889 return; 890 } 891 util_enqueue_list_head(pmadapter->pmoal_handle, 892 &ptr->buf_head, 893 (pmlan_linked_list) pmbuf, MNULL, MNULL); 894 895 pmbuf->flags |= MLAN_BUF_FLAG_REQUEUED_PKT; 896 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, 897 priv->wmm.ra_list_spinlock); 898 break; 899 case MLAN_STATUS_FAILURE: 900 pmadapter->data_sent = MFALSE; 901 PRINTM(MERROR, "Error: Failed to write data\n"); 902 pmadapter->dbg.num_tx_host_to_card_failure++; 903 pmbuf->status_code = MLAN_ERROR_DATA_TX_FAIL; 904 wlan_write_data_complete(pmadapter, pmbuf, ret); 905 break; 906 case MLAN_STATUS_PENDING: 907 pmadapter->data_sent = MFALSE; 908 default: 909 break; 910 } 911 if (ret != MLAN_STATUS_RESOURCE) { 912 pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, 913 priv->wmm.ra_list_spinlock); 914 if (wlan_is_ralist_valid(priv, ptr, ptrindex)) { 915 priv->wmm.packets_out[ptrindex]++; 916 priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr = ptr; 917 ptr->total_pkts--; 918 } 919 pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur = 920 pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur->pnext; 921 priv->wmm.pkts_queued[ptrindex]--; 922 util_scalar_decrement(pmadapter->pmoal_handle, 923 &priv->wmm.tx_pkts_queued, MNULL, MNULL); 924 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, 925 priv->wmm.ra_list_spinlock); 926 } 927 } else { 928 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, 929 priv->wmm.ra_list_spinlock); 930 } 931} 932 933/** 934 * @brief This function dequeues a packet 935 * 936 * @param pmadapter A pointer to mlan_adapter 937 * 938 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE 939 */ 940static int 941wlan_dequeue_tx_packet(pmlan_adapter pmadapter) 942{ 943 raListTbl *ptr; 944 pmlan_private priv = MNULL; 945 int ptrindex = 0; 946 t_u8 ra[MLAN_MAC_ADDR_LENGTH]; 947 int tid_del = 0; 948 int tid = 0; 949 950 ENTER(); 951 952 if (!(ptr = wlan_wmm_get_highest_priolist_ptr(pmadapter, &priv, &ptrindex))) { 953 LEAVE(); 954 return MLAN_STATUS_FAILURE; 955 } 956 957 /* Note:- Spinlock is locked in wlan_wmm_get_highest_priolist_ptr when it 958 returns a pointer (for the priv it returns), and is unlocked in 959 wlan_send_processed_packet, wlan_send_single_packet or 960 wlan_11n_aggregate_pkt. The spinlock would be required for some parts 961 of both of function. But, the the bulk of these function will execute 962 w/o spinlock. Unlocking the spinlock inside these function will help 963 us avoid taking the spinlock again, check to see if the ptr is still 964 valid and then proceed. This is done purely to increase execution time. 965 */ 966 967 /* Note:- Also, anybody adding code which does not get into 968 wlan_send_processed_packet, wlan_send_single_packet, or 969 wlan_11n_aggregate_pkt should make sure ra_list_spinlock is freed. 970 Otherwise there would be a lock up. */ 971 972 tid = wlan_get_tid(priv->adapter, ptr); 973 if (tid >= MAX_NUM_TID) 974 tid = wlan_wmm_downgrade_tid(priv, tid); 975 976 if (wlan_is_ptr_processed(priv, ptr)) { 977 wlan_send_processed_packet(priv, ptr, ptrindex); 978 LEAVE(); 979 return MLAN_STATUS_SUCCESS; 980 } 981 982 if (!ptr->is_11n_enabled || wlan_is_bastream_setup(priv, ptr, tid) 983#ifdef STA_SUPPORT 984 || ((priv->sec_info.ewpa_enabled == MFALSE) && 985 ((priv->sec_info.wpa_enabled 986 || priv->sec_info.wpa2_enabled) && 987 priv->wpa_is_gtk_set == MFALSE)) 988 || priv->wps.session_enable 989#endif /* STA_SUPPORT */ 990 ) { 991 if (ptr->is_11n_enabled && wlan_is_bastream_setup(priv, ptr, tid) 992 && wlan_is_amsdu_in_ampdu_allowed(priv, ptr, tid) 993 && wlan_is_amsdu_allowed(priv, ptr, tid) 994 && (wlan_num_pkts_in_txq(priv, ptr, pmadapter->tx_buf_size) >= 995 MIN_NUM_AMSDU)) { 996 wlan_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN, ptrindex); 997 } else 998 wlan_send_single_packet(priv, ptr, ptrindex); 999 } else { 1000 if (wlan_is_ampdu_allowed(priv, ptr, tid) && 1001 (ptr->packet_count > ptr->ba_packet_threshold)) { 1002 if (wlan_is_bastream_avail(priv)) { 1003 PRINTM(MINFO, "BA setup threshold %d reached. tid=%d\n", 1004 ptr->packet_count, tid); 1005 wlan_11n_create_txbastream_tbl(priv, 1006 ptr->ra, tid, 1007 BA_STREAM_SETUP_INPROGRESS); 1008 wlan_send_addba(priv, tid, ptr->ra); 1009 } else if (wlan_find_stream_to_delete(priv, ptr, tid, &tid_del, ra)) { 1010 PRINTM(MDAT_D, "tid_del=%d tid=%d\n", tid_del, tid); 1011 wlan_11n_create_txbastream_tbl(priv, 1012 ptr->ra, tid, 1013 BA_STREAM_SETUP_INPROGRESS); 1014 wlan_send_delba(priv, tid_del, ra, 1); 1015 } 1016 } 1017 if (wlan_is_amsdu_allowed(priv, ptr, tid) && 1018 (wlan_num_pkts_in_txq(priv, ptr, 1019 pmadapter->tx_buf_size) >= MIN_NUM_AMSDU)) { 1020 wlan_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN, ptrindex); 1021 } else { 1022 wlan_send_single_packet(priv, ptr, ptrindex); 1023 } 1024 } 1025 1026 LEAVE(); 1027 return MLAN_STATUS_SUCCESS; 1028} 1029 1030/** 1031 * @brief update tx_pause flag in ra_list 1032 * 1033 * @param priv A pointer to mlan_private 1034 * @param mac peer mac address 1035 * @param tx_pause tx_pause flag (0/1) 1036 * 1037 * @return N/A 1038 */ 1039t_void 1040wlan_updata_ralist_tx_pause(pmlan_private priv, t_u8 * mac, t_u8 tx_pause) 1041{ 1042 raListTbl *ra_list; 1043 int i; 1044 pmlan_adapter pmadapter = priv->adapter; 1045 t_u32 pkt_cnt = 0; 1046 t_u32 tx_pkts_queued = 0; 1047 ENTER(); 1048 1049 pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, 1050 priv->wmm.ra_list_spinlock); 1051 for (i = 0; i < MAX_NUM_TID; ++i) { 1052 ra_list = wlan_wmm_get_ralist_node(priv, i, mac); 1053 if (ra_list) { 1054 pkt_cnt += ra_list->total_pkts; 1055 ra_list->tx_pause = tx_pause; 1056 } 1057 } 1058 if (pkt_cnt) { 1059 tx_pkts_queued = util_scalar_read(pmadapter->pmoal_handle, 1060 &priv->wmm.tx_pkts_queued, MNULL, 1061 MNULL); 1062 if (tx_pause) 1063 tx_pkts_queued -= pkt_cnt; 1064 else 1065 tx_pkts_queued += pkt_cnt; 1066 util_scalar_write(priv->adapter->pmoal_handle, 1067 &priv->wmm.tx_pkts_queued, tx_pkts_queued, MNULL, 1068 MNULL); 1069 util_scalar_write(priv->adapter->pmoal_handle, 1070 &priv->wmm.highest_queued_prio, HIGH_PRIO_TID, MNULL, 1071 MNULL); 1072 } 1073 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, 1074 priv->wmm.ra_list_spinlock); 1075 LEAVE(); 1076} 1077 1078#ifdef STA_SUPPORT 1079#endif /* STA_SUPPORT */ 1080/******************************************************** 1081 Global Functions 1082********************************************************/ 1083 1084/** 1085 * @brief Get the threshold value for BA setup using system time. 1086 * 1087 * @param pmadapter Pointer to the mlan_adapter structure 1088 * 1089 * @return threshold value. 1090 */ 1091t_u8 1092wlan_get_random_ba_threshold(pmlan_adapter pmadapter) 1093{ 1094 t_u32 sec, usec; 1095 t_u8 ba_threshold = 0; 1096 1097 ENTER(); 1098 1099 /* setup ba_packet_threshold here random number between 1100 [BA_SETUP_PACKET_OFFSET, 1101 BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1] */ 1102 1103#define BA_SETUP_MAX_PACKET_THRESHOLD 16 1104#define BA_SETUP_PACKET_OFFSET 16 1105 1106 pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec, 1107 &usec); 1108 sec = (sec & 0xFFFF) + (sec >> 16); 1109 usec = (usec & 0xFFFF) + (usec >> 16); 1110 1111 ba_threshold = 1112 (((sec << 16) + usec) % BA_SETUP_MAX_PACKET_THRESHOLD) + 1113 BA_SETUP_PACKET_OFFSET; 1114 PRINTM(MINFO, "setup BA after %d packets\n", ba_threshold); 1115 1116 LEAVE(); 1117 return ba_threshold; 1118} 1119 1120/** 1121 * @brief This function cleans Tx/Rx queues 1122 * 1123 * @param priv A pointer to mlan_private 1124 * 1125 * @return N/A 1126 */ 1127t_void 1128wlan_clean_txrx(pmlan_private priv) 1129{ 1130 mlan_adapter *pmadapter = priv->adapter; 1131 t_u8 i = 0; 1132 1133 ENTER(); 1134 1135 if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) { 1136 wlan_cleanup_bypass_txq(pmadapter); 1137 } 1138 1139 wlan_11n_cleanup_reorder_tbl(priv); 1140 1141 pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, 1142 priv->wmm.ra_list_spinlock); 1143 1144 wlan_wmm_cleanup_queues(priv); 1145 wlan_11n_deleteall_txbastream_tbl(priv); 1146#ifdef SDIO_MULTI_PORT_TX_AGGR 1147 MP_TX_AGGR_BUF_RESET(priv->adapter); 1148#endif 1149#ifdef SDIO_MULTI_PORT_RX_AGGR 1150 MP_RX_AGGR_BUF_RESET(priv->adapter); 1151#endif 1152 wlan_wmm_delete_all_ralist(priv); 1153 memcpy(pmadapter, tos_to_tid, ac_to_tid, sizeof(tos_to_tid)); 1154 for (i = 0; i < MAX_NUM_TID; i++) { 1155 tos_to_tid_inv[tos_to_tid[i]] = (t_u8) i; 1156 } 1157#if defined(UAP_SUPPORT) 1158 priv->num_drop_pkts = 0; 1159#endif 1160 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, 1161 priv->wmm.ra_list_spinlock); 1162 1163 LEAVE(); 1164} 1165 1166/** 1167 * @brief Set the WMM queue priorities to their default values 1168 * 1169 * @param priv Pointer to the mlan_private driver data struct 1170 * 1171 * @return N/A 1172 */ 1173void 1174wlan_wmm_default_queue_priorities(pmlan_private priv) 1175{ 1176 ENTER(); 1177 1178 /* Default queue priorities: VO->VI->BE->BK */ 1179 priv->wmm.queue_priority[0] = WMM_AC_VO; 1180 priv->wmm.queue_priority[1] = WMM_AC_VI; 1181 priv->wmm.queue_priority[2] = WMM_AC_BE; 1182 priv->wmm.queue_priority[3] = WMM_AC_BK; 1183 1184 LEAVE(); 1185} 1186 1187/** 1188 * @brief Initialize WMM priority queues 1189 * 1190 * @param priv Pointer to the mlan_private driver data struct 1191 * @param pwmm_ie Pointer to the IEEEtypes_WmmParameter_t data struct 1192 * 1193 * @return N/A 1194 */ 1195void 1196wlan_wmm_setup_queue_priorities(pmlan_private priv, 1197 IEEEtypes_WmmParameter_t * pwmm_ie) 1198{ 1199 t_u16 cw_min, avg_back_off, tmp[4]; 1200 t_u32 i, j, num_ac; 1201 t_u8 ac_idx; 1202 1203 ENTER(); 1204 1205 if (!pwmm_ie || priv->wmm_enabled == MFALSE) { 1206 /* WMM is not enabled, just set the defaults and return */ 1207 wlan_wmm_default_queue_priorities(priv); 1208 LEAVE(); 1209 return; 1210 } 1211 1212 HEXDUMP("WMM: setup_queue_priorities: param IE", 1213 (t_u8 *) pwmm_ie, sizeof(IEEEtypes_WmmParameter_t)); 1214 1215 PRINTM(MINFO, "WMM Parameter IE: version=%d, " 1216 "qos_info Parameter Set Count=%d, Reserved=%#x\n", 1217 pwmm_ie->vend_hdr.version, pwmm_ie->qos_info.para_set_count, 1218 pwmm_ie->reserved); 1219 1220 for (num_ac = 0; num_ac < NELEMENTS(pwmm_ie->ac_params); num_ac++) { 1221 cw_min = (1 << pwmm_ie->ac_params[num_ac].ecw.ecw_min) - 1; 1222 avg_back_off 1223 = (cw_min >> 1) + pwmm_ie->ac_params[num_ac].aci_aifsn.aifsn; 1224 1225 ac_idx = wmm_aci_to_qidx_map[pwmm_ie->ac_params[num_ac].aci_aifsn.aci]; 1226 priv->wmm.queue_priority[ac_idx] = ac_idx; 1227 tmp[ac_idx] = avg_back_off; 1228 1229 PRINTM(MCMND, "WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n", 1230 (1 << pwmm_ie->ac_params[num_ac].ecw.ecw_max) - 1, 1231 cw_min, avg_back_off); 1232 PRINTM_AC(&pwmm_ie->ac_params[num_ac]); 1233 } 1234 1235 HEXDUMP("WMM: avg_back_off", (t_u8 *) tmp, sizeof(tmp)); 1236 HEXDUMP("WMM: queue_priority", priv->wmm.queue_priority, 1237 sizeof(priv->wmm.queue_priority)); 1238 1239 /* Bubble sort */ 1240 for (i = 0; i < num_ac; i++) { 1241 for (j = 1; j < num_ac - i; j++) { 1242 if (tmp[j - 1] > tmp[j]) { 1243 SWAP_U16(tmp[j - 1], tmp[j]); 1244 SWAP_U8(priv->wmm.queue_priority[j - 1], 1245 priv->wmm.queue_priority[j]); 1246 } else if (tmp[j - 1] == tmp[j]) { 1247 if (priv->wmm.queue_priority[j - 1] 1248 < priv->wmm.queue_priority[j]) { 1249 SWAP_U8(priv->wmm.queue_priority[j - 1], 1250 priv->wmm.queue_priority[j]); 1251 } 1252 } 1253 } 1254 } 1255 1256 wlan_wmm_queue_priorities_tid(priv, priv->wmm.queue_priority); 1257 1258 HEXDUMP("WMM: avg_back_off, sort", (t_u8 *) tmp, sizeof(tmp)); 1259 DBG_HEXDUMP(MCMD_D, "WMM: queue_priority, sort", priv->wmm.queue_priority, 1260 sizeof(priv->wmm.queue_priority)); 1261 LEAVE(); 1262} 1263 1264/** 1265 * @brief Downgrade WMM priority queue 1266 * 1267 * @param priv Pointer to the mlan_private driver data struct 1268 * 1269 * @return N/A 1270 */ 1271void 1272wlan_wmm_setup_ac_downgrade(pmlan_private priv) 1273{ 1274 int ac_val; 1275 1276 ENTER(); 1277 1278 PRINTM(MINFO, "WMM: AC Priorities: BK(0), BE(1), VI(2), VO(3)\n"); 1279 1280 if (priv->wmm_enabled == MFALSE) { 1281 /* WMM is not enabled, default priorities */ 1282 for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) { 1283 priv->wmm.ac_down_graded_vals[ac_val] = (mlan_wmm_ac_e) ac_val; 1284 } 1285 } else { 1286 for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) { 1287 priv->wmm.ac_down_graded_vals[ac_val] 1288 = wlan_wmm_eval_downgrade_ac(priv, (mlan_wmm_ac_e) ac_val); 1289 PRINTM(MINFO, "WMM: AC PRIO %d maps to %d\n", 1290 ac_val, priv->wmm.ac_down_graded_vals[ac_val]); 1291 } 1292 } 1293 1294 LEAVE(); 1295} 1296 1297/** 1298 * @brief Allocate and add a RA list for all TIDs with the given RA 1299 * 1300 * @param priv Pointer to the mlan_private driver data struct 1301 * @param ra Address of the receiver STA (AP in case of infra) 1302 * 1303 * @return N/A 1304 */ 1305void 1306wlan_ralist_add(mlan_private * priv, t_u8 * ra) 1307{ 1308 int i; 1309 raListTbl *ra_list; 1310 pmlan_adapter pmadapter = priv->adapter; 1311 1312 ENTER(); 1313 1314 for (i = 0; i < MAX_NUM_TID; ++i) { 1315 ra_list = wlan_wmm_allocate_ralist_node(pmadapter, ra); 1316 PRINTM(MINFO, "Creating RA List %p for tid %d\n", ra_list, i); 1317 if (!ra_list) 1318 break; 1319 ra_list->max_amsdu = 0; 1320 if (queuing_ra_based(priv)) { 1321 ra_list->is_11n_enabled = wlan_is_11n_enabled(priv, ra); 1322 if (ra_list->is_11n_enabled) 1323 ra_list->max_amsdu = get_station_max_amsdu_size(priv, ra); 1324 ra_list->tx_pause = wlan_is_tx_pause(priv, ra); 1325 } else { 1326 ra_list->is_11n_enabled = IS_11N_ENABLED(priv); 1327 if (ra_list->is_11n_enabled) 1328 ra_list->max_amsdu = priv->max_amsdu; 1329 } 1330 1331 PRINTM(MDATA, "ralist %p: is_11n_enabled=%d max_amsdu=%d\n", 1332 ra_list, ra_list->is_11n_enabled, ra_list->max_amsdu); 1333 1334 if (ra_list->is_11n_enabled) { 1335 ra_list->packet_count = 0; 1336 ra_list->ba_packet_threshold = 1337 wlan_get_random_ba_threshold(pmadapter); 1338 } 1339 1340 util_enqueue_list_tail(pmadapter->pmoal_handle, 1341 &priv->wmm.tid_tbl_ptr[i].ra_list, 1342 (pmlan_linked_list) ra_list, MNULL, MNULL); 1343 1344 if (!priv->wmm.tid_tbl_ptr[i].ra_list_curr) 1345 priv->wmm.tid_tbl_ptr[i].ra_list_curr = ra_list; 1346 } 1347 1348 LEAVE(); 1349} 1350 1351/** 1352 * @brief Initialize the WMM state information and the WMM data path queues. 1353 * 1354 * @param pmadapter Pointer to the mlan_adapter data structure 1355 * 1356 * @return N/A 1357 */ 1358t_void 1359wlan_wmm_init(pmlan_adapter pmadapter) 1360{ 1361 int i, j; 1362 pmlan_private priv; 1363 1364 ENTER(); 1365 1366 for (j = 0; j < pmadapter->priv_num; ++j) { 1367 if ((priv = pmadapter->priv[j])) { 1368 for (i = 0; i < MAX_NUM_TID; ++i) { 1369 priv->aggr_prio_tbl[i].amsdu = BA_STREAM_NOT_ALLOWED; 1370#ifdef WIFI_DIRECT_SUPPORT 1371 if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) 1372 priv->aggr_prio_tbl[i].ampdu_ap = 1373 priv->aggr_prio_tbl[i].ampdu_user = 1374 BA_STREAM_NOT_ALLOWED; 1375 else 1376#endif 1377 priv->aggr_prio_tbl[i].ampdu_ap = 1378 priv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i]; 1379 priv->wmm.pkts_queued[i] = 0; 1380 priv->wmm.tid_tbl_ptr[i].ra_list_curr = MNULL; 1381 } 1382 1383 priv->aggr_prio_tbl[6].ampdu_ap 1384 = priv->aggr_prio_tbl[6].ampdu_user = BA_STREAM_NOT_ALLOWED; 1385 1386 priv->aggr_prio_tbl[7].ampdu_ap 1387 = priv->aggr_prio_tbl[7].ampdu_user = BA_STREAM_NOT_ALLOWED; 1388 1389 priv->add_ba_param.timeout = MLAN_DEFAULT_BLOCK_ACK_TIMEOUT; 1390#ifdef STA_SUPPORT 1391 if (priv->bss_type == MLAN_BSS_TYPE_STA) { 1392 priv->add_ba_param.tx_win_size = MLAN_STA_AMPDU_DEF_TXWINSIZE; 1393 priv->add_ba_param.rx_win_size = MLAN_STA_AMPDU_DEF_RXWINSIZE; 1394 } 1395#endif 1396#ifdef UAP_SUPPORT 1397 if (priv->bss_type == MLAN_BSS_TYPE_UAP 1398#ifdef WIFI_DIRECT_SUPPORT 1399 || priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT 1400#endif 1401 ) { 1402 priv->add_ba_param.tx_win_size = MLAN_UAP_AMPDU_DEF_TXWINSIZE; 1403 priv->add_ba_param.rx_win_size = MLAN_UAP_AMPDU_DEF_RXWINSIZE; 1404 } 1405#endif 1406 priv->add_ba_param.tx_amsdu = MTRUE; 1407 priv->add_ba_param.rx_amsdu = MTRUE; 1408 memset(priv->adapter, priv->rx_seq, 0xff, sizeof(priv->rx_seq)); 1409 wlan_wmm_default_queue_priorities(priv); 1410 } 1411 } 1412 1413 LEAVE(); 1414} 1415 1416/** 1417 * @brief Setup the queue priorities and downgrade any queues as required 1418 * by the WMM info. Setups default values if WMM is not active 1419 * for this association. 1420 * 1421 * @param priv Pointer to the mlan_private driver data struct 1422 * 1423 * @return N/A 1424 */ 1425void 1426wlan_wmm_setup_queues(pmlan_private priv) 1427{ 1428 ENTER(); 1429 wlan_wmm_setup_queue_priorities(priv, MNULL); 1430 wlan_wmm_setup_ac_downgrade(priv); 1431 LEAVE(); 1432} 1433 1434#ifdef STA_SUPPORT 1435/** 1436 * @brief Send a command to firmware to retrieve the current WMM status 1437 * 1438 * @param priv Pointer to the mlan_private driver data struct 1439 * 1440 * @return MLAN_STATUS_SUCCESS; MLAN_STATUS_FAILURE 1441 */ 1442mlan_status 1443wlan_cmd_wmm_status_change(pmlan_private priv) 1444{ 1445 mlan_status ret = MLAN_STATUS_SUCCESS; 1446 1447 ENTER(); 1448 1449 ret = wlan_prepare_cmd(priv, HostCmd_CMD_WMM_GET_STATUS, 0, 0, 0, MNULL); 1450 LEAVE(); 1451 return ret; 1452} 1453#endif 1454 1455/** 1456 * @brief Check if wmm TX queue is empty 1457 * 1458 * @param pmadapter Pointer to the mlan_adapter driver data struct 1459 * 1460 * @return MFALSE if not empty; MTRUE if empty 1461 */ 1462int 1463wlan_wmm_lists_empty(pmlan_adapter pmadapter) 1464{ 1465 int j; 1466 pmlan_private priv; 1467 1468 ENTER(); 1469 1470 for (j = 0; j < pmadapter->priv_num; ++j) { 1471 if ((priv = pmadapter->priv[j])) { 1472 if ((priv->port_ctrl_mode == MTRUE) && (priv->port_open == MFALSE)) { 1473 PRINTM(MINFO, 1474 "wmm_lists_empty: PORT_CLOSED Ignore pkts from BSS%d\n", 1475 j); 1476 continue; 1477 } 1478 1479 if (util_scalar_read(pmadapter->pmoal_handle, 1480 &priv->wmm.tx_pkts_queued, 1481 pmadapter->callbacks.moal_spin_lock, 1482 pmadapter->callbacks.moal_spin_unlock)) { 1483 LEAVE(); 1484 return MFALSE; 1485 } 1486 } 1487 } 1488 1489 LEAVE(); 1490 return MTRUE; 1491} 1492 1493/** 1494 * @brief Get ralist node 1495 * 1496 * @param priv Pointer to the mlan_private driver data struct 1497 * @param tid TID 1498 * @param ra_addr Pointer to the route address 1499 * 1500 * @return ra_list or MNULL 1501 */ 1502raListTbl * 1503wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid, t_u8 * ra_addr) 1504{ 1505 raListTbl *ra_list; 1506 ENTER(); 1507 ra_list = 1508 (raListTbl *) util_peek_list(priv->adapter->pmoal_handle, 1509 &priv->wmm.tid_tbl_ptr[tid].ra_list, MNULL, 1510 MNULL); 1511 while (ra_list && (ra_list != (raListTbl *) 1512 & priv->wmm.tid_tbl_ptr[tid].ra_list)) { 1513 if (!memcmp(priv->adapter, ra_list->ra, ra_addr, MLAN_MAC_ADDR_LENGTH)) { 1514 LEAVE(); 1515 return ra_lis…
Large files files are truncated, but you can click here to view the full file