18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * NXP Wireless LAN device driver: 802.11n 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright 2011-2020 NXP 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * This software file (the "File") is distributed by NXP 78c2ecf20Sopenharmony_ci * under the terms of the GNU General Public License Version 2, June 1991 88c2ecf20Sopenharmony_ci * (the "License"). You may use, redistribute and/or modify this File in 98c2ecf20Sopenharmony_ci * accordance with the terms and conditions of the License, a copy of which 108c2ecf20Sopenharmony_ci * is available by writing to the Free Software Foundation, Inc., 118c2ecf20Sopenharmony_ci * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 128c2ecf20Sopenharmony_ci * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 158c2ecf20Sopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 168c2ecf20Sopenharmony_ci * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 178c2ecf20Sopenharmony_ci * this warranty disclaimer. 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#ifndef _MWIFIEX_11N_H_ 218c2ecf20Sopenharmony_ci#define _MWIFIEX_11N_H_ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include "11n_aggr.h" 248c2ecf20Sopenharmony_ci#include "11n_rxreorder.h" 258c2ecf20Sopenharmony_ci#include "wmm.h" 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ciint mwifiex_ret_11n_delba(struct mwifiex_private *priv, 288c2ecf20Sopenharmony_ci struct host_cmd_ds_command *resp); 298c2ecf20Sopenharmony_ciint mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, 308c2ecf20Sopenharmony_ci struct host_cmd_ds_command *resp); 318c2ecf20Sopenharmony_ciint mwifiex_cmd_11n_cfg(struct mwifiex_private *priv, 328c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, u16 cmd_action, 338c2ecf20Sopenharmony_ci struct mwifiex_ds_11n_tx_cfg *txcfg); 348c2ecf20Sopenharmony_ciint mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, 358c2ecf20Sopenharmony_ci struct mwifiex_bssdescriptor *bss_desc, 368c2ecf20Sopenharmony_ci u8 **buffer); 378c2ecf20Sopenharmony_ciint mwifiex_fill_cap_info(struct mwifiex_private *, u8 radio_type, 388c2ecf20Sopenharmony_ci struct ieee80211_ht_cap *); 398c2ecf20Sopenharmony_ciint mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv, 408c2ecf20Sopenharmony_ci u16 action, int *htcap_cfg); 418c2ecf20Sopenharmony_civoid mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv, 428c2ecf20Sopenharmony_ci struct mwifiex_tx_ba_stream_tbl 438c2ecf20Sopenharmony_ci *tx_tbl); 448c2ecf20Sopenharmony_civoid mwifiex_11n_delete_all_tx_ba_stream_tbl(struct mwifiex_private *priv); 458c2ecf20Sopenharmony_cistruct mwifiex_tx_ba_stream_tbl *mwifiex_get_ba_tbl(struct 468c2ecf20Sopenharmony_ci mwifiex_private 478c2ecf20Sopenharmony_ci *priv, int tid, 488c2ecf20Sopenharmony_ci u8 *ra); 498c2ecf20Sopenharmony_civoid mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid, 508c2ecf20Sopenharmony_ci enum mwifiex_ba_status ba_status); 518c2ecf20Sopenharmony_ciint mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac); 528c2ecf20Sopenharmony_ciint mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac, 538c2ecf20Sopenharmony_ci int initiator); 548c2ecf20Sopenharmony_civoid mwifiex_11n_delete_ba_stream(struct mwifiex_private *priv, u8 *del_ba); 558c2ecf20Sopenharmony_ciint mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv, 568c2ecf20Sopenharmony_ci struct mwifiex_ds_rx_reorder_tbl *buf); 578c2ecf20Sopenharmony_ciint mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv, 588c2ecf20Sopenharmony_ci struct mwifiex_ds_tx_ba_stream_tbl *buf); 598c2ecf20Sopenharmony_ciint mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv, 608c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 618c2ecf20Sopenharmony_ci int cmd_action, u16 *buf_size); 628c2ecf20Sopenharmony_ciint mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, 638c2ecf20Sopenharmony_ci int cmd_action, 648c2ecf20Sopenharmony_ci struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl); 658c2ecf20Sopenharmony_civoid mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra); 668c2ecf20Sopenharmony_ciu8 mwifiex_get_sec_chan_offset(int chan); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic inline u8 698c2ecf20Sopenharmony_cimwifiex_is_station_ampdu_allowed(struct mwifiex_private *priv, 708c2ecf20Sopenharmony_ci struct mwifiex_ra_list_tbl *ptr, int tid) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ptr->ra); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci if (unlikely(!node)) 758c2ecf20Sopenharmony_ci return false; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci return (node->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ? true : false; 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci/* This function checks whether AMPDU is allowed or not for a particular TID. */ 818c2ecf20Sopenharmony_cistatic inline u8 828c2ecf20Sopenharmony_cimwifiex_is_ampdu_allowed(struct mwifiex_private *priv, 838c2ecf20Sopenharmony_ci struct mwifiex_ra_list_tbl *ptr, int tid) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci if (is_broadcast_ether_addr(ptr->ra)) 868c2ecf20Sopenharmony_ci return false; 878c2ecf20Sopenharmony_ci if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { 888c2ecf20Sopenharmony_ci return mwifiex_is_station_ampdu_allowed(priv, ptr, tid); 898c2ecf20Sopenharmony_ci } else { 908c2ecf20Sopenharmony_ci if (ptr->tdls_link) 918c2ecf20Sopenharmony_ci return mwifiex_is_station_ampdu_allowed(priv, ptr, tid); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci return (priv->aggr_prio_tbl[tid].ampdu_ap != 948c2ecf20Sopenharmony_ci BA_STREAM_NOT_ALLOWED) ? true : false; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci/* 998c2ecf20Sopenharmony_ci * This function checks whether AMSDU is allowed or not for a particular TID. 1008c2ecf20Sopenharmony_ci */ 1018c2ecf20Sopenharmony_cistatic inline u8 1028c2ecf20Sopenharmony_cimwifiex_is_amsdu_allowed(struct mwifiex_private *priv, int tid) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci return (((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED) && 1058c2ecf20Sopenharmony_ci (priv->is_data_rate_auto || !(priv->bitmap_rates[2] & 0x03))) 1068c2ecf20Sopenharmony_ci ? true : false); 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci/* 1108c2ecf20Sopenharmony_ci * This function checks whether a space is available for new BA stream or not. 1118c2ecf20Sopenharmony_ci */ 1128c2ecf20Sopenharmony_cistatic inline u8 mwifiex_space_avail_for_new_ba_stream( 1138c2ecf20Sopenharmony_ci struct mwifiex_adapter *adapter) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci struct mwifiex_private *priv; 1168c2ecf20Sopenharmony_ci u8 i; 1178c2ecf20Sopenharmony_ci u32 ba_stream_num = 0, ba_stream_max; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci ba_stream_max = MWIFIEX_MAX_TX_BASTREAM_SUPPORTED; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci for (i = 0; i < adapter->priv_num; i++) { 1228c2ecf20Sopenharmony_ci priv = adapter->priv[i]; 1238c2ecf20Sopenharmony_ci if (priv) 1248c2ecf20Sopenharmony_ci ba_stream_num += mwifiex_wmm_list_len( 1258c2ecf20Sopenharmony_ci &priv->tx_ba_stream_tbl_ptr); 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci if (adapter->fw_api_ver == MWIFIEX_FW_V15) { 1298c2ecf20Sopenharmony_ci ba_stream_max = 1308c2ecf20Sopenharmony_ci GETSUPP_TXBASTREAMS(adapter->hw_dot_11n_dev_cap); 1318c2ecf20Sopenharmony_ci if (!ba_stream_max) 1328c2ecf20Sopenharmony_ci ba_stream_max = MWIFIEX_MAX_TX_BASTREAM_SUPPORTED; 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci return ((ba_stream_num < ba_stream_max) ? true : false); 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci/* 1398c2ecf20Sopenharmony_ci * This function finds the correct Tx BA stream to delete. 1408c2ecf20Sopenharmony_ci * 1418c2ecf20Sopenharmony_ci * Upon successfully locating, both the TID and the RA are returned. 1428c2ecf20Sopenharmony_ci */ 1438c2ecf20Sopenharmony_cistatic inline u8 1448c2ecf20Sopenharmony_cimwifiex_find_stream_to_delete(struct mwifiex_private *priv, int ptr_tid, 1458c2ecf20Sopenharmony_ci int *ptid, u8 *ra) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci int tid; 1488c2ecf20Sopenharmony_ci u8 ret = false; 1498c2ecf20Sopenharmony_ci struct mwifiex_tx_ba_stream_tbl *tx_tbl; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci tid = priv->aggr_prio_tbl[ptr_tid].ampdu_user; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci spin_lock_bh(&priv->tx_ba_stream_tbl_lock); 1548c2ecf20Sopenharmony_ci list_for_each_entry(tx_tbl, &priv->tx_ba_stream_tbl_ptr, list) { 1558c2ecf20Sopenharmony_ci if (tid > priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user) { 1568c2ecf20Sopenharmony_ci tid = priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user; 1578c2ecf20Sopenharmony_ci *ptid = tx_tbl->tid; 1588c2ecf20Sopenharmony_ci memcpy(ra, tx_tbl->ra, ETH_ALEN); 1598c2ecf20Sopenharmony_ci ret = true; 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci spin_unlock_bh(&priv->tx_ba_stream_tbl_lock); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci return ret; 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci/* 1688c2ecf20Sopenharmony_ci * This function checks whether associated station is 11n enabled 1698c2ecf20Sopenharmony_ci */ 1708c2ecf20Sopenharmony_cistatic inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv, 1718c2ecf20Sopenharmony_ci struct mwifiex_sta_node *node) 1728c2ecf20Sopenharmony_ci{ 1738c2ecf20Sopenharmony_ci if (!node || ((priv->bss_role == MWIFIEX_BSS_ROLE_UAP) && 1748c2ecf20Sopenharmony_ci !priv->ap_11n_enabled) || 1758c2ecf20Sopenharmony_ci ((priv->bss_mode == NL80211_IFTYPE_ADHOC) && 1768c2ecf20Sopenharmony_ci !priv->adapter->adhoc_11n_enabled)) 1778c2ecf20Sopenharmony_ci return 0; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci return node->is_11n_enabled; 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic inline u8 1838c2ecf20Sopenharmony_cimwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, const u8 *ra) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ra); 1868c2ecf20Sopenharmony_ci if (node) 1878c2ecf20Sopenharmony_ci return node->is_11n_enabled; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci return false; 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_ci#endif /* !_MWIFIEX_11N_H_ */ 192