1 /** @file mlan_11n.h
2 *
3 * @brief Interface for the 802.11n mlan_11n module implemented in mlan_11n.c
4 *
5 * Driver interface functions and type declarations for the 11n module
6 * implemented in mlan_11n.c.
7 *
8 *
9 * Copyright 2008-2021 NXP
10 *
11 * This software file (the File) is distributed by NXP
12 * under the terms of the GNU General Public License Version 2, June 1991
13 * (the License). You may use, redistribute and/or modify the File in
14 * accordance with the terms and conditions of the License, a copy of which
15 * is available by writing to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
17 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
18 *
19 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
21 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
22 * this warranty disclaimer.
23 *
24 */
25
26 /********************************************************
27 Change log:
28 12/01/2008: initial version
29 ********************************************************/
30
31 #ifndef _MLAN_11N_H_
32 #define _MLAN_11N_H_
33
34 #include "mlan_11n_aggr.h"
35 #include "mlan_11n_rxreorder.h"
36 #include "mlan_wmm.h"
37
38 /** Print the 802.11n device capability */
39 void wlan_show_dot11ndevcap(pmlan_adapter pmadapter, t_u32 cap);
40 /** Print the 802.11n device MCS */
41 void wlan_show_devmcssupport(pmlan_adapter pmadapter, t_u8 support);
42 /** Handle the command response of a delete block ack request */
43 mlan_status wlan_ret_11n_delba(mlan_private *priv, HostCmd_DS_COMMAND *resp);
44 /** Handle the command response of an add block ack request */
45 mlan_status wlan_ret_11n_addba_req(mlan_private *priv,
46 HostCmd_DS_COMMAND *resp);
47 /** Handle the command response of 11ncfg command */
48 mlan_status wlan_ret_11n_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
49 mlan_ioctl_req *pioctl_buf);
50 /** Prepare 11ncfg command */
51 mlan_status wlan_cmd_11n_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
52 t_u16 cmd_action, t_void *pdata_buf);
53 /** Prepare reject addba requst command */
54 mlan_status wlan_cmd_reject_addba_req(pmlan_private pmpriv,
55 HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
56 t_void *pdata_buf);
57 /** Handle the command response of rejecting addba request */
58 mlan_status wlan_ret_reject_addba_req(pmlan_private pmpriv,
59 HostCmd_DS_COMMAND *resp,
60 mlan_ioctl_req *pioctl_buf);
61 /** Prepare TX BF configuration command */
62 mlan_status wlan_cmd_tx_bf_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
63 t_u16 cmd_action, t_void *pdata_buf);
64 /** Handle the command response TX BF configuration */
65 mlan_status wlan_ret_tx_bf_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
66 mlan_ioctl_req *pioctl_buf);
67 #ifdef STA_SUPPORT
68 t_u8 wlan_11n_bandconfig_allowed(mlan_private *pmpriv, t_u16 bss_band);
69 /** Append the 802_11N tlv */
70 int wlan_cmd_append_11n_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc,
71 t_u8 **ppbuffer);
72 /** wlan fill HT cap tlv */
73 void wlan_fill_ht_cap_tlv(mlan_private *priv, MrvlIETypes_HTCap_t *pht_cap,
74 t_u16 band, t_u8 fill);
75 /** wlan fill HT cap IE */
76 void wlan_fill_ht_cap_ie(mlan_private *priv, IEEEtypes_HTCap_t *pht_cap,
77 t_u16 bands);
78 #endif /* STA_SUPPORT */
79 /** Miscellaneous configuration handler */
80 mlan_status wlan_11n_cfg_ioctl(pmlan_adapter pmadapter,
81 pmlan_ioctl_req pioctl_req);
82 /** Delete Tx BA stream table entry */
83 void wlan_11n_delete_txbastream_tbl_entry(mlan_private *priv,
84 TxBAStreamTbl *ptx_tbl);
85 /** Delete all Tx BA stream table entries */
86 void wlan_11n_deleteall_txbastream_tbl(mlan_private *priv);
87 /** Get Tx BA stream table */
88 TxBAStreamTbl *wlan_11n_get_txbastream_tbl(mlan_private *priv, int tid,
89 t_u8 *ra, int lock);
90 /** Create Tx BA stream table */
91 void wlan_11n_create_txbastream_tbl(mlan_private *priv, t_u8 *ra, int tid,
92 baStatus_e ba_status);
93 /** Send ADD BA request */
94 int wlan_send_addba(mlan_private *priv, int tid, t_u8 *peer_mac);
95 /** Send DEL BA request */
96 int wlan_send_delba(mlan_private *priv, pmlan_ioctl_req pioctl_req, int tid,
97 t_u8 *peer_mac, int initiator);
98 /** This function handles the command response of delete a block ack request*/
99 void wlan_11n_delete_bastream(mlan_private *priv, t_u8 *del_ba);
100 /** get rx reorder table */
101 int wlan_get_rxreorder_tbl(mlan_private *priv, rx_reorder_tbl *buf);
102 /** get tx ba stream table */
103 int wlan_get_txbastream_tbl(mlan_private *priv, tx_ba_stream_tbl *buf);
104 /** send delba */
105 void wlan_11n_delba(mlan_private *priv, int tid);
106 /** update amdpdu tx win size */
107 void wlan_update_ampdu_txwinsize(pmlan_adapter pmadapter);
108 /** Minimum number of AMSDU */
109 #define MIN_NUM_AMSDU 2
110 /** AMSDU Aggr control cmd resp */
111 mlan_status wlan_ret_amsdu_aggr_ctrl(pmlan_private pmpriv,
112 HostCmd_DS_COMMAND *resp,
113 mlan_ioctl_req *pioctl_buf);
114 void wlan_set_tx_pause_flag(mlan_private *priv, t_u8 flag);
115 /** reconfigure tx buf size */
116 mlan_status wlan_cmd_recfg_tx_buf(mlan_private *priv, HostCmd_DS_COMMAND *cmd,
117 int cmd_action, void *pdata_buf);
118 /** AMSDU aggr control cmd */
119 mlan_status wlan_cmd_amsdu_aggr_ctrl(mlan_private *priv,
120 HostCmd_DS_COMMAND *cmd, int cmd_action,
121 void *pdata_buf);
122
123 t_u8 wlan_validate_chan_offset(mlan_private *pmpriv, t_u16 band, t_u32 chan,
124 t_u8 chan_bw);
125 /** get channel offset */
126 t_u8 wlan_get_second_channel_offset(mlan_private *priv, int chan);
127
128 void wlan_update_11n_cap(mlan_private *pmpriv);
129
130 /** clean up txbastream_tbl */
131 void wlan_11n_cleanup_txbastream_tbl(mlan_private *priv, t_u8 *ra);
132 /**
133 * @brief This function checks whether a station has 11N enabled or not
134 *
135 * @param priv A pointer to mlan_private
136 * @param mac station mac address
137 * @return MTRUE or MFALSE
138 */
is_station_11n_enabled(mlan_private * priv,t_u8 * mac)139 static INLINE t_u8 is_station_11n_enabled(mlan_private *priv, t_u8 *mac)
140 {
141 sta_node *sta_ptr = MNULL;
142 sta_ptr = wlan_get_station_entry(priv, mac);
143 if (sta_ptr)
144 return (sta_ptr->is_11n_enabled) ? MTRUE : MFALSE;
145 return MFALSE;
146 }
147
148 /**
149 * @brief This function get station max amsdu size
150 *
151 * @param priv A pointer to mlan_private
152 * @param mac station mac address
153 * @return max amsdu size statio supported
154 */
get_station_max_amsdu_size(mlan_private * priv,t_u8 * mac)155 static INLINE t_u16 get_station_max_amsdu_size(mlan_private *priv, t_u8 *mac)
156 {
157 sta_node *sta_ptr = MNULL;
158 sta_ptr = wlan_get_station_entry(priv, mac);
159 if (sta_ptr)
160 return sta_ptr->max_amsdu;
161 return 0;
162 }
163
164 /**
165 * @brief This function checks whether a station allows AMPDU or not
166 *
167 * @param priv A pointer to mlan_private
168 * @param ptr A pointer to RA list table
169 * @param tid TID value for ptr
170 * @return MTRUE or MFALSE
171 */
is_station_ampdu_allowed(mlan_private * priv,raListTbl * ptr,int tid)172 static INLINE t_u8 is_station_ampdu_allowed(mlan_private *priv, raListTbl *ptr,
173 int tid)
174 {
175 sta_node *sta_ptr = MNULL;
176 sta_ptr = wlan_get_station_entry(priv, ptr->ra);
177 if (sta_ptr) {
178 if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
179 if (priv->sec_info.wapi_enabled &&
180 !sta_ptr->wapi_key_on)
181 return MFALSE;
182 }
183 return (sta_ptr->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ?
184 MTRUE :
185 MFALSE;
186 }
187 return MFALSE;
188 }
189
190 /**
191 * @brief This function disable station ampdu for specific tid
192 *
193 * @param priv A pointer to mlan_private
194 * @param tid tid index
195 * @param ra station mac address
196 * @return N/A
197 */
disable_station_ampdu(mlan_private * priv,t_u8 tid,t_u8 * ra)198 static INLINE void disable_station_ampdu(mlan_private *priv, t_u8 tid, t_u8 *ra)
199 {
200 sta_node *sta_ptr = MNULL;
201 sta_ptr = wlan_get_station_entry(priv, ra);
202 if (sta_ptr)
203 sta_ptr->ampdu_sta[tid] = BA_STREAM_NOT_ALLOWED;
204 return;
205 }
206
207 /**
208 * @brief This function reset station ampdu for specific id to user setting.
209 *
210 * @param priv A pointer to mlan_private
211 * @param tid tid index
212 * @param ra station mac address
213 * @return N/A
214 */
reset_station_ampdu(mlan_private * priv,t_u8 tid,t_u8 * ra)215 static INLINE void reset_station_ampdu(mlan_private *priv, t_u8 tid, t_u8 *ra)
216 {
217 sta_node *sta_ptr = MNULL;
218 sta_ptr = wlan_get_station_entry(priv, ra);
219 if (sta_ptr)
220 sta_ptr->ampdu_sta[tid] = priv->aggr_prio_tbl[tid].ampdu_user;
221 return;
222 }
223
224 #define IS_BG_RATE (priv->bitmap_rates[0] || priv->bitmap_rates[1])
225 /**
226 * @brief This function checks whether AMPDU is allowed or not
227 *
228 * @param priv A pointer to mlan_private
229 * @param ptr A pointer to RA list table
230 * @param tid TID value for ptr
231 *
232 * @return MTRUE or MFALSE
233 */
wlan_is_ampdu_allowed(mlan_private * priv,raListTbl * ptr,int tid)234 static INLINE t_u8 wlan_is_ampdu_allowed(mlan_private *priv, raListTbl *ptr,
235 int tid)
236 {
237 if (ptr->is_tdls_link)
238 return is_station_ampdu_allowed(priv, ptr, tid);
239 if (priv->adapter->tdls_status != TDLS_NOT_SETUP && !priv->txaggrctrl)
240 return MFALSE;
241
242 if ((!priv->is_data_rate_auto) && IS_BG_RATE)
243 return MFALSE;
244 #ifdef UAP_SUPPORT
245 if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
246 return is_station_ampdu_allowed(priv, ptr, tid);
247 #endif /* UAP_SUPPORT */
248 if (priv->sec_info.wapi_enabled && !priv->sec_info.wapi_key_on)
249 return MFALSE;
250 return (priv->aggr_prio_tbl[tid].ampdu_ap != BA_STREAM_NOT_ALLOWED) ?
251 MTRUE :
252 MFALSE;
253 }
254
255 #define BA_RSSI_HIGH_THRESHOLD -70
256
wlan_update_station_del_ba_count(mlan_private * priv,raListTbl * ptr)257 static INLINE void wlan_update_station_del_ba_count(mlan_private *priv,
258 raListTbl *ptr)
259 {
260 sta_node *sta_ptr = MNULL;
261 t_s8 rssi;
262 sta_ptr = wlan_get_station_entry(priv, ptr->ra);
263 if (sta_ptr) {
264 rssi = sta_ptr->snr - sta_ptr->nf;
265 if (rssi > BA_RSSI_HIGH_THRESHOLD)
266 ptr->del_ba_count = 0;
267 }
268 return;
269 }
270
wlan_update_del_ba_count(mlan_private * priv,raListTbl * ptr)271 static INLINE void wlan_update_del_ba_count(mlan_private *priv, raListTbl *ptr)
272 {
273 t_s8 rssi;
274 if (ptr->is_tdls_link)
275 return wlan_update_station_del_ba_count(priv, ptr);
276 rssi = priv->snr - priv->nf;
277 if (rssi > BA_RSSI_HIGH_THRESHOLD)
278 ptr->del_ba_count = 0;
279 }
280
281 /**
282 * @brief This function checks whether AMSDU is allowed or not
283 *
284 * @param priv A pointer to mlan_private
285 * @param ptr A pointer to RA list table
286 * @param tid TID value for ptr
287 *
288 * @return MTRUE or MFALSE
289 */
wlan_is_amsdu_allowed(mlan_private * priv,raListTbl * ptr,int tid)290 static INLINE t_u8 wlan_is_amsdu_allowed(mlan_private *priv, raListTbl *ptr,
291 int tid)
292 {
293 #ifdef UAP_SUPPORT
294 sta_node *sta_ptr = MNULL;
295 #endif
296 if (priv->amsdu_disable)
297 return MFALSE;
298 #ifdef UAP_SUPPORT
299 if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
300 sta_ptr = wlan_get_station_entry(priv, ptr->ra);
301 if (sta_ptr) {
302 if (priv->sec_info.wapi_enabled &&
303 !sta_ptr->wapi_key_on)
304 return MFALSE;
305 }
306 }
307 #endif /* UAP_SUPPORT */
308 if (ptr->is_tdls_link)
309 return (priv->aggr_prio_tbl[tid].amsdu !=
310 BA_STREAM_NOT_ALLOWED) ?
311 MTRUE :
312 MFALSE;
313 #define TXRATE_BITMAP_INDEX_MCS0_7 2
314 return ((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED) &&
315 ((priv->is_data_rate_auto) ||
316 !(((priv->bitmap_rates[TXRATE_BITMAP_INDEX_MCS0_7]) & 0x03) ||
317 IS_BG_RATE))) ?
318 MTRUE :
319 MFALSE;
320 }
321
322 /**
323 * @brief This function checks whether a BA stream is available or not
324 *
325 * @param priv A pointer to mlan_private
326 *
327 * @return MTRUE or MFALSE
328 */
wlan_is_bastream_avail(mlan_private * priv)329 static INLINE t_u8 wlan_is_bastream_avail(mlan_private *priv)
330 {
331 mlan_private *pmpriv = MNULL;
332 t_u8 i = 0;
333 t_u32 bastream_num = 0;
334 t_u32 bastream_max = 0;
335 for (i = 0; i < priv->adapter->priv_num; i++) {
336 pmpriv = priv->adapter->priv[i];
337 if (pmpriv)
338 bastream_num += wlan_wmm_list_len(
339 (pmlan_list_head)&pmpriv->tx_ba_stream_tbl_ptr);
340 }
341 bastream_max = ISSUPP_GETTXBASTREAM(priv->adapter->hw_dot_11n_dev_cap);
342 if (bastream_max == 0)
343 bastream_max = MLAN_MAX_TX_BASTREAM_DEFAULT;
344 return (bastream_num < bastream_max) ? MTRUE : MFALSE;
345 }
346
347 /**
348 * @brief This function finds the stream to delete
349 *
350 * @param priv A pointer to mlan_private
351 * @param ptr A pointer to RA list table
352 * @param ptr_tid TID value of ptr
353 * @param ptid A pointer to TID of stream to delete, if return MTRUE
354 * @param ra RA of stream to delete, if return MTRUE
355 *
356 * @return MTRUE or MFALSE
357 */
wlan_find_stream_to_delete(mlan_private * priv,raListTbl * ptr,int ptr_tid,int * ptid,t_u8 * ra)358 static INLINE t_u8 wlan_find_stream_to_delete(mlan_private *priv,
359 raListTbl *ptr, int ptr_tid,
360 int *ptid, t_u8 *ra)
361 {
362 int tid;
363 t_u8 ret = MFALSE;
364 TxBAStreamTbl *ptx_tbl;
365
366 ENTER();
367
368 ptx_tbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
369 &priv->tx_ba_stream_tbl_ptr,
370 MNULL, MNULL);
371 if (!ptx_tbl) {
372 LEAVE();
373 return ret;
374 }
375
376 tid = priv->aggr_prio_tbl[ptr_tid].ampdu_user;
377
378 while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
379 if (tid > priv->aggr_prio_tbl[ptx_tbl->tid].ampdu_user) {
380 tid = priv->aggr_prio_tbl[ptx_tbl->tid].ampdu_user;
381 *ptid = ptx_tbl->tid;
382 memcpy_ext(priv->adapter, ra, ptx_tbl->ra,
383 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
384 ret = MTRUE;
385 }
386
387 ptx_tbl = ptx_tbl->pnext;
388 }
389 LEAVE();
390 return ret;
391 }
392
393 /**
394 * @brief This function checks whether 11n is supported
395 *
396 * @param priv A pointer to mlan_private
397 * @param ra Address of the receiver STA
398 *
399 * @return MTRUE or MFALSE
400 */
wlan_is_11n_enabled(mlan_private * priv,t_u8 * ra)401 static INLINE int wlan_is_11n_enabled(mlan_private *priv, t_u8 *ra)
402 {
403 int ret = MFALSE;
404 ENTER();
405 #ifdef UAP_SUPPORT
406 if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
407 if ((!(ra[0] & 0x01)) && (priv->is_11n_enabled))
408 ret = is_station_11n_enabled(priv, ra);
409 }
410 #endif /* UAP_SUPPORT */
411 LEAVE();
412 return ret;
413 }
414 #endif /* !_MLAN_11N_H_ */
415