wmm.c revision f699254c7126d7df94491dfd4c3648f8ec0c0d51
15e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 25e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Marvell Wireless LAN device driver: WMM 35e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 45e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Copyright (C) 2011, Marvell International Ltd. 55e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 65e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This software file (the "File") is distributed by Marvell International 75e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Ltd. under the terms of the GNU General Public License Version 2, June 1991 85e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * (the "License"). You may use, redistribute and/or modify this File in 95e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * accordance with the terms and conditions of the License, a copy of which 105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * is available by writing to the Free Software Foundation, Inc., 115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * this warranty disclaimer. 185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "decl.h" 215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "ioctl.h" 225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "util.h" 235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "fw.h" 245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "main.h" 255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "wmm.h" 265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#include "11n.h" 275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* Maximum value FW can accept for driver delay in packet transmission */ 305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#define DRV_PKT_DELAY_TO_FW_MAX 512 315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#define WMM_QUEUED_PACKET_LOWER_LIMIT 180 345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#define WMM_QUEUED_PACKET_UPPER_LIMIT 200 365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* Offset for TOS field in the IP header */ 385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#define IPTOS_OFFSET 5 395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* WMM information IE */ 415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic const u8 wmm_info_ie[] = { WLAN_EID_VENDOR_SPECIFIC, 0x07, 425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x00, 0x50, 0xf2, 0x02, 435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x00, 0x01, 0x00 445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao}; 455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic const u8 wmm_aci_to_qidx_map[] = { WMM_AC_BE, 475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_BK, 485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_VI, 495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_VO 505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao}; 515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic u8 tos_to_tid[] = { 535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* TID DSCP_P2 DSCP_P1 DSCP_P0 WMM_AC */ 545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x01, /* 0 1 0 AC_BK */ 555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x02, /* 0 0 0 AC_BK */ 565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x00, /* 0 0 1 AC_BE */ 575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x03, /* 0 1 1 AC_BE */ 585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x04, /* 1 0 0 AC_VI */ 595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x05, /* 1 0 1 AC_VI */ 605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x06, /* 1 1 0 AC_VO */ 615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x07 /* 1 1 1 AC_VO */ 625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao}; 635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This table inverses the tos_to_tid operation to get a priority 665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * which is in sequential order, and can be compared. 675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Use this to compare the priority of two different TIDs. 685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic u8 tos_to_tid_inv[] = { 705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x02, /* from tos_to_tid[2] = 0 */ 715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x00, /* from tos_to_tid[0] = 1 */ 725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x01, /* from tos_to_tid[1] = 2 */ 735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x03, 745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x04, 755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x05, 765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x06, 775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 0x07}; 785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} }; 805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function debug prints the priority parameters for a WMM AC. 835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void 855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_ac_debug_print(const struct ieee_types_wmm_ac_parameters *ac_param) 865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao const char *ac_str[] = { "BK", "BE", "VI", "VO" }; 885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao pr_debug("info: WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, " 905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n", 915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_str[wmm_aci_to_qidx_map[(ac_param->aci_aifsn_bitmap 925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao & MWIFIEX_ACI) >> 5]], 935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (ac_param->aci_aifsn_bitmap & MWIFIEX_ACI) >> 5, 945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (ac_param->aci_aifsn_bitmap & MWIFIEX_ACM) >> 4, 955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_param->aci_aifsn_bitmap & MWIFIEX_AIFSN, 965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_param->ecw_bitmap & MWIFIEX_ECW_MIN, 975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (ac_param->ecw_bitmap & MWIFIEX_ECW_MAX) >> 4, 985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao le16_to_cpu(ac_param->tx_op_limit)); 995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 1005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 1025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function allocates a route address list. 1035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 1045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * The function also initializes the list with the provided RA. 1055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 1065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic struct mwifiex_ra_list_tbl * 1075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra) 1085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 1095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ra_list; 1105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list = kzalloc(sizeof(struct mwifiex_ra_list_tbl), GFP_ATOMIC); 1125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!ra_list) { 1145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_err(adapter->dev, "%s: failed to alloc ra_list\n", 1155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao __func__); 1165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return NULL; 1175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 1185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao INIT_LIST_HEAD(&ra_list->list); 1195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_queue_head_init(&ra_list->skb_head); 1205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao memcpy(ra_list->ra, ra, ETH_ALEN); 1225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list->total_pkts_size = 0; 1245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(adapter->dev, "info: allocated ra_list %p\n", ra_list); 1265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return ra_list; 1285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 1295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 1315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function allocates and adds a RA list for all TIDs 1325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * with the given RA. 1335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 1345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaovoid 1355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra) 1365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 1375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int i; 1385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ra_list; 1395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_adapter *adapter = priv->adapter; 1405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (i = 0; i < MAX_NUM_TID; ++i) { 1425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra); 1435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(adapter->dev, "info: created ra_list %p\n", ra_list); 1445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!ra_list) 1465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 1475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!mwifiex_queuing_ra_based(priv)) 1495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list->is_11n_enabled = IS_11N_ENABLED(priv); 1505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao else 1515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list->is_11n_enabled = false; 1525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(adapter->dev, "data: ralist %p: is_11n_enabled=%d\n", 1545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list, ra_list->is_11n_enabled); 1555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_add_tail(&ra_list->list, 1575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &priv->wmm.tid_tbl_ptr[i].ra_list); 1585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!priv->wmm.tid_tbl_ptr[i].ra_list_curr) 1605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.tid_tbl_ptr[i].ra_list_curr = ra_list; 1615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 1625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 1635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 1655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function sets the WMM queue priorities to their default values. 1665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 1675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv) 1685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 1695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Default queue priorities: VO->VI->BE->BK */ 1705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.queue_priority[0] = WMM_AC_VO; 1715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.queue_priority[1] = WMM_AC_VI; 1725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.queue_priority[2] = WMM_AC_BE; 1735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.queue_priority[3] = WMM_AC_BK; 1745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 1755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 1775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function map ACs to TIDs. 1785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 1795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void 180572e8f3ead47ad223fb428a4f1db986317e8e0ecAmitkumar Karwarmwifiex_wmm_queue_priorities_tid(u8 queue_priority[]) 1815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 1825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int i; 1835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (i = 0; i < 4; ++i) { 1855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tos_to_tid[7 - (i * 2)] = ac_to_tid[queue_priority[i]][1]; 1865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tos_to_tid[6 - (i * 2)] = ac_to_tid[queue_priority[i]][0]; 1875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 1885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 1895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 1915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function initializes WMM priority queues. 1925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 1935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaovoid 1945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, 1955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct ieee_types_wmm_parameter *wmm_ie) 1965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 1975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u16 cw_min, avg_back_off, tmp[4]; 1985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u32 i, j, num_ac; 1995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u8 ac_idx; 2005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!wmm_ie || !priv->wmm_enabled) { 2025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* WMM is not enabled, just set the defaults and return */ 2035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_wmm_default_queue_priorities(priv); 2045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return; 2055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 2065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, "info: WMM Parameter IE: version=%d, " 2085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao "qos_info Parameter Set Count=%d, Reserved=%#x\n", 2095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_ie->vend_hdr.version, wmm_ie->qos_info_bitmap & 2105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK, 2115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_ie->reserved); 2125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (num_ac = 0; num_ac < ARRAY_SIZE(wmm_ie->ac_params); num_ac++) { 2145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao cw_min = (1 << (wmm_ie->ac_params[num_ac].ecw_bitmap & 2155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao MWIFIEX_ECW_MIN)) - 1; 2165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao avg_back_off = (cw_min >> 1) + 2175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (wmm_ie->ac_params[num_ac].aci_aifsn_bitmap & 2185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao MWIFIEX_AIFSN); 2195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_idx = wmm_aci_to_qidx_map[(wmm_ie->ac_params[num_ac]. 2215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao aci_aifsn_bitmap & 2225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao MWIFIEX_ACI) >> 5]; 2235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.queue_priority[ac_idx] = ac_idx; 2245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tmp[ac_idx] = avg_back_off; 2255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, "info: WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n", 2275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (1 << ((wmm_ie->ac_params[num_ac].ecw_bitmap & 2285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao MWIFIEX_ECW_MAX) >> 4)) - 1, 2295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao cw_min, avg_back_off); 2305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_wmm_ac_debug_print(&wmm_ie->ac_params[num_ac]); 2315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 2325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Bubble sort */ 2345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (i = 0; i < num_ac; i++) { 2355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (j = 1; j < num_ac - i; j++) { 2365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (tmp[j - 1] > tmp[j]) { 2375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao swap(tmp[j - 1], tmp[j]); 2385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao swap(priv->wmm.queue_priority[j - 1], 2395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.queue_priority[j]); 2405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } else if (tmp[j - 1] == tmp[j]) { 2415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (priv->wmm.queue_priority[j - 1] 2425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao < priv->wmm.queue_priority[j]) 2435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao swap(priv->wmm.queue_priority[j - 1], 2445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.queue_priority[j]); 2455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 2465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 2475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 2485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 249572e8f3ead47ad223fb428a4f1db986317e8e0ecAmitkumar Karwar mwifiex_wmm_queue_priorities_tid(priv->wmm.queue_priority); 2505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 2515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 2535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function evaluates whether or not an AC is to be downgraded. 2545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 2555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * In case the AC is not enabled, the highest AC is returned that is 2565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * enabled and does not require admission control. 2575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 2585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic enum mwifiex_wmm_ac_e 2595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_eval_downgrade_ac(struct mwifiex_private *priv, 2605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao enum mwifiex_wmm_ac_e eval_ac) 2615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 2625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int down_ac; 2635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao enum mwifiex_wmm_ac_e ret_ac; 2645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_wmm_ac_status *ac_status; 2655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_status = &priv->wmm.ac_status[eval_ac]; 2675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!ac_status->disabled) 2695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Okay to use this AC, its enabled */ 2705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return eval_ac; 2715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Setup a default return value of the lowest priority */ 2735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ret_ac = WMM_AC_BK; 2745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* 2765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Find the highest AC that is enabled and does not require 2775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * admission control. The spec disallows downgrading to an AC, 2785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * which is enabled due to a completed admission control. 2795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Unadmitted traffic is not to be sent on an AC with admitted 2805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * traffic. 2815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 2825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (down_ac = WMM_AC_BK; down_ac < eval_ac; down_ac++) { 2835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_status = &priv->wmm.ac_status[down_ac]; 2845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!ac_status->disabled && !ac_status->flow_required) 2865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* AC is enabled and does not require admission 2875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao control */ 2885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ret_ac = (enum mwifiex_wmm_ac_e) down_ac; 2895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 2905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return ret_ac; 2925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 2935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 2955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function downgrades WMM priority queue. 2965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 2975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaovoid 2985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv) 2995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 3005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int ac_val; 3015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, "info: WMM: AC Priorities:" 3035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao "BK(0), BE(1), VI(2), VO(3)\n"); 3045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!priv->wmm_enabled) { 3065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* WMM is not enabled, default priorities */ 3075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) 3085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.ac_down_graded_vals[ac_val] = 3095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (enum mwifiex_wmm_ac_e) ac_val; 3105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } else { 3115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) { 3125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.ac_down_graded_vals[ac_val] 3135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao = mwifiex_wmm_eval_downgrade_ac(priv, 3145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (enum mwifiex_wmm_ac_e) ac_val); 3155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, "info: WMM: AC PRIO %d maps to %d\n", 3165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_val, priv->wmm.ac_down_graded_vals[ac_val]); 3175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 3185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 3195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 3205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 3225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function converts the IP TOS field to an WMM AC 3235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Queue assignment. 3245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 3255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic enum mwifiex_wmm_ac_e 3265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_convert_tos_to_ac(struct mwifiex_adapter *adapter, u32 tos) 3275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 3285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Map of TOS UP values to WMM AC */ 3295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao const enum mwifiex_wmm_ac_e tos_to_ac[] = { WMM_AC_BE, 3305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_BK, 3315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_BK, 3325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_BE, 3335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_VI, 3345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_VI, 3355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_VO, 3365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_VO 3375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao }; 3385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (tos >= ARRAY_SIZE(tos_to_ac)) 3405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return WMM_AC_BE; 3415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return tos_to_ac[tos]; 3435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 3445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 3465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function evaluates a given TID and downgrades it to a lower 3475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * TID if the WMM Parameter IE received from the AP indicates that the 3485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * AP is disabled (due to call admission control (ACM bit). Mapping 3495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * of TID to AC is taken care of internally. 3505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 3515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic u8 3525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid) 3535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 3545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao enum mwifiex_wmm_ac_e ac, ac_down; 3555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u8 new_tid; 3565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac = mwifiex_wmm_convert_tos_to_ac(priv->adapter, tid); 3585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_down = priv->wmm.ac_down_graded_vals[ac]; 3595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Send the index to tid array, picking from the array will be 3615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * taken care by dequeuing function 3625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 3635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao new_tid = ac_to_tid[ac_down][tid % 2]; 3645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return new_tid; 3665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 3675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 3695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function initializes the WMM state information and the 3705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * WMM data path queues. 3715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 3725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaovoid 3735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_init(struct mwifiex_adapter *adapter) 3745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 3755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int i, j; 3765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_private *priv; 3775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (j = 0; j < adapter->priv_num; ++j) { 3795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv = adapter->priv[j]; 3805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!priv) 3815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao continue; 3825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (i = 0; i < MAX_NUM_TID; ++i) { 3845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->aggr_prio_tbl[i].amsdu = tos_to_tid_inv[i]; 3855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->aggr_prio_tbl[i].ampdu_ap = tos_to_tid_inv[i]; 3865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i]; 3875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.tid_tbl_ptr[i].ra_list_curr = NULL; 3885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 3895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->aggr_prio_tbl[6].amsdu 3915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao = priv->aggr_prio_tbl[6].ampdu_ap 3925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao = priv->aggr_prio_tbl[6].ampdu_user 3935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao = BA_STREAM_NOT_ALLOWED; 3945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->aggr_prio_tbl[7].amsdu = priv->aggr_prio_tbl[7].ampdu_ap 3965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao = priv->aggr_prio_tbl[7].ampdu_user 3975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao = BA_STREAM_NOT_ALLOWED; 3985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; 4005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE; 4015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE; 402f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang 403f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang atomic_set(&priv->wmm.tx_pkts_queued, 0); 4045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 4055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 4065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 4085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function checks if WMM Tx queue is empty. 4095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 4105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaoint 4115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) 4125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 413f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang int i; 4145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_private *priv; 4155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 416f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang for (i = 0; i < adapter->priv_num; ++i) { 417f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang priv = adapter->priv[i]; 418f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang if (priv && atomic_read(&priv->wmm.tx_pkts_queued)) 419f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang return false; 4205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 4215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return true; 4235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 4245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 4265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function deletes all packets in an RA list node. 4275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 4285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * The packet sent completion callback handler are called with 4295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * status failure, after they are dequeued to ensure proper 4305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * cleanup. The RA list node itself is freed at the end. 4315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 4325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void 4335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_del_pkts_in_ralist_node(struct mwifiex_private *priv, 4345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ra_list) 4355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 4365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_adapter *adapter = priv->adapter; 4375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct sk_buff *skb, *tmp; 4385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) 4405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_write_data_complete(adapter, skb, -1); 4415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 4425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 4445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function deletes all packets in an RA list. 4455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 4465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Each nodes in the RA list are freed individually first, and then 4475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * the RA list itself is freed. 4485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 4495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void 4505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_del_pkts_in_ralist(struct mwifiex_private *priv, 4515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct list_head *ra_list_head) 4525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 4535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ra_list; 4545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_for_each_entry(ra_list, ra_list_head, list) 4565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_wmm_del_pkts_in_ralist_node(priv, ra_list); 4575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 4585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 4605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function deletes all packets in all RA lists. 4615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 4625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void mwifiex_wmm_cleanup_queues(struct mwifiex_private *priv) 4635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 4645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int i; 4655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (i = 0; i < MAX_NUM_TID; i++) 4675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_wmm_del_pkts_in_ralist(priv, &priv->wmm.tid_tbl_ptr[i]. 4685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list); 469f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang 470f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang atomic_set(&priv->wmm.tx_pkts_queued, 0); 4715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 4725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 4745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function deletes all route addresses from all RA lists. 4755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 4765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void mwifiex_wmm_delete_all_ralist(struct mwifiex_private *priv) 4775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 4785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ra_list, *tmp_node; 4795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int i; 4805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (i = 0; i < MAX_NUM_TID; ++i) { 4825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, 4835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao "info: ra_list: freeing buf for tid %d\n", i); 4845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_for_each_entry_safe(ra_list, tmp_node, 4855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &priv->wmm.tid_tbl_ptr[i].ra_list, list) { 4865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_del(&ra_list->list); 4875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao kfree(ra_list); 4885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 4895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[i].ra_list); 4915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.tid_tbl_ptr[i].ra_list_curr = NULL; 4935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 4945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 4955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 4975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function cleans up the Tx and Rx queues. 4985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 4995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Cleanup includes - 5005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * - All packets in RA lists 5015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * - All entries in Rx reorder table 5025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * - All entries in Tx BA stream table 5035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * - MPA buffer (if required) 5045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * - All RA lists 5055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 5065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaovoid 5075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_clean_txrx(struct mwifiex_private *priv) 5085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 5095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao unsigned long flags; 5105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_11n_cleanup_reorder_tbl(priv); 5125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); 5135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_wmm_cleanup_queues(priv); 5155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_11n_delete_all_tx_ba_stream_tbl(priv); 5165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (priv->adapter->if_ops.cleanup_mpa_buf) 5185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->adapter->if_ops.cleanup_mpa_buf(priv->adapter); 5195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_wmm_delete_all_ralist(priv); 5215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao memcpy(tos_to_tid, ac_to_tid, sizeof(tos_to_tid)); 5225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); 5245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 5255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 5275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function retrieves a particular RA list node, matching with the 5285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * given TID and RA address. 5295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 5305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic struct mwifiex_ra_list_tbl * 5315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, 5325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u8 *ra_addr) 5335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 5345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ra_list; 5355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_for_each_entry(ra_list, &priv->wmm.tid_tbl_ptr[tid].ra_list, 5375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list) { 5385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!memcmp(ra_list->ra, ra_addr, ETH_ALEN)) 5395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return ra_list; 5405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 5415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return NULL; 5435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 5445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 5465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function retrieves an RA list node for a given TID and 5475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * RA address pair. 5485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 5495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * If no such node is found, a new node is added first and then 5505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * retrieved. 5515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 5525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic struct mwifiex_ra_list_tbl * 5535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr) 5545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 5555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ra_list; 5565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list = mwifiex_wmm_get_ralist_node(priv, tid, ra_addr); 5585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (ra_list) 5595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return ra_list; 5605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_ralist_add(priv, ra_addr); 5615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return mwifiex_wmm_get_ralist_node(priv, tid, ra_addr); 5635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 5645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 5665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function checks if a particular RA list node exists in a given TID 5675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * table index. 5685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 5695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaoint 5705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_is_ralist_valid(struct mwifiex_private *priv, 5715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ra_list, int ptr_index) 5725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 5735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *rlist; 5745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_for_each_entry(rlist, &priv->wmm.tid_tbl_ptr[ptr_index].ra_list, 5765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list) { 5775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (rlist == ra_list) 5785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return true; 5795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 5805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return false; 5825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 5835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 5855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function adds a packet to WMM queue. 5865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 5875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * In disconnected state the packet is immediately dropped and the 5885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * packet send completion callback is called with status failure. 5895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 5905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Otherwise, the correct RA list node is located and the packet 5915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * is queued at the list tail. 5925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 5935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaovoid 5945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter, 5955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct sk_buff *skb) 5965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 5975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); 5985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_private *priv = adapter->priv[tx_info->bss_index]; 5995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u32 tid; 6005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ra_list; 6015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u8 ra[ETH_ALEN], tid_down; 6025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao unsigned long flags; 6035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!priv->media_connected) { 6055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(adapter->dev, "data: drop packet in disconnect\n"); 6065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_write_data_complete(adapter, skb, -1); 6075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return; 6085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 6095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tid = skb->priority; 6115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); 6135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tid_down = mwifiex_wmm_downgrade_tid(priv, tid); 6155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* In case of infra as we have already created the list during 6175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao association we just don't have to call get_queue_raptr, we will 6185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao have only 1 raptr for a tid in case of infra */ 6195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!mwifiex_queuing_ra_based(priv)) { 6205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!list_empty(&priv->wmm.tid_tbl_ptr[tid_down].ra_list)) 6215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list = list_first_entry( 6225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &priv->wmm.tid_tbl_ptr[tid_down].ra_list, 6235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl, list); 6245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao else 6255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list = NULL; 6265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } else { 6275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao memcpy(ra, skb->data, ETH_ALEN); 6285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, ra); 6295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 6305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!ra_list) { 6325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); 6335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_write_data_complete(adapter, skb, -1); 6345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return; 6355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 6365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_queue_tail(&ra_list->skb_head, skb); 6385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list->total_pkts_size += skb->len; 6405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 641f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang atomic_inc(&priv->wmm.tx_pkts_queued); 642f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang 6435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); 6445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 6455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 6475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function processes the get WMM status command response from firmware. 6485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 6495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * The response may contain multiple TLVs - 6505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * - AC Queue status TLVs 6515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * - Current WMM Parameter IE TLV 6525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * - Admission Control action frame TLVs 6535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 6545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function parses the TLVs and then calls further specific functions 6555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * to process any changes in the queue prioritize or state. 6565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 6575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaoint mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, 6585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao const struct host_cmd_ds_command *resp) 6595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 6605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u8 *curr = (u8 *) &resp->params.get_wmm_status; 6615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao uint16_t resp_len = le16_to_cpu(resp->size), tlv_len; 6625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int valid = true; 6635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ie_types_data *tlv_hdr; 6655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ie_types_wmm_queue_status *tlv_wmm_qstatus; 6665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct ieee_types_wmm_parameter *wmm_param_ie = NULL; 6675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_wmm_ac_status *ac_status; 6685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, "info: WMM: WMM_GET_STATUS cmdresp received: %d\n", 6705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao resp_len); 6715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao while ((resp_len >= sizeof(tlv_hdr->header)) && valid) { 6735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tlv_hdr = (struct mwifiex_ie_types_data *) curr; 6745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tlv_len = le16_to_cpu(tlv_hdr->header.len); 6755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao switch (le16_to_cpu(tlv_hdr->header.type)) { 6775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao case TLV_TYPE_WMMQSTATUS: 6785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tlv_wmm_qstatus = 6795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (struct mwifiex_ie_types_wmm_queue_status *) 6805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tlv_hdr; 6815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, 6825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao "info: CMD_RESP: WMM_GET_STATUS:" 6835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao " QSTATUS TLV: %d, %d, %d\n", 6845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tlv_wmm_qstatus->queue_index, 6855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tlv_wmm_qstatus->flow_required, 6865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tlv_wmm_qstatus->disabled); 6875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_status = &priv->wmm.ac_status[tlv_wmm_qstatus-> 6895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao queue_index]; 6905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_status->disabled = tlv_wmm_qstatus->disabled; 6915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_status->flow_required = 6925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tlv_wmm_qstatus->flow_required; 6935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_status->flow_created = tlv_wmm_qstatus->flow_created; 6945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 6955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao case WLAN_EID_VENDOR_SPECIFIC: 6975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* 6985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Point the regular IEEE IE 2 bytes into the Marvell IE 6995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * and setup the IEEE IE type and length byte fields 7005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 7015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_param_ie = 7035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (struct ieee_types_wmm_parameter *) (curr + 7045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2); 7055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_param_ie->vend_hdr.len = (u8) tlv_len; 7065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_param_ie->vend_hdr.element_id = 7075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WLAN_EID_VENDOR_SPECIFIC; 7085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, 7105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao "info: CMD_RESP: WMM_GET_STATUS:" 7115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao " WMM Parameter Set Count: %d\n", 7125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_param_ie->qos_info_bitmap & 7135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK); 7145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao memcpy((u8 *) &priv->curr_bss_params.bss_descriptor. 7165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_ie, wmm_param_ie, 7175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_param_ie->vend_hdr.len + 2); 7185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 7205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao default: 7225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao valid = false; 7235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 7245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 7255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao curr += (tlv_len + sizeof(tlv_hdr->header)); 7275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao resp_len -= (tlv_len + sizeof(tlv_hdr->header)); 7285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 7295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie); 7315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_wmm_setup_ac_downgrade(priv); 7325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return 0; 7345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 7355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 7375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Callback handler from the command module to allow insertion of a WMM TLV. 7385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 7395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * If the BSS we are associating to supports WMM, this function adds the 7405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * required WMM Information IE to the association request command buffer in 7415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * the form of a Marvell extended IEEE IE. 7425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 7435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaou32 7445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_process_association_req(struct mwifiex_private *priv, 7455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u8 **assoc_buf, 7465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct ieee_types_wmm_parameter *wmm_ie, 7475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct ieee80211_ht_cap *ht_cap) 7485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 7495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ie_types_wmm_param_set *wmm_tlv; 7505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u32 ret_len = 0; 7515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Null checks */ 7535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!assoc_buf) 7545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return 0; 7555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!(*assoc_buf)) 7565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return 0; 7575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!wmm_ie) 7595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return 0; 7605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, "info: WMM: process assoc req:" 7625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao "bss->wmmIe=0x%x\n", 7635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_ie->vend_hdr.element_id); 7645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if ((priv->wmm_required 7665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao || (ht_cap && (priv->adapter->config_bands & BAND_GN 7675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao || priv->adapter->config_bands & BAND_AN)) 7685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ) 7695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao && wmm_ie->vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) { 7705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_tlv = (struct mwifiex_ie_types_wmm_param_set *) *assoc_buf; 7715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_tlv->header.type = cpu_to_le16((u16) wmm_info_ie[0]); 7725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_tlv->header.len = cpu_to_le16((u16) wmm_info_ie[1]); 7735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao memcpy(wmm_tlv->wmm_ie, &wmm_info_ie[2], 7745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao le16_to_cpu(wmm_tlv->header.len)); 7755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (wmm_ie->qos_info_bitmap & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) 7765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao memcpy((u8 *) (wmm_tlv->wmm_ie 7775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao + le16_to_cpu(wmm_tlv->header.len) 7785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao - sizeof(priv->wmm_qosinfo)), 7795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &priv->wmm_qosinfo, 7805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao sizeof(priv->wmm_qosinfo)); 7815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ret_len = sizeof(wmm_tlv->header) 7835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao + le16_to_cpu(wmm_tlv->header.len); 7845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *assoc_buf += ret_len; 7865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 7875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return ret_len; 7895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 7905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 7925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function computes the time delay in the driver queues for a 7935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * given packet. 7945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 7955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * When the packet is received at the OS/Driver interface, the current 7965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * time is set in the packet structure. The difference between the present 7975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * time and that received time is computed in this function and limited 7985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * based on pre-compiled limits in the driver. 7995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 8005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaou8 8015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv, 8025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao const struct sk_buff *skb) 8035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 804270e58e8898c8be40451ebee45b6c9b5bd5db04bYogesh Ashok Powar u8 ret_val; 8055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct timeval out_tstamp, in_tstamp; 8065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u32 queue_delay; 8075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao do_gettimeofday(&out_tstamp); 8095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao in_tstamp = ktime_to_timeval(skb->tstamp); 8105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao queue_delay = (out_tstamp.tv_sec - in_tstamp.tv_sec) * 1000; 8125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao queue_delay += (out_tstamp.tv_usec - in_tstamp.tv_usec) / 1000; 8135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* 8155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Queue delay is passed as a uint8 in units of 2ms (ms shifted 8165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * by 1). Min value (other than 0) is therefore 2ms, max is 510ms. 8175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 8185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Pass max value if queue_delay is beyond the uint8 range 8195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 8205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ret_val = (u8) (min(queue_delay, priv->wmm.drv_pkt_delay_max) >> 1); 8215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, "data: WMM: Pkt Delay: %d ms," 8235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao " %d ms sent to FW\n", queue_delay, ret_val); 8245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return ret_val; 8265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 8275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 8295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function retrieves the highest priority RA list table pointer. 8305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 8315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic struct mwifiex_ra_list_tbl * 8325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, 8335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_private **priv, int *tid) 8345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 8355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_private *priv_tmp; 8365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ptr, *head; 8375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_bss_prio_node *bssprio_node, *bssprio_head; 8385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_tid_tbl *tid_ptr; 8395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int is_list_empty; 8405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao unsigned long flags; 8415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int i, j; 8425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (j = adapter->priv_num - 1; j >= 0; --j) { 8445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock, 8455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao flags); 8465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao is_list_empty = list_empty(&adapter->bss_prio_tbl[j] 8475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao .bss_prio_head); 8485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock, 8495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao flags); 8505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (is_list_empty) 8515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao continue; 8525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (adapter->bss_prio_tbl[j].bss_prio_cur == 8545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (struct mwifiex_bss_prio_node *) 8555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &adapter->bss_prio_tbl[j].bss_prio_head) { 8565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao bssprio_node = 8575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_first_entry(&adapter->bss_prio_tbl[j] 8585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao .bss_prio_head, 8595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_bss_prio_node, 8605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list); 8615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao bssprio_head = bssprio_node; 8625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } else { 8635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao bssprio_node = adapter->bss_prio_tbl[j].bss_prio_cur; 8645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao bssprio_head = bssprio_node; 8655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 8665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao do { 8685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv_tmp = bssprio_node->priv; 8695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (i = HIGH_PRIO_TID; i >= LOW_PRIO_TID; --i) { 8715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tid_ptr = &(priv_tmp)->wmm. 8735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tid_tbl_ptr[tos_to_tid[i]]; 8745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&tid_ptr->tid_tbl_lock, 8765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao flags); 8775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao is_list_empty = 8785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_empty(&adapter->bss_prio_tbl[j] 8795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao .bss_prio_head); 8805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&tid_ptr->tid_tbl_lock, 8815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao flags); 8825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (is_list_empty) 8835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao continue; 8845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* 8865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Always choose the next ra we transmitted 8875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * last time, this way we pick the ra's in 8885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * round robin fashion. 8895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 8905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr = list_first_entry( 8915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &tid_ptr->ra_list_curr->list, 8925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl, 8935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list); 8945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao head = ptr; 8965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (ptr == (struct mwifiex_ra_list_tbl *) 8975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &tid_ptr->ra_list) { 8985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Get next ra */ 8995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr = list_first_entry(&ptr->list, 9005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl, list); 9015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao head = ptr; 9025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 9035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao do { 9055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao is_list_empty = 9065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_queue_empty(&ptr->skb_head); 9075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!is_list_empty) { 9085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *priv = priv_tmp; 9095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *tid = tos_to_tid[i]; 9105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return ptr; 9115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 9125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Get next ra */ 9135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr = list_first_entry(&ptr->list, 9145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl, 9155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list); 9165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (ptr == 9175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (struct mwifiex_ra_list_tbl *) 9185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &tid_ptr->ra_list) 9195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr = list_first_entry( 9205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &ptr->list, 9215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl, 9225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list); 9235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } while (ptr != head); 9245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 9255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Get next bss priority node */ 9275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao bssprio_node = list_first_entry(&bssprio_node->list, 9285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_bss_prio_node, 9295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list); 9305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (bssprio_node == 9325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (struct mwifiex_bss_prio_node *) 9335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &adapter->bss_prio_tbl[j].bss_prio_head) 9345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Get next bss priority node */ 9355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao bssprio_node = list_first_entry( 9365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &bssprio_node->list, 9375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_bss_prio_node, 9385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list); 9395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } while (bssprio_node != bssprio_head); 9405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 9415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return NULL; 9425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 9435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 9455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function gets the number of packets in the Tx queue of a 9465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * particular RA list. 9475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 9485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic int 9495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_num_pkts_in_txq(struct mwifiex_private *priv, 9505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ptr, int max_buf_size) 9515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 9525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int count = 0, total_size = 0; 9535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct sk_buff *skb, *tmp; 9545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_queue_walk_safe(&ptr->skb_head, skb, tmp) { 9565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao total_size += skb->len; 9575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (total_size < max_buf_size) 9585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ++count; 9595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao else 9605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 9615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 9625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return count; 9645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 9655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 9675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function sends a single packet to firmware for transmission. 9685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 9695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void 9705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_send_single_packet(struct mwifiex_private *priv, 9715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ptr, int ptr_index, 9725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao unsigned long ra_list_flags) 9735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao __releases(&priv->wmm.ra_list_spinlock) 9745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 9755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct sk_buff *skb, *skb_next; 9765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_tx_param tx_param; 9775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_adapter *adapter = priv->adapter; 9785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_txinfo *tx_info; 9795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (skb_queue_empty(&ptr->skb_head)) { 9815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 9825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list_flags); 9835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(adapter->dev, "data: nothing to send\n"); 9845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return; 9855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 9865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb = skb_dequeue(&ptr->skb_head); 9885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tx_info = MWIFIEX_SKB_TXCB(skb); 9905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(adapter->dev, "data: dequeuing the packet %p %p\n", ptr, skb); 9915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr->total_pkts_size -= skb->len; 9935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!skb_queue_empty(&ptr->skb_head)) 9955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_next = skb_peek(&ptr->skb_head); 9965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao else 9975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_next = NULL; 9985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); 10005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tx_param.next_pkt_len = ((skb_next) ? skb_next->len + 10025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao sizeof(struct txpd) : 0); 10035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1004636c4598499eeacce0893dc8d91113b904bd531eYogesh Ashok Powar if (mwifiex_process_tx(priv, skb, &tx_param) == -EBUSY) { 10055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Queue the packet back at the head */ 10065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); 10075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { 10095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 10105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list_flags); 10115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_write_data_complete(adapter, skb, -1); 10125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return; 10135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 10145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_queue_tail(&ptr->skb_head, skb); 10165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr->total_pkts_size += skb->len; 10185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; 10195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 10205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list_flags); 10215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } else { 10225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); 10235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { 10245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.packets_out[ptr_index]++; 10255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.tid_tbl_ptr[ptr_index].ra_list_curr = ptr; 10265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 10275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = 10285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_first_entry( 10295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &adapter->bss_prio_tbl[priv->bss_priority] 10305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao .bss_prio_cur->list, 10315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_bss_prio_node, 10325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list); 1033f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang atomic_dec(&priv->wmm.tx_pkts_queued); 10345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 10355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list_flags); 10365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 10375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 10385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 10405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function checks if the first packet in the given RA list 10415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * is already processed or not. 10425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 10435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic int 10445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_is_ptr_processed(struct mwifiex_private *priv, 10455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ptr) 10465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 10475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct sk_buff *skb; 10485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_txinfo *tx_info; 10495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (skb_queue_empty(&ptr->skb_head)) 10515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return false; 10525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb = skb_peek(&ptr->skb_head); 10545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tx_info = MWIFIEX_SKB_TXCB(skb); 10565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (tx_info->flags & MWIFIEX_BUF_FLAG_REQUEUED_PKT) 10575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return true; 10585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return false; 10605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 10615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 10635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function sends a single processed packet to firmware for 10645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * transmission. 10655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 10665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void 10675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_send_processed_packet(struct mwifiex_private *priv, 10685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ptr, int ptr_index, 10695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao unsigned long ra_list_flags) 10705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao __releases(&priv->wmm.ra_list_spinlock) 10715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 10725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_tx_param tx_param; 10735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_adapter *adapter = priv->adapter; 10745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int ret = -1; 10755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct sk_buff *skb, *skb_next; 10765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_txinfo *tx_info; 10775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (skb_queue_empty(&ptr->skb_head)) { 10795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 10805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list_flags); 10815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return; 10825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 10835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb = skb_dequeue(&ptr->skb_head); 10855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!skb_queue_empty(&ptr->skb_head)) 10875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_next = skb_peek(&ptr->skb_head); 10885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao else 10895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_next = NULL; 10905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tx_info = MWIFIEX_SKB_TXCB(skb); 10925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); 10945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tx_param.next_pkt_len = 10955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ((skb_next) ? skb_next->len + 10965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao sizeof(struct txpd) : 0); 10975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, 10985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb->data, skb->len, &tx_param); 10995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao switch (ret) { 11005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao case -EBUSY: 11015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); 11025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); 11035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { 11055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 11065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list_flags); 11075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_write_data_complete(adapter, skb, -1); 11085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return; 11095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 11105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_queue_tail(&ptr->skb_head, skb); 11125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; 11145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 11155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list_flags); 11165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 11175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao case -1: 11185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao adapter->data_sent = false; 11195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_err(adapter->dev, "host_to_card failed: %#x\n", ret); 11205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao adapter->dbg.num_tx_host_to_card_failure++; 11215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_write_data_complete(adapter, skb, ret); 11225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 11235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao case -EINPROGRESS: 11245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao adapter->data_sent = false; 11255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao default: 11265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 11275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 11285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (ret != -EBUSY) { 11295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); 11305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { 11315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.packets_out[ptr_index]++; 11325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.tid_tbl_ptr[ptr_index].ra_list_curr = ptr; 11335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 11345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = 11355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_first_entry( 11365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &adapter->bss_prio_tbl[priv->bss_priority] 11375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao .bss_prio_cur->list, 11385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_bss_prio_node, 11395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list); 1140f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang atomic_dec(&priv->wmm.tx_pkts_queued); 11415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 11425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list_flags); 11435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 11445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 11455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 11475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function dequeues a packet from the highest priority list 11485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * and transmits it. 11495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 11505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic int 11515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) 11525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 11535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ptr; 11545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_private *priv = NULL; 11555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int ptr_index = 0; 11565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u8 ra[ETH_ALEN]; 11575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int tid_del = 0, tid = 0; 11585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao unsigned long flags; 11595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr = mwifiex_wmm_get_highest_priolist_ptr(adapter, &priv, &ptr_index); 11615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!ptr) 11625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return -1; 11635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1164572e8f3ead47ad223fb428a4f1db986317e8e0ecAmitkumar Karwar tid = mwifiex_get_tid(ptr); 11655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(adapter->dev, "data: tid=%d\n", tid); 11675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); 11695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { 11705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); 11715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return -1; 11725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 11735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (mwifiex_is_ptr_processed(priv, ptr)) { 11755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_send_processed_packet(priv, ptr, ptr_index, flags); 11765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* ra_list_spinlock has been freed in 11775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_send_processed_packet() */ 11785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return 0; 11795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 11805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!ptr->is_11n_enabled || mwifiex_is_ba_stream_setup(priv, ptr, tid) 11825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao || ((priv->sec_info.wpa_enabled 11835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao || priv->sec_info.wpa2_enabled) && !priv->wpa_is_gtk_set) 11845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ) { 11855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_send_single_packet(priv, ptr, ptr_index, flags); 11865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* ra_list_spinlock has been freed in 11875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_send_single_packet() */ 11885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } else { 1189572e8f3ead47ad223fb428a4f1db986317e8e0ecAmitkumar Karwar if (mwifiex_is_ampdu_allowed(priv, tid)) { 119053d7938e6a2ac6569476fc59b404e70c0537b42bBing Zhao if (mwifiex_space_avail_for_new_ba_stream(adapter)) { 11915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_11n_create_tx_ba_stream_tbl(priv, 11925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr->ra, tid, 11935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao BA_STREAM_SETUP_INPROGRESS); 11945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_send_addba(priv, tid, ptr->ra); 11955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } else if (mwifiex_find_stream_to_delete 1196572e8f3ead47ad223fb428a4f1db986317e8e0ecAmitkumar Karwar (priv, tid, &tid_del, ra)) { 11975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_11n_create_tx_ba_stream_tbl(priv, 11985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr->ra, tid, 11995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao BA_STREAM_SETUP_INPROGRESS); 12005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_send_delba(priv, tid_del, ra, 1); 12015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 12025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 12035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* Minimum number of AMSDU */ 12045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao#define MIN_NUM_AMSDU 2 1205572e8f3ead47ad223fb428a4f1db986317e8e0ecAmitkumar Karwar if (mwifiex_is_amsdu_allowed(priv, tid) && 12065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (mwifiex_num_pkts_in_txq(priv, ptr, adapter->tx_buf_size) >= 12075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao MIN_NUM_AMSDU)) 12085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN, 12095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr_index, flags); 12105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* ra_list_spinlock has been freed in 12115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_11n_aggregate_pkt() */ 12125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao else 12135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_send_single_packet(priv, ptr, ptr_index, flags); 12145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* ra_list_spinlock has been freed in 12155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_send_single_packet() */ 12165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 12175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return 0; 12185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 12195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 12205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 12215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function transmits the highest priority packet awaiting in the 12225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * WMM Queues. 12235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 12245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaovoid 12255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_process_tx(struct mwifiex_adapter *adapter) 12265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 12275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao do { 12285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Check if busy */ 12295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (adapter->data_sent || adapter->tx_lock_flag) 12305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 12315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 12325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (mwifiex_dequeue_tx_packet(adapter)) 12335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 12345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } while (true); 12355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 1236