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