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 18049729ff616547d7abcb96924d14aa860320e7352Marc Yangmwifiex_wmm_queue_priorities_tid(struct mwifiex_wmm_desc *wmm) 1815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 18249729ff616547d7abcb96924d14aa860320e7352Marc Yang u8 *queue_priority = wmm->queue_priority; 1835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int i; 1845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (i = 0; i < 4; ++i) { 1865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tos_to_tid[7 - (i * 2)] = ac_to_tid[queue_priority[i]][1]; 1875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tos_to_tid[6 - (i * 2)] = ac_to_tid[queue_priority[i]][0]; 1885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 18949729ff616547d7abcb96924d14aa860320e7352Marc Yang 19049729ff616547d7abcb96924d14aa860320e7352Marc Yang for (i = 0; i < MAX_NUM_TID; ++i) 19149729ff616547d7abcb96924d14aa860320e7352Marc Yang tos_to_tid_inv[tos_to_tid[i]] = (u8)i; 19249729ff616547d7abcb96924d14aa860320e7352Marc Yang 19349729ff616547d7abcb96924d14aa860320e7352Marc Yang atomic_set(&wmm->highest_queued_prio, HIGH_PRIO_TID); 1945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 1955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 1975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function initializes WMM priority queues. 1985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 1995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaovoid 2005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, 2015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct ieee_types_wmm_parameter *wmm_ie) 2025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 2035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u16 cw_min, avg_back_off, tmp[4]; 2045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u32 i, j, num_ac; 2055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u8 ac_idx; 2065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!wmm_ie || !priv->wmm_enabled) { 2085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* WMM is not enabled, just set the defaults and return */ 2095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_wmm_default_queue_priorities(priv); 2105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return; 2115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 2125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, "info: WMM Parameter IE: version=%d, " 2145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao "qos_info Parameter Set Count=%d, Reserved=%#x\n", 2155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_ie->vend_hdr.version, wmm_ie->qos_info_bitmap & 2165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK, 2175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_ie->reserved); 2185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (num_ac = 0; num_ac < ARRAY_SIZE(wmm_ie->ac_params); num_ac++) { 2205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao cw_min = (1 << (wmm_ie->ac_params[num_ac].ecw_bitmap & 2215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao MWIFIEX_ECW_MIN)) - 1; 2225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao avg_back_off = (cw_min >> 1) + 2235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (wmm_ie->ac_params[num_ac].aci_aifsn_bitmap & 2245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao MWIFIEX_AIFSN); 2255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_idx = wmm_aci_to_qidx_map[(wmm_ie->ac_params[num_ac]. 2275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao aci_aifsn_bitmap & 2285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao MWIFIEX_ACI) >> 5]; 2295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.queue_priority[ac_idx] = ac_idx; 2305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tmp[ac_idx] = avg_back_off; 2315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, "info: WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n", 2335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (1 << ((wmm_ie->ac_params[num_ac].ecw_bitmap & 2345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao MWIFIEX_ECW_MAX) >> 4)) - 1, 2355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao cw_min, avg_back_off); 2365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_wmm_ac_debug_print(&wmm_ie->ac_params[num_ac]); 2375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 2385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Bubble sort */ 2405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (i = 0; i < num_ac; i++) { 2415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (j = 1; j < num_ac - i; j++) { 2425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (tmp[j - 1] > tmp[j]) { 2435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao swap(tmp[j - 1], tmp[j]); 2445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao swap(priv->wmm.queue_priority[j - 1], 2455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.queue_priority[j]); 2465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } else if (tmp[j - 1] == tmp[j]) { 2475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (priv->wmm.queue_priority[j - 1] 2485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao < priv->wmm.queue_priority[j]) 2495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao swap(priv->wmm.queue_priority[j - 1], 2505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.queue_priority[j]); 2515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 2525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 2535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 2545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 25549729ff616547d7abcb96924d14aa860320e7352Marc Yang mwifiex_wmm_queue_priorities_tid(&priv->wmm); 2565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 2575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 2595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function evaluates whether or not an AC is to be downgraded. 2605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 2615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * In case the AC is not enabled, the highest AC is returned that is 2625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * enabled and does not require admission control. 2635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 2645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic enum mwifiex_wmm_ac_e 2655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_eval_downgrade_ac(struct mwifiex_private *priv, 2665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao enum mwifiex_wmm_ac_e eval_ac) 2675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 2685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int down_ac; 2695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao enum mwifiex_wmm_ac_e ret_ac; 2705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_wmm_ac_status *ac_status; 2715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_status = &priv->wmm.ac_status[eval_ac]; 2735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!ac_status->disabled) 2755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Okay to use this AC, its enabled */ 2765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return eval_ac; 2775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Setup a default return value of the lowest priority */ 2795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ret_ac = WMM_AC_BK; 2805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* 2825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Find the highest AC that is enabled and does not require 2835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * admission control. The spec disallows downgrading to an AC, 2845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * which is enabled due to a completed admission control. 2855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Unadmitted traffic is not to be sent on an AC with admitted 2865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * traffic. 2875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 2885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (down_ac = WMM_AC_BK; down_ac < eval_ac; down_ac++) { 2895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_status = &priv->wmm.ac_status[down_ac]; 2905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!ac_status->disabled && !ac_status->flow_required) 2925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* AC is enabled and does not require admission 2935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao control */ 2945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ret_ac = (enum mwifiex_wmm_ac_e) down_ac; 2955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 2965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return ret_ac; 2985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 2995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 3015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function downgrades WMM priority queue. 3025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 3035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaovoid 3045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv) 3055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 3065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int ac_val; 3075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, "info: WMM: AC Priorities:" 3095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao "BK(0), BE(1), VI(2), VO(3)\n"); 3105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!priv->wmm_enabled) { 3125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* WMM is not enabled, default priorities */ 3135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) 3145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.ac_down_graded_vals[ac_val] = 3155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (enum mwifiex_wmm_ac_e) ac_val; 3165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } else { 3175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) { 3185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.ac_down_graded_vals[ac_val] 3195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao = mwifiex_wmm_eval_downgrade_ac(priv, 3205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (enum mwifiex_wmm_ac_e) ac_val); 3215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, "info: WMM: AC PRIO %d maps to %d\n", 3225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_val, priv->wmm.ac_down_graded_vals[ac_val]); 3235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 3245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 3255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 3265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 3285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function converts the IP TOS field to an WMM AC 3295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Queue assignment. 3305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 3315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic enum mwifiex_wmm_ac_e 3325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_convert_tos_to_ac(struct mwifiex_adapter *adapter, u32 tos) 3335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 3345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Map of TOS UP values to WMM AC */ 3355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao const enum mwifiex_wmm_ac_e tos_to_ac[] = { WMM_AC_BE, 3365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_BK, 3375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_BK, 3385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_BE, 3395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_VI, 3405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_VI, 3415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_VO, 3425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WMM_AC_VO 3435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao }; 3445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (tos >= ARRAY_SIZE(tos_to_ac)) 3465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return WMM_AC_BE; 3475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return tos_to_ac[tos]; 3495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 3505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 3525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function evaluates a given TID and downgrades it to a lower 3535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * TID if the WMM Parameter IE received from the AP indicates that the 3545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * AP is disabled (due to call admission control (ACM bit). Mapping 3555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * of TID to AC is taken care of internally. 3565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 3575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic u8 3585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid) 3595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 3605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao enum mwifiex_wmm_ac_e ac, ac_down; 3615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u8 new_tid; 3625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac = mwifiex_wmm_convert_tos_to_ac(priv->adapter, tid); 3645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_down = priv->wmm.ac_down_graded_vals[ac]; 3655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Send the index to tid array, picking from the array will be 3675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * taken care by dequeuing function 3685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 3695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao new_tid = ac_to_tid[ac_down][tid % 2]; 3705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return new_tid; 3725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 3735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 3755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function initializes the WMM state information and the 3765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * WMM data path queues. 3775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 3785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaovoid 3795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_init(struct mwifiex_adapter *adapter) 3805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 3815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int i, j; 3825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_private *priv; 3835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (j = 0; j < adapter->priv_num; ++j) { 3855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv = adapter->priv[j]; 3865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!priv) 3875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao continue; 3885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (i = 0; i < MAX_NUM_TID; ++i) { 3905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->aggr_prio_tbl[i].amsdu = tos_to_tid_inv[i]; 3915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->aggr_prio_tbl[i].ampdu_ap = tos_to_tid_inv[i]; 3925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i]; 3935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.tid_tbl_ptr[i].ra_list_curr = NULL; 3945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 3955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 3965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->aggr_prio_tbl[6].amsdu 3975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao = priv->aggr_prio_tbl[6].ampdu_ap 3985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao = priv->aggr_prio_tbl[6].ampdu_user 3995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao = BA_STREAM_NOT_ALLOWED; 4005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->aggr_prio_tbl[7].amsdu = priv->aggr_prio_tbl[7].ampdu_ap 4025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao = priv->aggr_prio_tbl[7].ampdu_user 4035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao = BA_STREAM_NOT_ALLOWED; 4045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; 4065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE; 4075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE; 408f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang 409f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang atomic_set(&priv->wmm.tx_pkts_queued, 0); 41049729ff616547d7abcb96924d14aa860320e7352Marc Yang atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); 4115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 4125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 4135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 4155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function checks if WMM Tx queue is empty. 4165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 4175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaoint 4185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) 4195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 420f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang int i; 4215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_private *priv; 4225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 423f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang for (i = 0; i < adapter->priv_num; ++i) { 424f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang priv = adapter->priv[i]; 425f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang if (priv && atomic_read(&priv->wmm.tx_pkts_queued)) 426f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang return false; 4275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 4285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return true; 4305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 4315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 4335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function deletes all packets in an RA list node. 4345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 4355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * The packet sent completion callback handler are called with 4365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * status failure, after they are dequeued to ensure proper 4375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * cleanup. The RA list node itself is freed at the end. 4385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 4395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void 4405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_del_pkts_in_ralist_node(struct mwifiex_private *priv, 4415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ra_list) 4425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 4435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_adapter *adapter = priv->adapter; 4445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct sk_buff *skb, *tmp; 4455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) 4475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_write_data_complete(adapter, skb, -1); 4485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 4495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 4515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function deletes all packets in an RA list. 4525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 4535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Each nodes in the RA list are freed individually first, and then 4545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * the RA list itself is freed. 4555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 4565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void 4575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_del_pkts_in_ralist(struct mwifiex_private *priv, 4585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct list_head *ra_list_head) 4595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 4605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ra_list; 4615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_for_each_entry(ra_list, ra_list_head, list) 4635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_wmm_del_pkts_in_ralist_node(priv, ra_list); 4645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 4655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 4675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function deletes all packets in all RA lists. 4685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 4695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void mwifiex_wmm_cleanup_queues(struct mwifiex_private *priv) 4705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 4715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int i; 4725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (i = 0; i < MAX_NUM_TID; i++) 4745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_wmm_del_pkts_in_ralist(priv, &priv->wmm.tid_tbl_ptr[i]. 4755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list); 476f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang 477f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang atomic_set(&priv->wmm.tx_pkts_queued, 0); 47849729ff616547d7abcb96924d14aa860320e7352Marc Yang atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); 4795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 4805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 4825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function deletes all route addresses from all RA lists. 4835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 4845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void mwifiex_wmm_delete_all_ralist(struct mwifiex_private *priv) 4855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 4865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ra_list, *tmp_node; 4875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int i; 4885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (i = 0; i < MAX_NUM_TID; ++i) { 4905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, 4915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao "info: ra_list: freeing buf for tid %d\n", i); 4925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_for_each_entry_safe(ra_list, tmp_node, 4935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &priv->wmm.tid_tbl_ptr[i].ra_list, list) { 4945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_del(&ra_list->list); 4955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao kfree(ra_list); 4965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 4975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 4985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[i].ra_list); 4995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.tid_tbl_ptr[i].ra_list_curr = NULL; 5015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 5025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 5035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 5055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function cleans up the Tx and Rx queues. 5065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 5075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Cleanup includes - 5085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * - All packets in RA lists 5095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * - All entries in Rx reorder table 5105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * - All entries in Tx BA stream table 5115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * - MPA buffer (if required) 5125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * - All RA lists 5135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 5145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaovoid 5155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_clean_txrx(struct mwifiex_private *priv) 5165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 5175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao unsigned long flags; 5185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_11n_cleanup_reorder_tbl(priv); 5205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); 5215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_wmm_cleanup_queues(priv); 5235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_11n_delete_all_tx_ba_stream_tbl(priv); 5245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (priv->adapter->if_ops.cleanup_mpa_buf) 5265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->adapter->if_ops.cleanup_mpa_buf(priv->adapter); 5275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_wmm_delete_all_ralist(priv); 5295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao memcpy(tos_to_tid, ac_to_tid, sizeof(tos_to_tid)); 5305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); 5325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 5335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 5355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function retrieves a particular RA list node, matching with the 5365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * given TID and RA address. 5375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 5385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic struct mwifiex_ra_list_tbl * 5395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, 5405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u8 *ra_addr) 5415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 5425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ra_list; 5435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_for_each_entry(ra_list, &priv->wmm.tid_tbl_ptr[tid].ra_list, 5455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list) { 5465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!memcmp(ra_list->ra, ra_addr, ETH_ALEN)) 5475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return ra_list; 5485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 5495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return NULL; 5515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 5525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 5545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function retrieves an RA list node for a given TID and 5555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * RA address pair. 5565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 5575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * If no such node is found, a new node is added first and then 5585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * retrieved. 5595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 5605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic struct mwifiex_ra_list_tbl * 5615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr) 5625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 5635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ra_list; 5645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list = mwifiex_wmm_get_ralist_node(priv, tid, ra_addr); 5665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (ra_list) 5675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return ra_list; 5685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_ralist_add(priv, ra_addr); 5695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return mwifiex_wmm_get_ralist_node(priv, tid, ra_addr); 5715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 5725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 5745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function checks if a particular RA list node exists in a given TID 5755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * table index. 5765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 5775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaoint 5785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_is_ralist_valid(struct mwifiex_private *priv, 5795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ra_list, int ptr_index) 5805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 5815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *rlist; 5825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_for_each_entry(rlist, &priv->wmm.tid_tbl_ptr[ptr_index].ra_list, 5845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list) { 5855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (rlist == ra_list) 5865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return true; 5875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 5885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return false; 5905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 5915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 5925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 5935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function adds a packet to WMM queue. 5945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 5955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * In disconnected state the packet is immediately dropped and the 5965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * packet send completion callback is called with status failure. 5975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 5985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Otherwise, the correct RA list node is located and the packet 5995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * is queued at the list tail. 6005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 6015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaovoid 6025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter, 6035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct sk_buff *skb) 6045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 6055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); 6065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_private *priv = adapter->priv[tx_info->bss_index]; 6075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u32 tid; 6085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ra_list; 6095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u8 ra[ETH_ALEN], tid_down; 6105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao unsigned long flags; 6115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!priv->media_connected) { 6135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(adapter->dev, "data: drop packet in disconnect\n"); 6145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_write_data_complete(adapter, skb, -1); 6155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return; 6165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 6175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tid = skb->priority; 6195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); 6215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tid_down = mwifiex_wmm_downgrade_tid(priv, tid); 6235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* In case of infra as we have already created the list during 6255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao association we just don't have to call get_queue_raptr, we will 6265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao have only 1 raptr for a tid in case of infra */ 6275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!mwifiex_queuing_ra_based(priv)) { 6285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!list_empty(&priv->wmm.tid_tbl_ptr[tid_down].ra_list)) 6295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list = list_first_entry( 6305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &priv->wmm.tid_tbl_ptr[tid_down].ra_list, 6315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl, list); 6325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao else 6335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list = NULL; 6345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } else { 6355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao memcpy(ra, skb->data, ETH_ALEN); 6364e3c44207f90500f65a3858d344b4ff3c63ea765Amitkumar Karwar if (ra[0] & 0x01) 6374e3c44207f90500f65a3858d344b4ff3c63ea765Amitkumar Karwar memset(ra, 0xff, ETH_ALEN); 6385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, ra); 6395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 6405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!ra_list) { 6425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); 6435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_write_data_complete(adapter, skb, -1); 6445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return; 6455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 6465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_queue_tail(&ra_list->skb_head, skb); 6485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list->total_pkts_size += skb->len; 6505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 651f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang atomic_inc(&priv->wmm.tx_pkts_queued); 652f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang 65349729ff616547d7abcb96924d14aa860320e7352Marc Yang if (atomic_read(&priv->wmm.highest_queued_prio) < 65449729ff616547d7abcb96924d14aa860320e7352Marc Yang tos_to_tid_inv[tid_down]) 65549729ff616547d7abcb96924d14aa860320e7352Marc Yang atomic_set(&priv->wmm.highest_queued_prio, 65649729ff616547d7abcb96924d14aa860320e7352Marc Yang tos_to_tid_inv[tid_down]); 65749729ff616547d7abcb96924d14aa860320e7352Marc Yang 6585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); 6595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 6605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 6625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function processes the get WMM status command response from firmware. 6635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 6645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * The response may contain multiple TLVs - 6655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * - AC Queue status TLVs 6665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * - Current WMM Parameter IE TLV 6675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * - Admission Control action frame TLVs 6685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 6695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function parses the TLVs and then calls further specific functions 6705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * to process any changes in the queue prioritize or state. 6715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 6725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaoint mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, 6735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao const struct host_cmd_ds_command *resp) 6745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 6755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u8 *curr = (u8 *) &resp->params.get_wmm_status; 6765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao uint16_t resp_len = le16_to_cpu(resp->size), tlv_len; 6775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int valid = true; 6785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ie_types_data *tlv_hdr; 6805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ie_types_wmm_queue_status *tlv_wmm_qstatus; 6815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct ieee_types_wmm_parameter *wmm_param_ie = NULL; 6825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_wmm_ac_status *ac_status; 6835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, "info: WMM: WMM_GET_STATUS cmdresp received: %d\n", 6855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao resp_len); 6865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao while ((resp_len >= sizeof(tlv_hdr->header)) && valid) { 6885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tlv_hdr = (struct mwifiex_ie_types_data *) curr; 6895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tlv_len = le16_to_cpu(tlv_hdr->header.len); 6905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 6915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao switch (le16_to_cpu(tlv_hdr->header.type)) { 6925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao case TLV_TYPE_WMMQSTATUS: 6935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tlv_wmm_qstatus = 6945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (struct mwifiex_ie_types_wmm_queue_status *) 6955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tlv_hdr; 6965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, 6975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao "info: CMD_RESP: WMM_GET_STATUS:" 6985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao " QSTATUS TLV: %d, %d, %d\n", 6995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tlv_wmm_qstatus->queue_index, 7005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tlv_wmm_qstatus->flow_required, 7015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tlv_wmm_qstatus->disabled); 7025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_status = &priv->wmm.ac_status[tlv_wmm_qstatus-> 7045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao queue_index]; 7055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_status->disabled = tlv_wmm_qstatus->disabled; 7065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_status->flow_required = 7075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tlv_wmm_qstatus->flow_required; 7085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ac_status->flow_created = tlv_wmm_qstatus->flow_created; 7095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 7105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao case WLAN_EID_VENDOR_SPECIFIC: 7125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* 7135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Point the regular IEEE IE 2 bytes into the Marvell IE 7145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * and setup the IEEE IE type and length byte fields 7155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 7165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_param_ie = 7185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (struct ieee_types_wmm_parameter *) (curr + 7195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 2); 7205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_param_ie->vend_hdr.len = (u8) tlv_len; 7215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_param_ie->vend_hdr.element_id = 7225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao WLAN_EID_VENDOR_SPECIFIC; 7235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, 7255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao "info: CMD_RESP: WMM_GET_STATUS:" 7265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao " WMM Parameter Set Count: %d\n", 7275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_param_ie->qos_info_bitmap & 7285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK); 7295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao memcpy((u8 *) &priv->curr_bss_params.bss_descriptor. 7315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_ie, wmm_param_ie, 7325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_param_ie->vend_hdr.len + 2); 7335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 7355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao default: 7375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao valid = false; 7385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 7395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 7405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao curr += (tlv_len + sizeof(tlv_hdr->header)); 7425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao resp_len -= (tlv_len + sizeof(tlv_hdr->header)); 7435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 7445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie); 7465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_wmm_setup_ac_downgrade(priv); 7475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return 0; 7495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 7505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 7525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Callback handler from the command module to allow insertion of a WMM TLV. 7535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 7545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * If the BSS we are associating to supports WMM, this function adds the 7555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * required WMM Information IE to the association request command buffer in 7565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * the form of a Marvell extended IEEE IE. 7575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 7585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaou32 7595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_process_association_req(struct mwifiex_private *priv, 7605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u8 **assoc_buf, 7615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct ieee_types_wmm_parameter *wmm_ie, 7625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct ieee80211_ht_cap *ht_cap) 7635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 7645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ie_types_wmm_param_set *wmm_tlv; 7655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u32 ret_len = 0; 7665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Null checks */ 7685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!assoc_buf) 7695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return 0; 7705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!(*assoc_buf)) 7715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return 0; 7725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!wmm_ie) 7745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return 0; 7755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, "info: WMM: process assoc req:" 7775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao "bss->wmmIe=0x%x\n", 7785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_ie->vend_hdr.element_id); 7795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if ((priv->wmm_required 7815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao || (ht_cap && (priv->adapter->config_bands & BAND_GN 7825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao || priv->adapter->config_bands & BAND_AN)) 7835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ) 7845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao && wmm_ie->vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) { 7855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_tlv = (struct mwifiex_ie_types_wmm_param_set *) *assoc_buf; 7865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_tlv->header.type = cpu_to_le16((u16) wmm_info_ie[0]); 7875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao wmm_tlv->header.len = cpu_to_le16((u16) wmm_info_ie[1]); 7885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao memcpy(wmm_tlv->wmm_ie, &wmm_info_ie[2], 7895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao le16_to_cpu(wmm_tlv->header.len)); 7905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (wmm_ie->qos_info_bitmap & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) 7915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao memcpy((u8 *) (wmm_tlv->wmm_ie 7925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao + le16_to_cpu(wmm_tlv->header.len) 7935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao - sizeof(priv->wmm_qosinfo)), 7945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &priv->wmm_qosinfo, 7955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao sizeof(priv->wmm_qosinfo)); 7965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 7975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ret_len = sizeof(wmm_tlv->header) 7985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao + le16_to_cpu(wmm_tlv->header.len); 7995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *assoc_buf += ret_len; 8015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 8025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return ret_len; 8045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 8055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 8075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function computes the time delay in the driver queues for a 8085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * given packet. 8095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 8105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * When the packet is received at the OS/Driver interface, the current 8115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * time is set in the packet structure. The difference between the present 8125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * time and that received time is computed in this function and limited 8135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * based on pre-compiled limits in the driver. 8145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 8155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaou8 8165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv, 8175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao const struct sk_buff *skb) 8185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 819270e58e8898c8be40451ebee45b6c9b5bd5db04bYogesh Ashok Powar u8 ret_val; 8205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct timeval out_tstamp, in_tstamp; 8215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u32 queue_delay; 8225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao do_gettimeofday(&out_tstamp); 8245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao in_tstamp = ktime_to_timeval(skb->tstamp); 8255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao queue_delay = (out_tstamp.tv_sec - in_tstamp.tv_sec) * 1000; 8275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao queue_delay += (out_tstamp.tv_usec - in_tstamp.tv_usec) / 1000; 8285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* 8305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Queue delay is passed as a uint8 in units of 2ms (ms shifted 8315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * by 1). Min value (other than 0) is therefore 2ms, max is 510ms. 8325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * 8335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Pass max value if queue_delay is beyond the uint8 range 8345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 8355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ret_val = (u8) (min(queue_delay, priv->wmm.drv_pkt_delay_max) >> 1); 8365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(priv->adapter->dev, "data: WMM: Pkt Delay: %d ms," 8385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao " %d ms sent to FW\n", queue_delay, ret_val); 8395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return ret_val; 8415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 8425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 8445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function retrieves the highest priority RA list table pointer. 8455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 8465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic struct mwifiex_ra_list_tbl * 8475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, 8485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_private **priv, int *tid) 8495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 8505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_private *priv_tmp; 8515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ptr, *head; 8525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_bss_prio_node *bssprio_node, *bssprio_head; 8535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_tid_tbl *tid_ptr; 8545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int is_list_empty; 8555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao unsigned long flags; 8565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int i, j; 8575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao for (j = adapter->priv_num - 1; j >= 0; --j) { 8595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock, 8605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao flags); 8615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao is_list_empty = list_empty(&adapter->bss_prio_tbl[j] 8625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao .bss_prio_head); 8635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock, 8645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao flags); 8655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (is_list_empty) 8665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao continue; 8675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (adapter->bss_prio_tbl[j].bss_prio_cur == 8695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (struct mwifiex_bss_prio_node *) 8705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &adapter->bss_prio_tbl[j].bss_prio_head) { 8715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao bssprio_node = 8725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_first_entry(&adapter->bss_prio_tbl[j] 8735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao .bss_prio_head, 8745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_bss_prio_node, 8755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list); 8765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao bssprio_head = bssprio_node; 8775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } else { 8785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao bssprio_node = adapter->bss_prio_tbl[j].bss_prio_cur; 8795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao bssprio_head = bssprio_node; 8805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 8815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao do { 88349729ff616547d7abcb96924d14aa860320e7352Marc Yang atomic_t *hqp; 88449729ff616547d7abcb96924d14aa860320e7352Marc Yang spinlock_t *lock; 88549729ff616547d7abcb96924d14aa860320e7352Marc Yang 8865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv_tmp = bssprio_node->priv; 88749729ff616547d7abcb96924d14aa860320e7352Marc Yang hqp = &priv_tmp->wmm.highest_queued_prio; 88849729ff616547d7abcb96924d14aa860320e7352Marc Yang lock = &priv_tmp->wmm.ra_list_spinlock; 8895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 89049729ff616547d7abcb96924d14aa860320e7352Marc Yang for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) { 8915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tid_ptr = &(priv_tmp)->wmm. 8935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tid_tbl_ptr[tos_to_tid[i]]; 8945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 8955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&tid_ptr->tid_tbl_lock, 8965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao flags); 8975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao is_list_empty = 8985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_empty(&adapter->bss_prio_tbl[j] 8995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao .bss_prio_head); 9005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&tid_ptr->tid_tbl_lock, 9015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao flags); 9025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (is_list_empty) 9035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao continue; 9045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* 9065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * Always choose the next ra we transmitted 9075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * last time, this way we pick the ra's in 9085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * round robin fashion. 9095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 9105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr = list_first_entry( 9115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &tid_ptr->ra_list_curr->list, 9125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl, 9135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list); 9145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao head = ptr; 9165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (ptr == (struct mwifiex_ra_list_tbl *) 9175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &tid_ptr->ra_list) { 9185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Get next ra */ 9195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr = list_first_entry(&ptr->list, 9205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl, list); 9215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao head = ptr; 9225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 9235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao do { 9255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao is_list_empty = 9265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_queue_empty(&ptr->skb_head); 9275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!is_list_empty) { 92849729ff616547d7abcb96924d14aa860320e7352Marc Yang spin_lock_irqsave(lock, flags); 92949729ff616547d7abcb96924d14aa860320e7352Marc Yang if (atomic_read(hqp) > i) 93049729ff616547d7abcb96924d14aa860320e7352Marc Yang atomic_set(hqp, i); 93149729ff616547d7abcb96924d14aa860320e7352Marc Yang spin_unlock_irqrestore(lock, 93249729ff616547d7abcb96924d14aa860320e7352Marc Yang flags); 9335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *priv = priv_tmp; 9345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao *tid = tos_to_tid[i]; 9355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return ptr; 9365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 9375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Get next ra */ 9385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr = list_first_entry(&ptr->list, 9395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl, 9405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list); 9415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (ptr == 9425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (struct mwifiex_ra_list_tbl *) 9435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &tid_ptr->ra_list) 9445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr = list_first_entry( 9455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &ptr->list, 9465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl, 9475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list); 9485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } while (ptr != head); 9495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 9505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 95117e8cec87586c26b953c6541c8a045e906ea046cMarc Yang /* No packet at any TID for this priv. Mark as such 95217e8cec87586c26b953c6541c8a045e906ea046cMarc Yang * to skip checking TIDs for this priv (until pkt is 95317e8cec87586c26b953c6541c8a045e906ea046cMarc Yang * added). 95417e8cec87586c26b953c6541c8a045e906ea046cMarc Yang */ 95517e8cec87586c26b953c6541c8a045e906ea046cMarc Yang atomic_set(hqp, NO_PKT_PRIO_TID); 95617e8cec87586c26b953c6541c8a045e906ea046cMarc Yang 9575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Get next bss priority node */ 9585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao bssprio_node = list_first_entry(&bssprio_node->list, 9595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_bss_prio_node, 9605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list); 9615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (bssprio_node == 9635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao (struct mwifiex_bss_prio_node *) 9645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &adapter->bss_prio_tbl[j].bss_prio_head) 9655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Get next bss priority node */ 9665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao bssprio_node = list_first_entry( 9675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &bssprio_node->list, 9685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_bss_prio_node, 9695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list); 9705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } while (bssprio_node != bssprio_head); 9715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 9725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return NULL; 9735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 9745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 9755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 976d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar * This function checks if 11n aggregation is possible. 977d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar */ 978d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwarstatic int 979d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwarmwifiex_is_11n_aggragation_possible(struct mwifiex_private *priv, 980d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar struct mwifiex_ra_list_tbl *ptr, 981d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar int max_buf_size) 982d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar{ 983d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar int count = 0, total_size = 0; 984d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar struct sk_buff *skb, *tmp; 985d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar 986d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar skb_queue_walk_safe(&ptr->skb_head, skb, tmp) { 987d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar total_size += skb->len; 988d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar if (total_size >= max_buf_size) 989d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar break; 990d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar if (++count >= MIN_NUM_AMSDU) 991d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar return true; 992d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar } 993d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar 994d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar return false; 995d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar} 996d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar 997d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar/* 9985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function sends a single packet to firmware for transmission. 9995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 10005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void 10015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_send_single_packet(struct mwifiex_private *priv, 10025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ptr, int ptr_index, 10035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao unsigned long ra_list_flags) 10045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao __releases(&priv->wmm.ra_list_spinlock) 10055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 10065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct sk_buff *skb, *skb_next; 10075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_tx_param tx_param; 10085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_adapter *adapter = priv->adapter; 10095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_txinfo *tx_info; 10105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (skb_queue_empty(&ptr->skb_head)) { 10125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 10135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list_flags); 10145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(adapter->dev, "data: nothing to send\n"); 10155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return; 10165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 10175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb = skb_dequeue(&ptr->skb_head); 10195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tx_info = MWIFIEX_SKB_TXCB(skb); 10215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(adapter->dev, "data: dequeuing the packet %p %p\n", ptr, skb); 10225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr->total_pkts_size -= skb->len; 10245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!skb_queue_empty(&ptr->skb_head)) 10265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_next = skb_peek(&ptr->skb_head); 10275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao else 10285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_next = NULL; 10295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); 10315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tx_param.next_pkt_len = ((skb_next) ? skb_next->len + 10335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao sizeof(struct txpd) : 0); 10345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1035636c4598499eeacce0893dc8d91113b904bd531eYogesh Ashok Powar if (mwifiex_process_tx(priv, skb, &tx_param) == -EBUSY) { 10365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Queue the packet back at the head */ 10375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); 10385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { 10405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 10415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list_flags); 10425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_write_data_complete(adapter, skb, -1); 10435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return; 10445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 10455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_queue_tail(&ptr->skb_head, skb); 10475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr->total_pkts_size += skb->len; 10495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; 10505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 10515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list_flags); 10525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } else { 10535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); 10545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { 10555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.packets_out[ptr_index]++; 10565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.tid_tbl_ptr[ptr_index].ra_list_curr = ptr; 10575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 10585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = 10595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_first_entry( 10605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &adapter->bss_prio_tbl[priv->bss_priority] 10615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao .bss_prio_cur->list, 10625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_bss_prio_node, 10635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list); 1064f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang atomic_dec(&priv->wmm.tx_pkts_queued); 10655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 10665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list_flags); 10675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 10685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 10695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 10715e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function checks if the first packet in the given RA list 10725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * is already processed or not. 10735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 10745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic int 10755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_is_ptr_processed(struct mwifiex_private *priv, 10765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ptr) 10775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 10785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct sk_buff *skb; 10795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_txinfo *tx_info; 10805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (skb_queue_empty(&ptr->skb_head)) 10825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return false; 10835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb = skb_peek(&ptr->skb_head); 10855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tx_info = MWIFIEX_SKB_TXCB(skb); 10875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (tx_info->flags & MWIFIEX_BUF_FLAG_REQUEUED_PKT) 10885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return true; 10895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return false; 10915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 10925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 10935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 10945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function sends a single processed packet to firmware for 10955e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * transmission. 10965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 10975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic void 10985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_send_processed_packet(struct mwifiex_private *priv, 10995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ptr, int ptr_index, 11005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao unsigned long ra_list_flags) 11015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao __releases(&priv->wmm.ra_list_spinlock) 11025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 11035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_tx_param tx_param; 11045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_adapter *adapter = priv->adapter; 11055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int ret = -1; 11065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct sk_buff *skb, *skb_next; 11075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_txinfo *tx_info; 11085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (skb_queue_empty(&ptr->skb_head)) { 11105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 11115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list_flags); 11125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return; 11135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 11145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb = skb_dequeue(&ptr->skb_head); 11165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!skb_queue_empty(&ptr->skb_head)) 11185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_next = skb_peek(&ptr->skb_head); 11195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao else 11205e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_next = NULL; 11215e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tx_info = MWIFIEX_SKB_TXCB(skb); 11235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); 11255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tx_param.next_pkt_len = 11265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ((skb_next) ? skb_next->len + 11275e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao sizeof(struct txpd) : 0); 1128d930faee141bd0a6a4873791996c5354c9a85ca7Amitkumar Karwar ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, skb, 1129d930faee141bd0a6a4873791996c5354c9a85ca7Amitkumar Karwar &tx_param); 11305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao switch (ret) { 11315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao case -EBUSY: 11325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); 11335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); 11345e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11355e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { 11365e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 11375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list_flags); 11385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_write_data_complete(adapter, skb, -1); 11395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return; 11405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 11415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao skb_queue_tail(&ptr->skb_head, skb); 11435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; 11455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 11465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list_flags); 11475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 11485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao case -1: 11495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao adapter->data_sent = false; 11505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_err(adapter->dev, "host_to_card failed: %#x\n", ret); 11515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao adapter->dbg.num_tx_host_to_card_failure++; 11525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_write_data_complete(adapter, skb, ret); 11535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 11545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao case -EINPROGRESS: 11555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao adapter->data_sent = false; 11565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao default: 11575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 11585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 11595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (ret != -EBUSY) { 11605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); 11615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { 11625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.packets_out[ptr_index]++; 11635e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao priv->wmm.tid_tbl_ptr[ptr_index].ra_list_curr = ptr; 11645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 11655e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = 11665e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list_first_entry( 11675e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao &adapter->bss_prio_tbl[priv->bss_priority] 11685e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao .bss_prio_cur->list, 11695e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_bss_prio_node, 11705e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao list); 1171f699254c7126d7df94491dfd4c3648f8ec0c0d51Marc Yang atomic_dec(&priv->wmm.tx_pkts_queued); 11725e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 11735e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ra_list_flags); 11745e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 11755e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 11765e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11775e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 11785e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function dequeues a packet from the highest priority list 11795e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * and transmits it. 11805e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 11815e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaostatic int 11825e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) 11835e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 11845e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_ra_list_tbl *ptr; 11855e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao struct mwifiex_private *priv = NULL; 11865e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int ptr_index = 0; 11875e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao u8 ra[ETH_ALEN]; 11885e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao int tid_del = 0, tid = 0; 11895e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao unsigned long flags; 11905e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11915e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr = mwifiex_wmm_get_highest_priolist_ptr(adapter, &priv, &ptr_index); 11925e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!ptr) 11935e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return -1; 11945e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 1195572e8f3ead47ad223fb428a4f1db986317e8e0ecAmitkumar Karwar tid = mwifiex_get_tid(ptr); 11965e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11975e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao dev_dbg(adapter->dev, "data: tid=%d\n", tid); 11985e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 11995e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); 12005e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { 12015e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); 12025e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return -1; 12035e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 12045e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 12055e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (mwifiex_is_ptr_processed(priv, ptr)) { 12065e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_send_processed_packet(priv, ptr, ptr_index, flags); 12075e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* ra_list_spinlock has been freed in 12085e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_send_processed_packet() */ 12095e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return 0; 12105e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 12115e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 12125e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (!ptr->is_11n_enabled || mwifiex_is_ba_stream_setup(priv, ptr, tid) 12135e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao || ((priv->sec_info.wpa_enabled 12145e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao || priv->sec_info.wpa2_enabled) && !priv->wpa_is_gtk_set) 12155e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ) { 12165e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_send_single_packet(priv, ptr, ptr_index, flags); 12175e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* ra_list_spinlock has been freed in 12185e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_send_single_packet() */ 12195e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } else { 1220572e8f3ead47ad223fb428a4f1db986317e8e0ecAmitkumar Karwar if (mwifiex_is_ampdu_allowed(priv, tid)) { 122153d7938e6a2ac6569476fc59b404e70c0537b42bBing Zhao if (mwifiex_space_avail_for_new_ba_stream(adapter)) { 12225e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_11n_create_tx_ba_stream_tbl(priv, 12235e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr->ra, tid, 12245e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao BA_STREAM_SETUP_INPROGRESS); 12255e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_send_addba(priv, tid, ptr->ra); 12265e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } else if (mwifiex_find_stream_to_delete 1227572e8f3ead47ad223fb428a4f1db986317e8e0ecAmitkumar Karwar (priv, tid, &tid_del, ra)) { 12285e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_11n_create_tx_ba_stream_tbl(priv, 12295e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr->ra, tid, 12305e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao BA_STREAM_SETUP_INPROGRESS); 12315e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_send_delba(priv, tid_del, ra, 1); 12325e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 12335e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 1234572e8f3ead47ad223fb428a4f1db986317e8e0ecAmitkumar Karwar if (mwifiex_is_amsdu_allowed(priv, tid) && 1235d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar mwifiex_is_11n_aggragation_possible(priv, ptr, 1236d85c5fe462fe3531f607fda787e9c80617e35437Amitkumar Karwar adapter->tx_buf_size)) 12375e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN, 12385e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao ptr_index, flags); 12395e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* ra_list_spinlock has been freed in 12405e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_11n_aggregate_pkt() */ 12415e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao else 12425e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_send_single_packet(priv, ptr, ptr_index, flags); 12435e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* ra_list_spinlock has been freed in 12445e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao mwifiex_send_single_packet() */ 12455e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao } 12465e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao return 0; 12475e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 12485e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 12495e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao/* 12505e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * This function transmits the highest priority packet awaiting in the 12515e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao * WMM Queues. 12525e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao */ 12535e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaovoid 12545e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhaomwifiex_wmm_process_tx(struct mwifiex_adapter *adapter) 12555e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao{ 12565e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao do { 12575e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao /* Check if busy */ 12585e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (adapter->data_sent || adapter->tx_lock_flag) 12595e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 12605e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao 12615e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao if (mwifiex_dequeue_tx_packet(adapter)) 12625e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao break; 126393968147874508e6dd534af1e236a7353269da3fMarc Yang } while (!mwifiex_wmm_lists_empty(adapter)); 12645e6e3a92b9a4c9416b17f468fa5c7fa2233b8b4eBing Zhao} 1265