aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwifiex/11n.h
blob: afdd58aa90deda02793601bbf534e6eb0ad9180d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*
 * Marvell Wireless LAN device driver: 802.11n
 *
 * Copyright (C) 2011-2014, Marvell International Ltd.
 *
 * This software file (the "File") is distributed by Marvell International
 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
 * (the "License").  You may use, redistribute and/or modify this File in
 * accordance with the terms and conditions of the License, a copy of which
 * is available by writing to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
 *
 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
 * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
 * this warranty disclaimer.
 */

#ifndef _MWIFIEX_11N_H_
#define _MWIFIEX_11N_H_

#include "11n_aggr.h"
#include "11n_rxreorder.h"
#include "wmm.h"

int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
			  struct host_cmd_ds_command *resp);
int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
			      struct host_cmd_ds_command *resp);
int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv,
			struct host_cmd_ds_command *cmd, u16 cmd_action,
			struct mwifiex_ds_11n_tx_cfg *txcfg);
int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
			       struct mwifiex_bssdescriptor *bss_desc,
			       u8 **buffer);
int mwifiex_fill_cap_info(struct mwifiex_private *, u8 radio_type,
			  struct ieee80211_ht_cap *);
int mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv,
				  u16 action, int *htcap_cfg);
void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv,
					     struct mwifiex_tx_ba_stream_tbl
					     *tx_tbl);
void mwifiex_11n_delete_all_tx_ba_stream_tbl(struct mwifiex_private *priv);
struct mwifiex_tx_ba_stream_tbl *mwifiex_get_ba_tbl(struct
							     mwifiex_private
							     *priv, int tid,
							     u8 *ra);
void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid,
			   enum mwifiex_ba_status ba_status);
int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac);
int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
		       int initiator);
void mwifiex_11n_delete_ba_stream(struct mwifiex_private *priv, u8 *del_ba);
int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv,
			      struct mwifiex_ds_rx_reorder_tbl *buf);
int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
			       struct mwifiex_ds_tx_ba_stream_tbl *buf);
int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
			     struct host_cmd_ds_command *cmd,
			     int cmd_action, u16 *buf_size);
int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
				int cmd_action,
				struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl);
void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra);
u8 mwifiex_get_sec_chan_offset(int chan);

static inline u8
mwifiex_is_station_ampdu_allowed(struct mwifiex_private *priv,
				 struct mwifiex_ra_list_tbl *ptr, int tid)
{
	struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ptr->ra);

	if (unlikely(!node))
		return false;

	return (node->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ? true : false;
}

/* This function checks whether AMPDU is allowed or not for a particular TID. */
static inline u8
mwifiex_is_ampdu_allowed(struct mwifiex_private *priv,
			 struct mwifiex_ra_list_tbl *ptr, int tid)
{
	if (is_broadcast_ether_addr(ptr->ra))
		return false;
	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
		return mwifiex_is_station_ampdu_allowed(priv, ptr, tid);
	} else {
		if (ptr->tdls_link)
			return mwifiex_is_station_ampdu_allowed(priv, ptr, tid);

		return (priv->aggr_prio_tbl[tid].ampdu_ap !=
			BA_STREAM_NOT_ALLOWED) ? true : false;
	}
}

/*
 * This function checks whether AMSDU is allowed or not for a particular TID.
 */
static inline u8
mwifiex_is_amsdu_allowed(struct mwifiex_private *priv, int tid)
{
	return (((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED) &&
		 (priv->is_data_rate_auto || !(priv->bitmap_rates[2] & 0x03)))
		? true : false);
}

/*
 * This function checks whether a space is available for new BA stream or not.
 */
static inline u8 mwifiex_space_avail_for_new_ba_stream(
					struct mwifiex_adapter *adapter)
{
	struct mwifiex_private *priv;
	u8 i;
	u32 ba_stream_num = 0, ba_stream_max;

	ba_stream_max = MWIFIEX_MAX_TX_BASTREAM_SUPPORTED;

	for (i = 0; i < adapter->priv_num; i++) {
		priv = adapter->priv[i];
		if (priv)
			ba_stream_num += mwifiex_wmm_list_len(
				&priv->tx_ba_stream_tbl_ptr);
	}

	if (adapter->fw_api_ver == MWIFIEX_FW_V15) {
		ba_stream_max =
			       GETSUPP_TXBASTREAMS(adapter->hw_dot_11n_dev_cap);
		if (!ba_stream_max)
			ba_stream_max = MWIFIEX_MAX_TX_BASTREAM_SUPPORTED;
	}

	return ((ba_stream_num < ba_stream_max) ? true : false);
}

/*
 * This function finds the correct Tx BA stream to delete.
 *
 * Upon successfully locating, both the TID and the RA are returned.
 */
static inline u8
mwifiex_find_stream_to_delete(struct mwifiex_private *priv, int ptr_tid,
			      int *ptid, u8 *ra)
{
	int tid;
	u8 ret = false;
	struct mwifiex_tx_ba_stream_tbl *tx_tbl;
	unsigned long flags;

	tid = priv->aggr_prio_tbl[ptr_tid].ampdu_user;

	spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
	list_for_each_entry(tx_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
		if (tid > priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user) {
			tid = priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user;
			*ptid = tx_tbl->tid;
			memcpy(ra, tx_tbl->ra, ETH_ALEN);
			ret = true;
		}
	}
	spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);

	return ret;
}

/*
 * This function checks whether associated station is 11n enabled
 */
static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv,
					     struct mwifiex_sta_node *node)
{

	if (!node || (priv->bss_role != MWIFIEX_BSS_ROLE_UAP) ||
	    !priv->ap_11n_enabled)
		return 0;

	return node->is_11n_enabled;
}

static inline u8
mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, const u8 *ra)
{
	struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ra);
	if (node)
		return node->is_11n_enabled;

	return false;
}
#endif /* !_MWIFIEX_11N_H_ */