1 /** @file mlan_11n.c
2 *
3 * @brief This file contains functions for 11n handling.
4 *
5 *
6 * Copyright 2008-2021 NXP
7 *
8 * This software file (the File) is distributed by NXP
9 * under the terms of the GNU General Public License Version 2, June 1991
10 * (the License). You may use, redistribute and/or modify the File in
11 * accordance with the terms and conditions of the License, a copy of which
12 * is available by writing to the Free Software Foundation, Inc.,
13 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15 *
16 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
19 * this warranty disclaimer.
20 *
21 */
22
23 /********************************************************
24 Change log:
25 11/10/2008: initial version
26 ********************************************************/
27
28 #include "mlan.h"
29 #include "mlan_join.h"
30 #include "mlan_util.h"
31 #include "mlan_fw.h"
32 #include "mlan_main.h"
33 #include "mlan_wmm.h"
34 #include "mlan_11n.h"
35 #include "mlan_11ac.h"
36
37 /********************************************************
38 Local Variables
39 ********************************************************/
40
41 /********************************************************
42 Global Variables
43 ********************************************************/
44
45 /********************************************************
46 Local Functions
47 ********************************************************/
48
49 /**
50 *
51 * @brief set/get max tx buf size
52 *
53 * @param pmadapter A pointer to mlan_adapter structure
54 * @param pioctl_req A pointer to ioctl request buffer
55 *
56 * @return MLAN_STATUS_SUCCESS --success, otherwise
57 * fail
58 */
wlan_11n_ioctl_max_tx_buf_size(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)59 static mlan_status wlan_11n_ioctl_max_tx_buf_size(pmlan_adapter pmadapter,
60 pmlan_ioctl_req pioctl_req)
61 {
62 mlan_status ret = MLAN_STATUS_SUCCESS;
63 mlan_ds_11n_cfg *cfg = MNULL;
64
65 ENTER();
66 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
67 cfg->param.tx_buf_size = (t_u32)pmadapter->max_tx_buf_size;
68 pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
69
70 LEAVE();
71 return ret;
72 }
73
74 /**
75 * @brief Set/get htcapinfo configuration
76 *
77 * @param pmadapter A pointer to mlan_adapter structure
78 * @param pioctl_req A pointer to ioctl request buffer
79 *
80 * @return MLAN_STATUS_SUCCESS --success, otherwise
81 * fail
82 */
wlan_11n_ioctl_htusrcfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)83 static mlan_status wlan_11n_ioctl_htusrcfg(pmlan_adapter pmadapter,
84 pmlan_ioctl_req pioctl_req)
85 {
86 mlan_status ret = MLAN_STATUS_SUCCESS;
87 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
88 mlan_ds_11n_cfg *cfg = MNULL;
89
90 ENTER();
91
92 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
93
94 if (pioctl_req->action == MLAN_ACT_SET) {
95 if (((cfg->param.htcap_cfg.htcap & ~IGN_HW_DEV_CAP) &
96 pmpriv->adapter->hw_dot_11n_dev_cap) !=
97 (cfg->param.htcap_cfg.htcap & ~IGN_HW_DEV_CAP)) {
98 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
99 ret = MLAN_STATUS_FAILURE;
100 } else {
101 if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_BG) {
102 pmpriv->usr_dot_11n_dev_cap_bg =
103 cfg->param.htcap_cfg.htcap;
104 PRINTM(MINFO,
105 "Set: UsrDot11nCap for 2.4GHz 0x%x\n",
106 pmpriv->usr_dot_11n_dev_cap_bg);
107 }
108 if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_A) {
109 pmpriv->usr_dot_11n_dev_cap_a =
110 cfg->param.htcap_cfg.htcap;
111 PRINTM(MINFO,
112 "Set: UsrDot11nCap for 5GHz 0x%x\n",
113 pmpriv->usr_dot_11n_dev_cap_a);
114 }
115 if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_BOTH) {
116 pmpriv->usr_dot_11n_dev_cap_bg =
117 cfg->param.htcap_cfg.htcap;
118 pmpriv->usr_dot_11n_dev_cap_a =
119 cfg->param.htcap_cfg.htcap;
120 PRINTM(MINFO,
121 "Set: UsrDot11nCap for 2.4GHz and 5GHz 0x%x\n",
122 cfg->param.htcap_cfg.htcap);
123 }
124 }
125 } else {
126 /* Hardware 11N device capability required */
127 if (cfg->param.htcap_cfg.hw_cap_req)
128 cfg->param.htcap_cfg.htcap =
129 pmadapter->hw_dot_11n_dev_cap;
130 else {
131 if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_BG) {
132 cfg->param.htcap_cfg.htcap =
133 pmpriv->usr_dot_11n_dev_cap_bg;
134 PRINTM(MINFO,
135 "Get: UsrDot11nCap for 2.4GHz 0x%x\n",
136 cfg->param.htcap_cfg.htcap);
137 }
138 if (cfg->param.htcap_cfg.misc_cfg == BAND_SELECT_A) {
139 cfg->param.htcap_cfg.htcap =
140 pmpriv->usr_dot_11n_dev_cap_a;
141 PRINTM(MINFO,
142 "Get: UsrDot11nCap for 5GHz 0x%x\n",
143 cfg->param.htcap_cfg.htcap);
144 }
145 }
146 }
147
148 LEAVE();
149 return ret;
150 }
151
152 /**
153 * @brief Enable/Disable AMSDU AGGR CTRL
154 *
155 * @param pmadapter A pointer to mlan_adapter structure
156 * @param pioctl_req A pointer to ioctl request buffer
157 *
158 * @return MLAN_STATUS_PENDING --success, otherwise fail
159 */
wlan_11n_ioctl_amsdu_aggr_ctrl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)160 static mlan_status wlan_11n_ioctl_amsdu_aggr_ctrl(pmlan_adapter pmadapter,
161 pmlan_ioctl_req pioctl_req)
162 {
163 mlan_status ret = MLAN_STATUS_SUCCESS;
164 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
165 mlan_ds_11n_cfg *cfg = MNULL;
166 t_u16 cmd_action = 0;
167
168 ENTER();
169
170 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
171 if (pioctl_req->action == MLAN_ACT_SET)
172 cmd_action = HostCmd_ACT_GEN_SET;
173 else
174 cmd_action = HostCmd_ACT_GEN_GET;
175
176 /* Send request to firmware */
177 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_AMSDU_AGGR_CTRL, cmd_action,
178 0, (t_void *)pioctl_req,
179 (t_void *)&cfg->param.amsdu_aggr_ctrl);
180 if (ret == MLAN_STATUS_SUCCESS)
181 ret = MLAN_STATUS_PENDING;
182
183 LEAVE();
184 return ret;
185 }
186
187 /**
188 * @brief Set/get 11n configuration
189 *
190 * @param pmadapter A pointer to mlan_adapter structure
191 * @param pioctl_req A pointer to ioctl request buffer
192 *
193 * @return MLAN_STATUS_PENDING --success, otherwise fail
194 */
wlan_11n_ioctl_httxcfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)195 static mlan_status wlan_11n_ioctl_httxcfg(pmlan_adapter pmadapter,
196 pmlan_ioctl_req pioctl_req)
197 {
198 mlan_status ret = MLAN_STATUS_SUCCESS;
199 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
200 mlan_ds_11n_cfg *cfg = MNULL;
201 t_u16 cmd_action = 0;
202
203 ENTER();
204
205 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
206 if (pioctl_req->action == MLAN_ACT_SET)
207 cmd_action = HostCmd_ACT_GEN_SET;
208 else
209 cmd_action = HostCmd_ACT_GEN_GET;
210
211 /* Send request to firmware */
212 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_11N_CFG, cmd_action, 0,
213 (t_void *)pioctl_req,
214 (t_void *)&cfg->param.tx_cfg);
215 if (ret == MLAN_STATUS_SUCCESS)
216 ret = MLAN_STATUS_PENDING;
217
218 LEAVE();
219 return ret;
220 }
221
222 /**
223 * @brief Set/get TX beamforming capabilities
224 *
225 * @param pmadapter A pointer to mlan_adapter structure
226 * @param pioctl_req A pointer to ioctl request buffer
227 *
228 * @return MLAN_STATUS_SUCCESS --success
229 */
wlan_11n_ioctl_tx_bf_cap(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)230 static mlan_status wlan_11n_ioctl_tx_bf_cap(pmlan_adapter pmadapter,
231 pmlan_ioctl_req pioctl_req)
232 {
233 mlan_status ret = MLAN_STATUS_SUCCESS;
234 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
235 mlan_ds_11n_cfg *cfg = MNULL;
236
237 ENTER();
238
239 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
240 if (pioctl_req->action == MLAN_ACT_SET)
241 pmpriv->tx_bf_cap = cfg->param.tx_bf_cap;
242 else
243 cfg->param.tx_bf_cap = pmpriv->tx_bf_cap;
244
245 LEAVE();
246 return ret;
247 }
248
249 /**
250 * @brief Set/get TX beamforming configurations
251 *
252 * @param pmadapter A pointer to mlan_adapter structure
253 * @param pioctl_req A pointer to ioctl request buffer
254 *
255 * @return MLAN_STATUS_PENDING --success, otherwise fail
256 */
wlan_11n_ioctl_tx_bf_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)257 static mlan_status wlan_11n_ioctl_tx_bf_cfg(pmlan_adapter pmadapter,
258 pmlan_ioctl_req pioctl_req)
259 {
260 mlan_status ret = MLAN_STATUS_SUCCESS;
261 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
262 mlan_ds_11n_cfg *cfg = MNULL;
263 t_u16 cmd_action = 0;
264
265 ENTER();
266
267 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
268 if (pioctl_req->action == MLAN_ACT_SET)
269 cmd_action = HostCmd_ACT_GEN_SET;
270 else
271 cmd_action = HostCmd_ACT_GEN_GET;
272
273 /* Send request to firmware */
274 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_BF_CFG, cmd_action, 0,
275 (t_void *)pioctl_req,
276 (t_void *)&cfg->param.tx_bf);
277 if (ret == MLAN_STATUS_SUCCESS)
278 ret = MLAN_STATUS_PENDING;
279
280 LEAVE();
281 return ret;
282 }
283
284 /**
285 * @brief Set/get HT stream configurations
286 *
287 * @param pmadapter A pointer to mlan_adapter structure
288 * @param pioctl_req A pointer to ioctl request buffer
289 *
290 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
291 */
wlan_11n_ioctl_stream_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)292 static mlan_status wlan_11n_ioctl_stream_cfg(pmlan_adapter pmadapter,
293 pmlan_ioctl_req pioctl_req)
294 {
295 mlan_status ret = MLAN_STATUS_SUCCESS;
296 mlan_ds_11n_cfg *cfg = MNULL;
297 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
298
299 ENTER();
300
301 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
302 if (pioctl_req->action == MLAN_ACT_GET) {
303 cfg->param.stream_cfg = pmpriv->usr_dev_mcs_support;
304 } else if (pioctl_req->action == MLAN_ACT_SET) {
305 switch (cfg->param.stream_cfg) {
306 case HT_STREAM_MODE_2X2:
307 if (pmadapter->hw_dev_mcs_support ==
308 HT_STREAM_MODE_1X1) {
309 PRINTM(MERROR,
310 "HW does not support this mode\n");
311 ret = MLAN_STATUS_FAILURE;
312 } else
313 pmpriv->usr_dev_mcs_support =
314 cfg->param.stream_cfg;
315 break;
316 case HT_STREAM_MODE_1X1:
317 pmpriv->usr_dev_mcs_support = cfg->param.stream_cfg;
318 break;
319 default:
320 PRINTM(MERROR, "Invalid stream mode\n");
321 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
322 ret = MLAN_STATUS_FAILURE;
323 break;
324 }
325 }
326
327 LEAVE();
328 return ret;
329 }
330
331 /**
332 * @brief Set/get control to coex RX window size configuration
333 *
334 * @param pmadapter A pointer to mlan_adapter structure
335 * @param pioctl_req A pointer to ioctl request buffer
336 *
337 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
338 */
wlan_11n_ioctl_coex_rx_winsize(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)339 static mlan_status wlan_11n_ioctl_coex_rx_winsize(pmlan_adapter pmadapter,
340 pmlan_ioctl_req pioctl_req)
341 {
342 mlan_status ret = MLAN_STATUS_SUCCESS;
343 mlan_ds_11n_cfg *cfg = MNULL;
344
345 ENTER();
346
347 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
348 if (pioctl_req->action == MLAN_ACT_GET)
349 cfg->param.coex_rx_winsize = pmadapter->coex_rx_winsize;
350 else if (pioctl_req->action == MLAN_ACT_SET)
351 pmadapter->coex_rx_winsize = (t_u8)cfg->param.coex_rx_winsize;
352
353 LEAVE();
354 return ret;
355 }
356
357 /**
358 * @brief This function will send delba request to
359 * the peer in the TxBAStreamTbl
360 *
361 * @param priv A pointer to mlan_private
362 * @param ra MAC Address to send DELBA
363 *
364 * @return N/A
365 */
wlan_11n_send_delba_to_peer(mlan_private * priv,t_u8 * ra)366 void wlan_11n_send_delba_to_peer(mlan_private *priv, t_u8 *ra)
367 {
368 TxBAStreamTbl *ptx_tbl;
369
370 ENTER();
371 wlan_request_ralist_lock(priv);
372 ptx_tbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
373 &priv->tx_ba_stream_tbl_ptr,
374 MNULL, MNULL);
375 if (!ptx_tbl) {
376 wlan_release_ralist_lock(priv);
377 LEAVE();
378 return;
379 }
380
381 while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
382 if (!memcmp(priv->adapter, ptx_tbl->ra, ra,
383 MLAN_MAC_ADDR_LENGTH)) {
384 PRINTM(MIOCTL, "Tx:Send delba to tid=%d, " MACSTR "\n",
385 ptx_tbl->tid, MAC2STR(ptx_tbl->ra));
386 wlan_send_delba(priv, MNULL, ptx_tbl->tid, ptx_tbl->ra,
387 1);
388 }
389 ptx_tbl = ptx_tbl->pnext;
390 }
391 wlan_release_ralist_lock(priv);
392 /* Signal MOAL to trigger mlan_main_process */
393 wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL);
394 LEAVE();
395 return;
396 }
397
398 /**
399 * @brief Set/Get control to TX AMPDU configuration on infra link
400 *
401 * @param pmadapter A pointer to mlan_adapter structure
402 * @param pioctl_req A pointer to ioctl request buffer
403 *
404 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
405 */
wlan_11n_ioctl_txaggrctrl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)406 static mlan_status wlan_11n_ioctl_txaggrctrl(pmlan_adapter pmadapter,
407 pmlan_ioctl_req pioctl_req)
408 {
409 mlan_status ret = MLAN_STATUS_SUCCESS;
410 mlan_ds_11n_cfg *cfg = MNULL;
411 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
412
413 ENTER();
414
415 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
416 if (pioctl_req->action == MLAN_ACT_GET)
417 cfg->param.txaggrctrl = pmpriv->txaggrctrl;
418 else if (pioctl_req->action == MLAN_ACT_SET)
419 pmpriv->txaggrctrl = (t_u8)cfg->param.txaggrctrl;
420
421 if (pmpriv->media_connected == MTRUE) {
422 if (pioctl_req->action == MLAN_ACT_SET && !pmpriv->txaggrctrl &&
423 pmpriv->adapter->tdls_status != TDLS_NOT_SETUP)
424 wlan_11n_send_delba_to_peer(
425 pmpriv, pmpriv->curr_bss_params.bss_descriptor
426 .mac_address);
427 }
428 LEAVE();
429 return ret;
430 }
431
432 /**
433 * @brief This function will resend addba request to all
434 * the peer in the TxBAStreamTbl
435 *
436 * @param priv A pointer to mlan_private
437 *
438 * @return N/A
439 */
wlan_11n_update_addba_request(mlan_private * priv)440 static void wlan_11n_update_addba_request(mlan_private *priv)
441 {
442 TxBAStreamTbl *ptx_tbl;
443
444 ENTER();
445
446 wlan_request_ralist_lock(priv);
447 ptx_tbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
448 &priv->tx_ba_stream_tbl_ptr,
449 MNULL, MNULL);
450 if (!ptx_tbl) {
451 wlan_release_ralist_lock(priv);
452 LEAVE();
453 return;
454 }
455
456 while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
457 wlan_send_addba(priv, ptx_tbl->tid, ptx_tbl->ra);
458 ptx_tbl = ptx_tbl->pnext;
459 }
460 wlan_release_ralist_lock(priv);
461 /* Signal MOAL to trigger mlan_main_process */
462 wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL);
463 LEAVE();
464 return;
465 }
466
467 /**
468 * @brief Set/get addba parameter
469 *
470 * @param pmadapter A pointer to mlan_adapter structure
471 * @param pioctl_req A pointer to ioctl request buffer
472 *
473 * @return MLAN_STATUS_SUCCESS --success
474 */
wlan_11n_ioctl_addba_param(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)475 static mlan_status wlan_11n_ioctl_addba_param(pmlan_adapter pmadapter,
476 pmlan_ioctl_req pioctl_req)
477 {
478 mlan_status ret = MLAN_STATUS_SUCCESS;
479 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
480 mlan_ds_11n_cfg *cfg = MNULL;
481 t_u32 timeout;
482
483 ENTER();
484
485 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
486 if (pioctl_req->action == MLAN_ACT_GET) {
487 cfg->param.addba_param.timeout = pmpriv->add_ba_param.timeout;
488 cfg->param.addba_param.txwinsize =
489 pmpriv->add_ba_param.tx_win_size;
490 cfg->param.addba_param.rxwinsize =
491 pmpriv->add_ba_param.rx_win_size;
492 cfg->param.addba_param.txamsdu = pmpriv->add_ba_param.tx_amsdu;
493 cfg->param.addba_param.rxamsdu = pmpriv->add_ba_param.rx_amsdu;
494 } else {
495 timeout = pmpriv->add_ba_param.timeout;
496 pmpriv->add_ba_param.timeout = cfg->param.addba_param.timeout;
497 pmpriv->add_ba_param.tx_win_size =
498 cfg->param.addba_param.txwinsize;
499
500 pmpriv->add_ba_param.rx_win_size =
501 cfg->param.addba_param.rxwinsize;
502 pmpriv->user_rxwinsize = pmpriv->add_ba_param.rx_win_size;
503 pmpriv->add_ba_param.tx_amsdu = cfg->param.addba_param.txamsdu;
504 pmpriv->add_ba_param.rx_amsdu = cfg->param.addba_param.rxamsdu;
505 if (timeout != pmpriv->add_ba_param.timeout)
506 wlan_11n_update_addba_request(pmpriv);
507 }
508
509 LEAVE();
510 return ret;
511 }
512
513 /**
514 * @brief This function send delba to specific tid
515 *
516 * @param priv A pointer to mlan_priv
517 * @param tid tid
518 * @return N/A
519 */
wlan_11n_delba(mlan_private * priv,int tid)520 void wlan_11n_delba(mlan_private *priv, int tid)
521 {
522 RxReorderTbl *rx_reor_tbl_ptr;
523
524 ENTER();
525
526 rx_reor_tbl_ptr = (RxReorderTbl *)util_peek_list(
527 priv->adapter->pmoal_handle, &priv->rx_reorder_tbl_ptr,
528 priv->adapter->callbacks.moal_spin_lock,
529 priv->adapter->callbacks.moal_spin_unlock);
530 if (!rx_reor_tbl_ptr) {
531 LEAVE();
532 return;
533 }
534
535 while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
536 if (rx_reor_tbl_ptr->tid == tid) {
537 PRINTM(MIOCTL, "Send delba to tid=%d, " MACSTR "\n",
538 tid, MAC2STR(rx_reor_tbl_ptr->ta));
539 wlan_send_delba(priv, MNULL, tid, rx_reor_tbl_ptr->ta,
540 0);
541 LEAVE();
542 return;
543 }
544 rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
545 }
546
547 LEAVE();
548 return;
549 }
550
551 /**
552 * @brief Set/get addba reject set
553 *
554 * @param pmadapter A pointer to mlan_adapter structure
555 * @param pioctl_req A pointer to ioctl request buffer
556 *
557 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
558 */
wlan_11n_ioctl_addba_reject(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)559 static mlan_status wlan_11n_ioctl_addba_reject(pmlan_adapter pmadapter,
560 pmlan_ioctl_req pioctl_req)
561 {
562 int i = 0;
563 mlan_status ret = MLAN_STATUS_SUCCESS;
564 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
565 mlan_ds_11n_cfg *cfg = MNULL;
566
567 ENTER();
568
569 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
570
571 if (pioctl_req->action == MLAN_ACT_GET) {
572 PRINTM(MINFO, "Get Addba reject\n");
573 memcpy_ext(pmadapter, cfg->param.addba_reject,
574 pmpriv->addba_reject, MAX_NUM_TID, MAX_NUM_TID);
575 } else {
576 for (i = 0; i < MAX_NUM_TID; i++) {
577 /* For AMPDU */
578 if (cfg->param.addba_reject[i] >
579 ADDBA_RSP_STATUS_REJECT) {
580 pioctl_req->status_code =
581 MLAN_ERROR_INVALID_PARAMETER;
582 ret = MLAN_STATUS_FAILURE;
583 break;
584 }
585
586 pmpriv->addba_reject[i] = cfg->param.addba_reject[i];
587 }
588 if (pmpriv->media_connected == MTRUE) {
589 for (i = 0; i < MAX_NUM_TID; i++) {
590 if (cfg->param.addba_reject[i] ==
591 ADDBA_RSP_STATUS_REJECT) {
592 PRINTM(MIOCTL,
593 "Receive addba reject: tid=%d\n",
594 i);
595 wlan_11n_delba(pmpriv, i);
596 }
597 }
598 wlan_recv_event(pmpriv,
599 MLAN_EVENT_ID_DRV_DEFER_HANDLING,
600 MNULL);
601 }
602 }
603
604 LEAVE();
605 return ret;
606 }
607
608 /**
609 * @brief Set/get ibss ampdu param
610 *
611 * @param pmadapter A pointer to mlan_adapter structure
612 * @param pioctl_req A pointer to ioctl request buffer
613 *
614 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
615 */
wlan_11n_ioctl_ibss_ampdu_param(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)616 static mlan_status wlan_11n_ioctl_ibss_ampdu_param(pmlan_adapter pmadapter,
617 pmlan_ioctl_req pioctl_req)
618 {
619 int i = 0;
620 mlan_status ret = MLAN_STATUS_SUCCESS;
621 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
622 mlan_ds_11n_cfg *cfg = MNULL;
623
624 ENTER();
625
626 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
627
628 if (pioctl_req->action == MLAN_ACT_GET) {
629 PRINTM(MINFO, "Get IBSS AMPDU param\n");
630 for (i = 0; i < MAX_NUM_TID; i++) {
631 cfg->param.ibss_ampdu.ampdu[i] = pmpriv->ibss_ampdu[i];
632 cfg->param.ibss_ampdu.addba_reject[i] =
633 pmpriv->ibss_addba_reject[i];
634 }
635 } else {
636 for (i = 0; i < MAX_NUM_TID; i++) {
637 /* For AMPDU RX*/
638 if (cfg->param.ibss_ampdu.addba_reject[i] >
639 ADDBA_RSP_STATUS_REJECT) {
640 pioctl_req->status_code =
641 MLAN_ERROR_INVALID_PARAMETER;
642 ret = MLAN_STATUS_FAILURE;
643 break;
644 }
645 pmpriv->ibss_addba_reject[i] =
646 cfg->param.ibss_ampdu.addba_reject[i];
647 /* For AMPDU TX*/
648 if ((cfg->param.ibss_ampdu.ampdu[i] > HIGH_PRIO_TID) &&
649 (cfg->param.ibss_ampdu.ampdu[i] !=
650 BA_STREAM_NOT_ALLOWED)) {
651 pioctl_req->status_code =
652 MLAN_ERROR_INVALID_PARAMETER;
653 ret = MLAN_STATUS_FAILURE;
654 break;
655 }
656 pmpriv->ibss_ampdu[i] = cfg->param.ibss_ampdu.ampdu[i];
657 }
658 PRINTM(MMSG, "IBSS addba reject: %d %d %d %d %d %d %d %d\n",
659 pmpriv->ibss_addba_reject[0],
660 pmpriv->ibss_addba_reject[1],
661 pmpriv->ibss_addba_reject[2],
662 pmpriv->ibss_addba_reject[3],
663 pmpriv->ibss_addba_reject[4],
664 pmpriv->ibss_addba_reject[5],
665 pmpriv->ibss_addba_reject[6],
666 pmpriv->ibss_addba_reject[7]);
667 PRINTM(MMSG, "IBSS ampdu %d %d %d %d %d %d %d %d\n",
668 pmpriv->ibss_ampdu[0], pmpriv->ibss_ampdu[1],
669 pmpriv->ibss_ampdu[2], pmpriv->ibss_ampdu[3],
670 pmpriv->ibss_ampdu[4], pmpriv->ibss_ampdu[5],
671 pmpriv->ibss_ampdu[6], pmpriv->ibss_ampdu[7]);
672 }
673 LEAVE();
674 return ret;
675 }
676
677 /**
678 * @brief Set/Get Minimum BA Threshold
679 *
680 * @param pmadapter A pointer to mlan_adapter structure
681 * @param pioctl_req A pointer to ioctl request buffer
682 *
683 * @return MLAN_STATUS_SUCCESS --success
684 */
685 static mlan_status
wlan_11n_ioctl_min_ba_threshold_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)686 wlan_11n_ioctl_min_ba_threshold_cfg(pmlan_adapter pmadapter,
687 pmlan_ioctl_req pioctl_req)
688 {
689 mlan_status ret = MLAN_STATUS_SUCCESS;
690 mlan_ds_11n_cfg *cfg = MNULL;
691 ENTER();
692 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
693 if (pioctl_req->action == MLAN_ACT_GET)
694 cfg->param.min_ba_threshold = pmadapter->min_ba_threshold;
695 else
696 pmadapter->min_ba_threshold = cfg->param.min_ba_threshold;
697 pioctl_req->data_read_written = sizeof(t_u8) + MLAN_SUB_COMMAND_SIZE;
698 LEAVE();
699 return ret;
700 }
701
702 /**
703 * @brief This function will send DELBA to entries in the priv's
704 * Tx BA stream table
705 *
706 * @param priv A pointer to mlan_private
707 * @param pioctl_req A pointer to ioctl request buffer
708 * @param tid TID
709 * @param peer_address A pointer to peer address
710 * @param last_tx_ba_to_delete A pointer to the last entry in TxBAStreamTbl
711 *
712 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_PENDING
713 */
wlan_send_delba_to_entry_in_txbastream_tbl(pmlan_private priv,pmlan_ioctl_req pioctl_req,t_u8 tid,t_u8 * peer_address,TxBAStreamTbl * last_tx_ba_to_delete)714 static mlan_status wlan_send_delba_to_entry_in_txbastream_tbl(
715 pmlan_private priv, pmlan_ioctl_req pioctl_req, t_u8 tid,
716 t_u8 *peer_address, TxBAStreamTbl *last_tx_ba_to_delete)
717 {
718 pmlan_adapter pmadapter = priv->adapter;
719 TxBAStreamTbl *tx_ba_stream_tbl_ptr;
720 t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0};
721 mlan_status ret = MLAN_STATUS_SUCCESS;
722
723 ENTER();
724
725 wlan_request_ralist_lock(priv);
726 tx_ba_stream_tbl_ptr =
727 (TxBAStreamTbl *)util_peek_list(pmadapter->pmoal_handle,
728 &priv->tx_ba_stream_tbl_ptr,
729 MNULL, MNULL);
730 if (!tx_ba_stream_tbl_ptr) {
731 wlan_release_ralist_lock(priv);
732 LEAVE();
733 return ret;
734 }
735
736 while (tx_ba_stream_tbl_ptr !=
737 (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
738 if (tx_ba_stream_tbl_ptr->ba_status ==
739 BA_STREAM_SETUP_COMPLETE) {
740 if (((tid == DELBA_ALL_TIDS) ||
741 (tid == tx_ba_stream_tbl_ptr->tid)) &&
742 (!memcmp(pmadapter, peer_address, zero_mac,
743 MLAN_MAC_ADDR_LENGTH) ||
744 !memcmp(pmadapter, peer_address,
745 tx_ba_stream_tbl_ptr->ra,
746 MLAN_MAC_ADDR_LENGTH))) {
747 if (last_tx_ba_to_delete &&
748 (tx_ba_stream_tbl_ptr ==
749 last_tx_ba_to_delete))
750 ret = wlan_send_delba(
751 priv, pioctl_req,
752 tx_ba_stream_tbl_ptr->tid,
753 tx_ba_stream_tbl_ptr->ra, 1);
754 else
755 ret = wlan_send_delba(
756 priv, MNULL,
757 tx_ba_stream_tbl_ptr->tid,
758 tx_ba_stream_tbl_ptr->ra, 1);
759 }
760 }
761 tx_ba_stream_tbl_ptr = tx_ba_stream_tbl_ptr->pnext;
762 }
763 wlan_release_ralist_lock(priv);
764
765 LEAVE();
766 return ret;
767 }
768
769 /**
770 * @brief This function will send DELBA to entries in the priv's
771 * rx reordering table
772 *
773 * @param priv A pointer to mlan_private
774 * @param pioctl_req A pointer to ioctl request buffer
775 * @param tid TID
776 * @param peer_address A pointer to peer address
777 * @param last_rx_ba_to_delete A pointer to the last entry in RxReorderTbl
778 *
779 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_PENDING
780 */
wlan_send_delba_to_entry_in_reorder_tbl(pmlan_private priv,pmlan_ioctl_req pioctl_req,t_u8 tid,t_u8 * peer_address,RxReorderTbl * last_rx_ba_to_delete)781 static mlan_status wlan_send_delba_to_entry_in_reorder_tbl(
782 pmlan_private priv, pmlan_ioctl_req pioctl_req, t_u8 tid,
783 t_u8 *peer_address, RxReorderTbl *last_rx_ba_to_delete)
784 {
785 pmlan_adapter pmadapter = priv->adapter;
786 RxReorderTbl *rx_reor_tbl_ptr;
787 t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0};
788 mlan_status ret = MLAN_STATUS_SUCCESS;
789
790 ENTER();
791
792 rx_reor_tbl_ptr = (RxReorderTbl *)util_peek_list(
793 pmadapter->pmoal_handle, &priv->rx_reorder_tbl_ptr,
794 pmadapter->callbacks.moal_spin_lock,
795 pmadapter->callbacks.moal_spin_unlock);
796 if (!rx_reor_tbl_ptr) {
797 LEAVE();
798 return ret;
799 }
800
801 while (rx_reor_tbl_ptr != (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
802 if (rx_reor_tbl_ptr->ba_status == BA_STREAM_SETUP_COMPLETE) {
803 if (((tid == DELBA_ALL_TIDS) ||
804 (tid == rx_reor_tbl_ptr->tid)) &&
805 (!memcmp(pmadapter, peer_address, zero_mac,
806 MLAN_MAC_ADDR_LENGTH) ||
807 !memcmp(pmadapter, peer_address,
808 rx_reor_tbl_ptr->ta,
809 MLAN_MAC_ADDR_LENGTH))) {
810 if (last_rx_ba_to_delete &&
811 (rx_reor_tbl_ptr == last_rx_ba_to_delete))
812 ret = wlan_send_delba(
813 priv, pioctl_req,
814 rx_reor_tbl_ptr->tid,
815 rx_reor_tbl_ptr->ta, 0);
816 else
817 ret = wlan_send_delba(
818 priv, MNULL,
819 rx_reor_tbl_ptr->tid,
820 rx_reor_tbl_ptr->ta, 0);
821 }
822 }
823 rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
824 }
825
826 LEAVE();
827 return ret;
828 }
829
830 /**
831 * @brief IOCTL to delete BA
832 *
833 * @param pmadapter A pointer to mlan_adapter structure
834 * @param pioctl_req A pointer to ioctl request buffer
835 *
836 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
837 */
wlan_11n_ioctl_delba(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)838 static mlan_status wlan_11n_ioctl_delba(pmlan_adapter pmadapter,
839 pmlan_ioctl_req pioctl_req)
840 {
841 mlan_status ret = MLAN_STATUS_SUCCESS;
842 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
843 mlan_ds_11n_cfg *cfg = MNULL;
844 TxBAStreamTbl *tx_ba_stream_tbl_ptr, *last_tx_ba_to_delete = MNULL;
845 RxReorderTbl *rx_reor_tbl_ptr, *last_rx_ba_to_delete = MNULL;
846 t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0};
847 t_u8 tid, *peer_address;
848
849 ENTER();
850
851 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
852 tid = cfg->param.del_ba.tid;
853 peer_address = cfg->param.del_ba.peer_mac_addr;
854
855 PRINTM(MINFO, "DelBA: direction %d, TID %d, peer address " MACSTR "\n",
856 cfg->param.del_ba.direction, tid, MAC2STR(peer_address));
857
858 if (cfg->param.del_ba.direction & DELBA_RX) {
859 rx_reor_tbl_ptr = (RxReorderTbl *)util_peek_list(
860 pmadapter->pmoal_handle, &pmpriv->rx_reorder_tbl_ptr,
861 pmadapter->callbacks.moal_spin_lock,
862 pmadapter->callbacks.moal_spin_unlock);
863
864 if (rx_reor_tbl_ptr) {
865 while (rx_reor_tbl_ptr !=
866 (RxReorderTbl *)&pmpriv->rx_reorder_tbl_ptr) {
867 if (rx_reor_tbl_ptr->ba_status ==
868 BA_STREAM_SETUP_COMPLETE) {
869 if (((tid == DELBA_ALL_TIDS) ||
870 (tid == rx_reor_tbl_ptr->tid)) &&
871 (!memcmp(pmadapter, peer_address,
872 zero_mac,
873 MLAN_MAC_ADDR_LENGTH) ||
874 !memcmp(pmadapter, peer_address,
875 rx_reor_tbl_ptr->ta,
876 MLAN_MAC_ADDR_LENGTH))) {
877 /* Found RX BA to delete */
878 last_rx_ba_to_delete =
879 rx_reor_tbl_ptr;
880 }
881 }
882 rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext;
883 }
884 }
885 }
886
887 if ((last_rx_ba_to_delete == MNULL) &&
888 (cfg->param.del_ba.direction & DELBA_TX)) {
889 wlan_request_ralist_lock(pmpriv);
890 tx_ba_stream_tbl_ptr = (TxBAStreamTbl *)util_peek_list(
891 pmadapter->pmoal_handle, &pmpriv->tx_ba_stream_tbl_ptr,
892 MNULL, MNULL);
893
894 if (tx_ba_stream_tbl_ptr) {
895 while (tx_ba_stream_tbl_ptr !=
896 (TxBAStreamTbl *)&pmpriv->tx_ba_stream_tbl_ptr) {
897 if (tx_ba_stream_tbl_ptr->ba_status ==
898 BA_STREAM_SETUP_COMPLETE) {
899 if (((tid == DELBA_ALL_TIDS) ||
900 (tid ==
901 tx_ba_stream_tbl_ptr->tid)) &&
902 (!memcmp(pmadapter, peer_address,
903 zero_mac,
904 MLAN_MAC_ADDR_LENGTH) ||
905 !memcmp(pmadapter, peer_address,
906 tx_ba_stream_tbl_ptr->ra,
907 MLAN_MAC_ADDR_LENGTH))) {
908 /* Found TX BA to delete */
909 last_tx_ba_to_delete =
910 tx_ba_stream_tbl_ptr;
911 }
912 }
913 tx_ba_stream_tbl_ptr =
914 tx_ba_stream_tbl_ptr->pnext;
915 }
916 }
917 wlan_release_ralist_lock(pmpriv);
918 }
919
920 if (cfg->param.del_ba.direction & DELBA_TX) {
921 if (last_rx_ba_to_delete)
922 ret = wlan_send_delba_to_entry_in_txbastream_tbl(
923 pmpriv, MNULL, tid, peer_address, MNULL);
924 else
925 ret = wlan_send_delba_to_entry_in_txbastream_tbl(
926 pmpriv, pioctl_req, tid, peer_address,
927 last_tx_ba_to_delete);
928 }
929 if (last_rx_ba_to_delete) {
930 ret = wlan_send_delba_to_entry_in_reorder_tbl(
931 pmpriv, pioctl_req, tid, peer_address,
932 last_rx_ba_to_delete);
933 }
934
935 LEAVE();
936 return ret;
937 }
938
939 /**
940 * @brief IOCTL to reject addba req
941 *
942 * @param pmadapter A pointer to mlan_adapter structure
943 * @param pioctl_req A pointer to ioctl request buffer
944 *
945 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
946 */
wlan_11n_ioctl_rejectaddbareq(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)947 static mlan_status wlan_11n_ioctl_rejectaddbareq(pmlan_adapter pmadapter,
948 pmlan_ioctl_req pioctl_req)
949 {
950 mlan_status ret = MLAN_STATUS_SUCCESS;
951 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
952 mlan_ds_11n_cfg *cfg = MNULL;
953 t_u16 cmd_action = 0;
954
955 ENTER();
956
957 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
958 if (pioctl_req->action == MLAN_ACT_SET)
959 cmd_action = HostCmd_ACT_GEN_SET;
960 else
961 cmd_action = HostCmd_ACT_GEN_GET;
962
963 /* Send command to firmware */
964 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_REJECT_ADDBA_REQ, cmd_action,
965 0, (t_void *)pioctl_req,
966 &cfg->param.reject_addba_req);
967
968 if (ret == MLAN_STATUS_SUCCESS)
969 ret = MLAN_STATUS_PENDING;
970
971 LEAVE();
972 return ret;
973 }
974
975 /**
976 * @brief This function will send DELBA to entries in the priv's
977 * Tx BA stream table
978 *
979 * @param priv A pointer to mlan_private
980 * @param tid TID
981 *
982 * @return N/A
983 */
wlan_send_delba_txbastream_tbl(pmlan_private priv,t_u8 tid)984 static void wlan_send_delba_txbastream_tbl(pmlan_private priv, t_u8 tid)
985 {
986 pmlan_adapter pmadapter = priv->adapter;
987 TxBAStreamTbl *tx_ba_stream_tbl_ptr;
988
989 ENTER();
990
991 wlan_request_ralist_lock(priv);
992 tx_ba_stream_tbl_ptr =
993 (TxBAStreamTbl *)util_peek_list(pmadapter->pmoal_handle,
994 &priv->tx_ba_stream_tbl_ptr,
995 MNULL, MNULL);
996 if (!tx_ba_stream_tbl_ptr) {
997 wlan_release_ralist_lock(priv);
998 LEAVE();
999 return;
1000 }
1001
1002 while (tx_ba_stream_tbl_ptr !=
1003 (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
1004 if (tx_ba_stream_tbl_ptr->ba_status ==
1005 BA_STREAM_SETUP_COMPLETE) {
1006 if (tid == tx_ba_stream_tbl_ptr->tid) {
1007 PRINTM(MIOCTL,
1008 "Tx:Send delba to tid=%d, " MACSTR "\n",
1009 tid, MAC2STR(tx_ba_stream_tbl_ptr->ra));
1010 wlan_release_ralist_lock(priv);
1011 wlan_send_delba(priv, MNULL,
1012 tx_ba_stream_tbl_ptr->tid,
1013 tx_ba_stream_tbl_ptr->ra, 1);
1014 LEAVE();
1015 return;
1016 }
1017 }
1018 tx_ba_stream_tbl_ptr = tx_ba_stream_tbl_ptr->pnext;
1019 }
1020 wlan_release_ralist_lock(priv);
1021
1022 LEAVE();
1023 return;
1024 }
1025
1026 /**
1027 * @brief update station list for the new aggr_prio_tbl setting
1028 *
1029 * @param priv A pointer to mlan_private structure
1030 *
1031 *
1032 * @return N/A
1033 */
wlan_update_all_stations_ampdu(mlan_private * priv)1034 static void wlan_update_all_stations_ampdu(mlan_private *priv)
1035 {
1036 sta_node *sta_ptr;
1037 mlan_adapter *pmadapter = priv->adapter;
1038 int i = 0;
1039
1040 ENTER();
1041 pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
1042 priv->wmm.ra_list_spinlock);
1043 sta_ptr = (sta_node *)util_peek_list(pmadapter->pmoal_handle,
1044 &priv->sta_list, MNULL, MNULL);
1045 if (!sta_ptr) {
1046 pmadapter->callbacks.moal_spin_unlock(
1047 pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
1048 LEAVE();
1049 return;
1050 }
1051 while (sta_ptr != (sta_node *)&priv->sta_list) {
1052 for (i = 0; i < MAX_NUM_TID; i++) {
1053 if (sta_ptr->is_11n_enabled || sta_ptr->is_11ax_enabled)
1054 sta_ptr->ampdu_sta[i] =
1055 priv->aggr_prio_tbl[i].ampdu_user;
1056 }
1057 sta_ptr = sta_ptr->pnext;
1058 }
1059 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
1060 priv->wmm.ra_list_spinlock);
1061 LEAVE();
1062 return;
1063 }
1064
1065 /**
1066 * @brief Set/get aggr_prio_tbl
1067 *
1068 * @param pmadapter A pointer to mlan_adapter structure
1069 * @param pioctl_req A pointer to ioctl request buffer
1070 *
1071 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
1072 */
wlan_11n_ioctl_aggr_prio_tbl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1073 static mlan_status wlan_11n_ioctl_aggr_prio_tbl(pmlan_adapter pmadapter,
1074 pmlan_ioctl_req pioctl_req)
1075 {
1076 int i = 0;
1077 mlan_status ret = MLAN_STATUS_SUCCESS;
1078 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1079 mlan_ds_11n_cfg *cfg = MNULL;
1080
1081 ENTER();
1082
1083 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
1084
1085 if (pioctl_req->action == MLAN_ACT_GET) {
1086 for (i = 0; i < MAX_NUM_TID; i++) {
1087 cfg->param.aggr_prio_tbl.ampdu[i] =
1088 pmpriv->aggr_prio_tbl[i].ampdu_user;
1089 cfg->param.aggr_prio_tbl.amsdu[i] =
1090 pmpriv->aggr_prio_tbl[i].amsdu;
1091 }
1092 } else {
1093 for (i = 0; i < MAX_NUM_TID; i++) {
1094 /* For AMPDU */
1095 if ((cfg->param.aggr_prio_tbl.ampdu[i] >
1096 HIGH_PRIO_TID) &&
1097 (cfg->param.aggr_prio_tbl.ampdu[i] !=
1098 BA_STREAM_NOT_ALLOWED)) {
1099 pioctl_req->status_code =
1100 MLAN_ERROR_INVALID_PARAMETER;
1101 ret = MLAN_STATUS_FAILURE;
1102 break;
1103 }
1104
1105 pmpriv->aggr_prio_tbl[i].ampdu_ap =
1106 pmpriv->aggr_prio_tbl[i].ampdu_user =
1107 cfg->param.aggr_prio_tbl.ampdu[i];
1108
1109 /* For AMSDU */
1110 if ((cfg->param.aggr_prio_tbl.amsdu[i] >
1111 HIGH_PRIO_TID &&
1112 cfg->param.aggr_prio_tbl.amsdu[i] !=
1113 BA_STREAM_NOT_ALLOWED)) {
1114 pioctl_req->status_code =
1115 MLAN_ERROR_INVALID_PARAMETER;
1116 ret = MLAN_STATUS_FAILURE;
1117 break;
1118 } else {
1119 pmpriv->aggr_prio_tbl[i].amsdu =
1120 cfg->param.aggr_prio_tbl.amsdu[i];
1121 }
1122 }
1123 if (pmpriv->media_connected == MTRUE) {
1124 for (i = 0; i < MAX_NUM_TID; i++) {
1125 if (cfg->param.aggr_prio_tbl.ampdu[i] ==
1126 BA_STREAM_NOT_ALLOWED) {
1127 PRINTM(MIOCTL,
1128 "Receive aggrpriotbl: BA not allowed tid=%d\n",
1129 i);
1130 wlan_send_delba_txbastream_tbl(pmpriv,
1131 i);
1132 }
1133 }
1134 wlan_update_all_stations_ampdu(pmpriv);
1135 wlan_recv_event(pmpriv,
1136 MLAN_EVENT_ID_DRV_DEFER_HANDLING,
1137 MNULL);
1138 }
1139 }
1140
1141 LEAVE();
1142 return ret;
1143 }
1144
1145 /**
1146 * @brief This function update all the tx_win_size
1147 *
1148 * @param pmadapter A pointer to mlan_adapter
1149 *
1150 *
1151 * @return N/A
1152 */
wlan_update_ampdu_txwinsize(pmlan_adapter pmadapter)1153 void wlan_update_ampdu_txwinsize(pmlan_adapter pmadapter)
1154 {
1155 t_u8 i;
1156 t_u32 tx_win_size = 0;
1157 pmlan_private priv = MNULL;
1158
1159 ENTER();
1160
1161 for (i = 0; i < pmadapter->priv_num; i++) {
1162 if (pmadapter->priv[i]) {
1163 priv = pmadapter->priv[i];
1164 tx_win_size = priv->add_ba_param.tx_win_size;
1165 #ifdef STA_SUPPORT
1166 if (priv->bss_type == MLAN_BSS_TYPE_STA)
1167 priv->add_ba_param.tx_win_size =
1168 MLAN_STA_AMPDU_DEF_TXWINSIZE;
1169 #endif
1170 #ifdef WIFI_DIRECT_SUPPORT
1171 if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
1172 priv->add_ba_param.tx_win_size =
1173 MLAN_WFD_AMPDU_DEF_TXRXWINSIZE;
1174 #endif
1175 #ifdef UAP_SUPPORT
1176 if (priv->bss_type == MLAN_BSS_TYPE_UAP)
1177 priv->add_ba_param.tx_win_size =
1178 MLAN_UAP_AMPDU_DEF_TXWINSIZE;
1179 #endif
1180 if (pmadapter->coex_win_size &&
1181 pmadapter->coex_tx_win_size)
1182 priv->add_ba_param.tx_win_size =
1183 pmadapter->coex_tx_win_size;
1184
1185 if (tx_win_size != priv->add_ba_param.tx_win_size) {
1186 if (priv->media_connected == MTRUE) {
1187 for (i = 0; i < MAX_NUM_TID; i++)
1188 wlan_send_delba_txbastream_tbl(
1189 priv, i);
1190 wlan_recv_event(
1191 priv,
1192 MLAN_EVENT_ID_DRV_DEFER_HANDLING,
1193 MNULL);
1194 }
1195 }
1196 }
1197 }
1198 LEAVE();
1199 return;
1200 }
1201
1202 /**
1203 * @brief Get supported MCS set
1204 *
1205 * @param pmadapter A pointer to mlan_adapter structure
1206 * @param pioctl_req A pointer to ioctl request buffer
1207 *
1208 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
1209 */
wlan_11n_ioctl_supported_mcs_set(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1210 static mlan_status wlan_11n_ioctl_supported_mcs_set(pmlan_adapter pmadapter,
1211 pmlan_ioctl_req pioctl_req)
1212 {
1213 mlan_ds_11n_cfg *cfg = MNULL;
1214 int rx_mcs_supp;
1215 t_u8 mcs_set[NUM_MCS_FIELD];
1216 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1217
1218 ENTER();
1219
1220 if (pioctl_req->action == MLAN_ACT_SET) {
1221 PRINTM(MERROR, "Set operation is not supported\n");
1222 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1223 LEAVE();
1224 return MLAN_STATUS_FAILURE;
1225 }
1226 rx_mcs_supp = GET_RXMCSSUPP(pmpriv->usr_dev_mcs_support);
1227 /* Set MCS for 1x1/2x2*/
1228 memset(pmadapter, (t_u8 *)mcs_set, 0xff, rx_mcs_supp);
1229 /* Clear all the other values */
1230 memset(pmadapter, (t_u8 *)&mcs_set[rx_mcs_supp], 0,
1231 NUM_MCS_FIELD - rx_mcs_supp);
1232 /* Set MCS32 with 40MHz support */
1233 if ((ISSUPP_CHANWIDTH40(pmpriv->usr_dot_11n_dev_cap_bg) ||
1234 ISSUPP_CHANWIDTH40(pmpriv->usr_dot_11n_dev_cap_a)) &&
1235 !(pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
1236 pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS) &&
1237 pmadapter->init_para.mcs32 == 1)
1238 SETHT_MCS32(mcs_set);
1239
1240 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
1241 memcpy_ext(pmadapter, cfg->param.supported_mcs_set, mcs_set,
1242 NUM_MCS_FIELD, NUM_MCS_FIELD);
1243
1244 LEAVE();
1245 return MLAN_STATUS_SUCCESS;
1246 }
1247
1248 /**
1249 * @brief This function checks if the given pointer is valid entry of
1250 * Tx BA Stream table
1251 *
1252 * @param priv Pointer to mlan_private
1253 * @param ptxtblptr Pointer to tx ba stream entry
1254 *
1255 * @return MTRUE or MFALSE
1256 */
wlan_is_txbastreamptr_valid(mlan_private * priv,TxBAStreamTbl * ptxtblptr)1257 static int wlan_is_txbastreamptr_valid(mlan_private *priv,
1258 TxBAStreamTbl *ptxtblptr)
1259 {
1260 TxBAStreamTbl *ptx_tbl;
1261
1262 ENTER();
1263
1264 ptx_tbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
1265 &priv->tx_ba_stream_tbl_ptr,
1266 MNULL, MNULL);
1267 if (!ptx_tbl) {
1268 LEAVE();
1269 return MFALSE;
1270 }
1271
1272 while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
1273 if (ptx_tbl == ptxtblptr) {
1274 LEAVE();
1275 return MTRUE;
1276 }
1277 ptx_tbl = ptx_tbl->pnext;
1278 }
1279 LEAVE();
1280 return MFALSE;
1281 }
1282
1283 /**
1284 * @brief This function will return the pointer to a entry in BA Stream
1285 * table which matches the ba_status requested
1286 *
1287 * @param priv A pointer to mlan_private
1288 * @param ba_status Current status of the BA stream
1289 *
1290 * @return A pointer to first entry matching status in BA stream
1291 * NULL if not found
1292 */
wlan_11n_get_txbastream_status(mlan_private * priv,baStatus_e ba_status)1293 static TxBAStreamTbl *wlan_11n_get_txbastream_status(mlan_private *priv,
1294 baStatus_e ba_status)
1295 {
1296 TxBAStreamTbl *ptx_tbl;
1297
1298 ENTER();
1299
1300 ptx_tbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
1301 &priv->tx_ba_stream_tbl_ptr,
1302 MNULL, MNULL);
1303 if (!ptx_tbl) {
1304 LEAVE();
1305 return MNULL;
1306 }
1307
1308 while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
1309 if (ptx_tbl->ba_status == ba_status) {
1310 LEAVE();
1311 return ptx_tbl;
1312 }
1313 ptx_tbl = ptx_tbl->pnext;
1314 }
1315
1316 LEAVE();
1317 return MNULL;
1318 }
1319
1320 /********************************************************
1321 Global Functions
1322 ********************************************************/
1323
1324 #ifdef STA_SUPPORT
1325 /**
1326 * @brief This function fills the cap info
1327 *
1328 * @param priv A pointer to mlan_private structure
1329 * @param pht_cap A pointer to MrvlIETypes_HTCap_t structure
1330 * @param bands Band configuration
1331 *
1332 * @return N/A
1333 */
wlan_fill_cap_info(mlan_private * priv,HTCap_t * ht_cap,t_u16 bands)1334 static void wlan_fill_cap_info(mlan_private *priv, HTCap_t *ht_cap, t_u16 bands)
1335 {
1336 t_u32 usr_dot_11n_dev_cap;
1337
1338 ENTER();
1339
1340 if (bands & BAND_A)
1341 usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
1342 else
1343 usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
1344
1345 if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap))
1346 SETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
1347 else
1348 RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
1349
1350 if (ISSUPP_GREENFIELD(usr_dot_11n_dev_cap))
1351 SETHT_GREENFIELD(ht_cap->ht_cap_info);
1352 else
1353 RESETHT_GREENFIELD(ht_cap->ht_cap_info);
1354
1355 if (ISSUPP_SHORTGI20(usr_dot_11n_dev_cap))
1356 SETHT_SHORTGI20(ht_cap->ht_cap_info);
1357 else
1358 RESETHT_SHORTGI20(ht_cap->ht_cap_info);
1359
1360 if (ISSUPP_SHORTGI40(usr_dot_11n_dev_cap))
1361 SETHT_SHORTGI40(ht_cap->ht_cap_info);
1362 else
1363 RESETHT_SHORTGI40(ht_cap->ht_cap_info);
1364 if (ISSUPP_RXSTBC(usr_dot_11n_dev_cap))
1365 SETHT_RXSTBC(ht_cap->ht_cap_info, 1);
1366 else
1367 RESETHT_RXSTBC(ht_cap->ht_cap_info);
1368
1369 if (ISENABLED_40MHZ_INTOLARENT(usr_dot_11n_dev_cap))
1370 SETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
1371 else
1372 RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
1373
1374 /** if current channel only allow 20Mhz, we should cler 40Mhz support */
1375 if (priv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
1376 priv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS) {
1377 RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
1378 RESETHT_SHORTGI40(ht_cap->ht_cap_info);
1379 RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
1380 }
1381 /* No user config for LDPC coding capability yet */
1382 if (ISSUPP_RXLDPC(usr_dot_11n_dev_cap))
1383 SETHT_LDPCCODINGCAP(ht_cap->ht_cap_info);
1384 else
1385 RESETHT_LDPCCODINGCAP(ht_cap->ht_cap_info);
1386
1387 /* No user config for TX STBC yet */
1388 if (ISSUPP_TXSTBC(usr_dot_11n_dev_cap))
1389 SETHT_TXSTBC(ht_cap->ht_cap_info);
1390 else
1391 RESETHT_TXSTBC(ht_cap->ht_cap_info);
1392
1393 /* No user config for Delayed BACK yet */
1394 RESETHT_DELAYEDBACK(ht_cap->ht_cap_info);
1395
1396 /* Need change to support 8k AMSDU receive */
1397 RESETHT_MAXAMSDU(ht_cap->ht_cap_info);
1398
1399 /* SM power save */
1400 RESETHT_SM_POWERSAVE(ht_cap->ht_cap_info); /* Clear to HT SMPS static
1401 mode*/
1402 if (ISSUPP_MIMOPS(usr_dot_11n_dev_cap)) {
1403 if (ISSUPP_SMPS_DYNAMIC_MODE(usr_dot_11n_dev_cap))
1404 SETHT_SMPS_DYNAMIC(ht_cap->ht_cap_info); /* Set to HT
1405 SMPS dynamic
1406 mode */
1407 } else {
1408 SETHT_SMPS_DISABLE(ht_cap->ht_cap_info); /* Disable HT SMPS */
1409 }
1410
1411 LEAVE();
1412 }
1413
1414 /**
1415 * @brief This function clear the bit in cap info which we don't support
1416 *
1417 * @param priv A pointer to mlan_private structure
1418 * @param pht_cap A pointer to MrvlIETypes_HTCap_t structure
1419 * @param bands Band configuration
1420 *
1421 * @return N/A
1422 */
wlan_reset_cap_info(mlan_private * priv,HTCap_t * ht_cap,t_u16 bands)1423 static void wlan_reset_cap_info(mlan_private *priv, HTCap_t *ht_cap,
1424 t_u16 bands)
1425 {
1426 t_u32 usr_dot_11n_dev_cap;
1427
1428 ENTER();
1429
1430 if (bands & BAND_A)
1431 usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
1432 else
1433 usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
1434
1435 if (!ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap))
1436 RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
1437
1438 if (!ISSUPP_GREENFIELD(usr_dot_11n_dev_cap))
1439 RESETHT_GREENFIELD(ht_cap->ht_cap_info);
1440
1441 if (!ISSUPP_SHORTGI20(usr_dot_11n_dev_cap))
1442 RESETHT_SHORTGI20(ht_cap->ht_cap_info);
1443
1444 if (!ISSUPP_SHORTGI40(usr_dot_11n_dev_cap))
1445 RESETHT_SHORTGI40(ht_cap->ht_cap_info);
1446 if (!ISSUPP_RXSTBC(usr_dot_11n_dev_cap))
1447 RESETHT_RXSTBC(ht_cap->ht_cap_info);
1448
1449 if (!ISENABLED_40MHZ_INTOLARENT(usr_dot_11n_dev_cap))
1450 RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
1451
1452 /** if current channel only allow 20Mhz, we should cler 40Mhz support */
1453 if (priv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
1454 priv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS) {
1455 RESETHT_SUPPCHANWIDTH(ht_cap->ht_cap_info);
1456 RESETHT_SHORTGI40(ht_cap->ht_cap_info);
1457 RESETHT_40MHZ_INTOLARANT(ht_cap->ht_cap_info);
1458 }
1459 /* No user config for LDPC coding capability yet */
1460 if (!ISSUPP_RXLDPC(usr_dot_11n_dev_cap))
1461 RESETHT_LDPCCODINGCAP(ht_cap->ht_cap_info);
1462
1463 /* No user config for TX STBC yet */
1464 if (!ISSUPP_TXSTBC(usr_dot_11n_dev_cap))
1465 RESETHT_TXSTBC(ht_cap->ht_cap_info);
1466
1467 /* No user config for Delayed BACK yet */
1468 RESETHT_DELAYEDBACK(ht_cap->ht_cap_info);
1469
1470 /* Need change to support 8k AMSDU receive */
1471 RESETHT_MAXAMSDU(ht_cap->ht_cap_info);
1472 /* SM power save */
1473 if (!ISSUPP_MIMOPS(usr_dot_11n_dev_cap))
1474 SETHT_SMPS_DISABLE(ht_cap->ht_cap_info); /* Disable HT SMPS */
1475
1476 LEAVE();
1477 }
1478
1479 /**
1480 * @brief This function fills the HT cap tlv
1481 *
1482 * @param priv A pointer to mlan_private structure
1483 * @param pht_cap A pointer to MrvlIETypes_HTCap_t structure
1484 * @param bands Band configuration
1485 * @param fill A flag for fill the htcap info
1486 *
1487 * @return N/A
1488 */
wlan_fill_ht_cap_tlv(mlan_private * priv,MrvlIETypes_HTCap_t * pht_cap,t_u16 bands,t_u8 fill)1489 void wlan_fill_ht_cap_tlv(mlan_private *priv, MrvlIETypes_HTCap_t *pht_cap,
1490 t_u16 bands, t_u8 fill)
1491 {
1492 mlan_adapter *pmadapter = priv->adapter;
1493 int rx_mcs_supp;
1494 t_u32 usr_dot_11n_dev_cap;
1495
1496 ENTER();
1497
1498 if (bands & BAND_A)
1499 usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
1500 else
1501 usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
1502
1503 /* Fill HT cap info */
1504 if (fill)
1505 wlan_fill_cap_info(priv, &pht_cap->ht_cap, bands);
1506 else
1507 wlan_reset_cap_info(priv, &pht_cap->ht_cap, bands);
1508
1509 pht_cap->ht_cap.ht_cap_info =
1510 wlan_cpu_to_le16(pht_cap->ht_cap.ht_cap_info);
1511
1512 /* Set ampdu param */
1513 SETAMPDU_SIZE(pht_cap->ht_cap.ampdu_param, AMPDU_FACTOR_64K);
1514 SETAMPDU_SPACING(pht_cap->ht_cap.ampdu_param, 0);
1515
1516 rx_mcs_supp = GET_RXMCSSUPP(priv->usr_dev_mcs_support);
1517 #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
1518 defined(PCIE9097) || defined(SD9097) || defined(USB9097) || \
1519 defined(SDNW62X) || defined(PCIENW62X) || defined(USBNW62X)
1520 if (IS_CARD9098(pmadapter->card_type) ||
1521 IS_CARDNW62X(pmadapter->card_type) ||
1522 IS_CARD9097(pmadapter->card_type)) {
1523 if (bands & BAND_A)
1524 rx_mcs_supp = MIN(
1525 rx_mcs_supp,
1526 GET_RXMCSSUPP(pmadapter->user_htstream >> 8));
1527 else
1528 rx_mcs_supp =
1529 MIN(rx_mcs_supp,
1530 GET_RXMCSSUPP(pmadapter->user_htstream));
1531 }
1532 #endif
1533 memset(pmadapter, (t_u8 *)pht_cap->ht_cap.supported_mcs_set, 0xff,
1534 rx_mcs_supp);
1535 /* Clear all the other values to get the minimum mcs set btw STA and AP
1536 */
1537 memset(pmadapter,
1538 (t_u8 *)&pht_cap->ht_cap.supported_mcs_set[rx_mcs_supp], 0,
1539 NUM_MCS_FIELD - rx_mcs_supp);
1540 /* Set MCS32 with 40MHz support */
1541 /* if current channel only support 20MHz, we should not set 40Mz
1542 * supprot*/
1543 if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
1544 !(priv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
1545 priv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS) &&
1546 pmadapter->init_para.mcs32 == 1)
1547 SETHT_MCS32(pht_cap->ht_cap.supported_mcs_set);
1548
1549 /* Clear RD responder bit */
1550 RESETHT_EXTCAP_RDG(pht_cap->ht_cap.ht_ext_cap);
1551 pht_cap->ht_cap.ht_ext_cap =
1552 wlan_cpu_to_le16(pht_cap->ht_cap.ht_ext_cap);
1553
1554 /* Set Tx BF cap */
1555 pht_cap->ht_cap.tx_bf_cap = wlan_cpu_to_le32(priv->tx_bf_cap);
1556
1557 LEAVE();
1558 return;
1559 }
1560
1561 /**
1562 * @brief This function fills the HT cap ie
1563 *
1564 * @param priv A pointer to mlan_private structure
1565 * @param pht_cap A pointer to IEEEtypes_HTCap_t structure
1566 * @param bands Band configuration
1567 *
1568 * @return N/A
1569 */
wlan_fill_ht_cap_ie(mlan_private * priv,IEEEtypes_HTCap_t * pht_cap,t_u16 bands)1570 void wlan_fill_ht_cap_ie(mlan_private *priv, IEEEtypes_HTCap_t *pht_cap,
1571 t_u16 bands)
1572 {
1573 mlan_adapter *pmadapter = priv->adapter;
1574 int rx_mcs_supp;
1575 t_u32 usr_dot_11n_dev_cap;
1576
1577 ENTER();
1578
1579 pht_cap->ieee_hdr.element_id = HT_CAPABILITY;
1580 pht_cap->ieee_hdr.len = sizeof(HTCap_t);
1581 if (bands & BAND_A)
1582 usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_a;
1583 else
1584 usr_dot_11n_dev_cap = priv->usr_dot_11n_dev_cap_bg;
1585
1586 /* Fill HT cap info */
1587 wlan_fill_cap_info(priv, &pht_cap->ht_cap, bands);
1588
1589 /* Set ampdu param */
1590 SETAMPDU_SIZE(pht_cap->ht_cap.ampdu_param, AMPDU_FACTOR_64K);
1591 SETAMPDU_SPACING(pht_cap->ht_cap.ampdu_param, 0);
1592
1593 rx_mcs_supp = GET_RXMCSSUPP(priv->usr_dev_mcs_support);
1594 #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \
1595 defined(PCIE9097) || defined(SD9097) || defined(USB9097) || \
1596 defined(SDNW62X) || defined(PCIENW62X) || defined(USBNW62X)
1597 if (IS_CARD9098(pmadapter->card_type) ||
1598 IS_CARDNW62X(pmadapter->card_type) ||
1599 IS_CARD9097(pmadapter->card_type)) {
1600 if (bands & BAND_A)
1601 rx_mcs_supp = MIN(
1602 rx_mcs_supp,
1603 GET_RXMCSSUPP(pmadapter->user_htstream >> 8));
1604 else
1605 rx_mcs_supp =
1606 MIN(rx_mcs_supp,
1607 GET_RXMCSSUPP(pmadapter->user_htstream));
1608 }
1609 #endif
1610 memset(pmadapter, (t_u8 *)pht_cap->ht_cap.supported_mcs_set, 0xff,
1611 rx_mcs_supp);
1612 /* Clear all the other values to get the minimum mcs set btw STA and AP
1613 */
1614 memset(pmadapter,
1615 (t_u8 *)&pht_cap->ht_cap.supported_mcs_set[rx_mcs_supp], 0,
1616 NUM_MCS_FIELD - rx_mcs_supp);
1617 /* Set MCS32 with 40MHz support */
1618 /* if current channel only support 20MHz, we should not set 40Mz
1619 * supprot*/
1620 if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
1621 !(priv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
1622 priv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS) &&
1623 pmadapter->init_para.mcs32 == 1)
1624 SETHT_MCS32(pht_cap->ht_cap.supported_mcs_set);
1625
1626 /* Clear RD responder bit */
1627 RESETHT_EXTCAP_RDG(pht_cap->ht_cap.ht_ext_cap);
1628
1629 /* Set Tx BF cap */
1630 pht_cap->ht_cap.tx_bf_cap = priv->tx_bf_cap;
1631
1632 LEAVE();
1633 return;
1634 }
1635 #endif /* STA_SUPPORT */
1636
1637 /**
1638 * @brief This function prints the 802.11n device capability
1639 *
1640 * @param pmadapter A pointer to mlan_adapter structure
1641 * @param cap Capability value
1642 *
1643 * @return N/A
1644 */
wlan_show_dot11ndevcap(pmlan_adapter pmadapter,t_u32 cap)1645 void wlan_show_dot11ndevcap(pmlan_adapter pmadapter, t_u32 cap)
1646 {
1647 ENTER();
1648
1649 PRINTM(MINFO, "GET_HW_SPEC: Maximum MSDU length = %s octets\n",
1650 (ISSUPP_MAXAMSDU(cap) ? "7935" : "3839"));
1651 PRINTM(MINFO, "GET_HW_SPEC: Beam forming %s\n",
1652 (ISSUPP_BEAMFORMING(cap) ? "supported" : "not supported"));
1653 PRINTM(MINFO, "GET_HW_SPEC: Greenfield preamble %s\n",
1654 (ISSUPP_GREENFIELD(cap) ? "supported" : "not supported"));
1655 PRINTM(MINFO, "GET_HW_SPEC: AMPDU %s\n",
1656 (ISSUPP_AMPDU(cap) ? "supported" : "not supported"));
1657 PRINTM(MINFO, "GET_HW_SPEC: MIMO Power Save %s\n",
1658 (ISSUPP_MIMOPS(cap) ? "supported" : "not supported"));
1659 PRINTM(MINFO, "GET_HW_SPEC: Rx STBC %s\n",
1660 (ISSUPP_RXSTBC(cap) ? "supported" : "not supported"));
1661 PRINTM(MINFO, "GET_HW_SPEC: Tx STBC %s\n",
1662 (ISSUPP_TXSTBC(cap) ? "supported" : "not supported"));
1663 PRINTM(MINFO, "GET_HW_SPEC: Short GI for 40 Mhz %s\n",
1664 (ISSUPP_SHORTGI40(cap) ? "supported" : "not supported"));
1665 PRINTM(MINFO, "GET_HW_SPEC: Short GI for 20 Mhz %s\n",
1666 (ISSUPP_SHORTGI20(cap) ? "supported" : "not supported"));
1667 PRINTM(MINFO, "GET_HW_SPEC: LDPC coded packet receive %s\n",
1668 (ISSUPP_RXLDPC(cap) ? "supported" : "not supported"));
1669
1670 PRINTM(MINFO, "GET_HW_SPEC: Number of Tx BA streams supported = %d\n",
1671 ISSUPP_GETTXBASTREAM(cap));
1672 PRINTM(MINFO, "GET_HW_SPEC: 40 Mhz channel width %s\n",
1673 (ISSUPP_CHANWIDTH40(cap) ? "supported" : "not supported"));
1674 PRINTM(MINFO, "GET_HW_SPEC: 20 Mhz channel width %s\n",
1675 (ISSUPP_CHANWIDTH20(cap) ? "supported" : "not supported"));
1676 PRINTM(MINFO, "GET_HW_SPEC: 10 Mhz channel width %s\n",
1677 (ISSUPP_CHANWIDTH10(cap) ? "supported" : "not supported"));
1678
1679 if (ISSUPP_RXANTENNAA(cap))
1680 PRINTM(MINFO, "GET_HW_SPEC: Presence of Rx antenna A\n");
1681 if (ISSUPP_RXANTENNAB(cap))
1682 PRINTM(MINFO, "GET_HW_SPEC: Presence of Rx antenna B\n");
1683 if (ISSUPP_RXANTENNAC(cap))
1684 PRINTM(MINFO, "GET_HW_SPEC: Presence of Rx antenna C\n");
1685 if (ISSUPP_RXANTENNAD(cap))
1686 PRINTM(MINFO, "GET_HW_SPEC: Presence of Rx antenna D\n");
1687 if (ISSUPP_TXANTENNAA(cap))
1688 PRINTM(MINFO, "GET_HW_SPEC: Presence of Tx antenna A\n");
1689 if (ISSUPP_TXANTENNAB(cap))
1690 PRINTM(MINFO, "GET_HW_SPEC: Presence of Tx antenna B\n");
1691 if (ISSUPP_TXANTENNAC(cap))
1692 PRINTM(MINFO, "GET_HW_SPEC: Presence of Tx antenna C\n");
1693 if (ISSUPP_TXANTENNAD(cap))
1694 PRINTM(MINFO, "GET_HW_SPEC: Presence of Tx antenna D\n");
1695
1696 LEAVE();
1697 return;
1698 }
1699
1700 /**
1701 * @brief This function prints the 802.11n device MCS
1702 *
1703 * @param pmadapter A pointer to mlan_adapter structure
1704 * @param support Support value
1705 *
1706 * @return N/A
1707 */
wlan_show_devmcssupport(pmlan_adapter pmadapter,t_u8 support)1708 void wlan_show_devmcssupport(pmlan_adapter pmadapter, t_u8 support)
1709 {
1710 ENTER();
1711
1712 PRINTM(MINFO, "GET_HW_SPEC: MCSs for %dx%d MIMO\n",
1713 GET_RXMCSSUPP(support), GET_TXMCSSUPP(support));
1714
1715 LEAVE();
1716 return;
1717 }
1718
1719 /**
1720 * @brief This function handles the command response of
1721 * delete a block ack request
1722 *
1723 * @param priv A pointer to mlan_private structure
1724 * @param resp A pointer to HostCmd_DS_COMMAND
1725 *
1726 * @return MLAN_STATUS_SUCCESS
1727 */
wlan_ret_11n_delba(mlan_private * priv,HostCmd_DS_COMMAND * resp)1728 mlan_status wlan_ret_11n_delba(mlan_private *priv, HostCmd_DS_COMMAND *resp)
1729 {
1730 int tid;
1731 TxBAStreamTbl *ptx_ba_tbl;
1732 HostCmd_DS_11N_DELBA *pdel_ba =
1733 (HostCmd_DS_11N_DELBA *)&resp->params.del_ba;
1734
1735 ENTER();
1736
1737 pdel_ba->del_ba_param_set = wlan_le16_to_cpu(pdel_ba->del_ba_param_set);
1738 pdel_ba->reason_code = wlan_le16_to_cpu(pdel_ba->reason_code);
1739
1740 tid = pdel_ba->del_ba_param_set >> DELBA_TID_POS;
1741 if (pdel_ba->del_result == BA_RESULT_SUCCESS) {
1742 mlan_11n_delete_bastream_tbl(
1743 priv, tid, pdel_ba->peer_mac_addr, TYPE_DELBA_SENT,
1744 INITIATOR_BIT(pdel_ba->del_ba_param_set), 0);
1745 wlan_request_ralist_lock(priv);
1746 ptx_ba_tbl = wlan_11n_get_txbastream_status(
1747 priv, BA_STREAM_SETUP_INPROGRESS);
1748 wlan_release_ralist_lock(priv);
1749 if (ptx_ba_tbl)
1750 wlan_send_addba(priv, ptx_ba_tbl->tid, ptx_ba_tbl->ra);
1751 } else { /*
1752 * In case of failure, recreate
1753 * the deleted stream in case
1754 * we initiated the ADDBA
1755 */
1756 if (INITIATOR_BIT(pdel_ba->del_ba_param_set)) {
1757 wlan_request_ralist_lock(priv);
1758 if (!wlan_11n_get_txbastream_tbl(
1759 priv, tid, pdel_ba->peer_mac_addr, MFALSE))
1760 wlan_11n_create_txbastream_tbl(
1761 priv, pdel_ba->peer_mac_addr, tid,
1762 BA_STREAM_SETUP_INPROGRESS);
1763 ptx_ba_tbl = wlan_11n_get_txbastream_status(
1764 priv, BA_STREAM_SETUP_INPROGRESS);
1765 wlan_release_ralist_lock(priv);
1766 if (ptx_ba_tbl) {
1767 mlan_11n_delete_bastream_tbl(
1768 priv, ptx_ba_tbl->tid, ptx_ba_tbl->ra,
1769 TYPE_DELBA_SENT, MTRUE, 0);
1770 }
1771 }
1772 }
1773
1774 LEAVE();
1775 return MLAN_STATUS_SUCCESS;
1776 }
1777
1778 /**
1779 * @brief This function handles the command response of
1780 * add a block ack request
1781 *
1782 * @param priv A pointer to mlan_private structure
1783 * @param resp A pointer to HostCmd_DS_COMMAND
1784 *
1785 * @return MLAN_STATUS_SUCCESS
1786 */
wlan_ret_11n_addba_req(mlan_private * priv,HostCmd_DS_COMMAND * resp)1787 mlan_status wlan_ret_11n_addba_req(mlan_private *priv, HostCmd_DS_COMMAND *resp)
1788 {
1789 t_u8 tid;
1790 HostCmd_DS_11N_ADDBA_RSP *padd_ba_rsp =
1791 (HostCmd_DS_11N_ADDBA_RSP *)&resp->params.add_ba_rsp;
1792 TxBAStreamTbl *ptx_ba_tbl;
1793 raListTbl *ra_list = MNULL;
1794 int tid_down;
1795
1796 ENTER();
1797
1798 padd_ba_rsp->block_ack_param_set =
1799 wlan_le16_to_cpu(padd_ba_rsp->block_ack_param_set);
1800 padd_ba_rsp->block_ack_tmo =
1801 wlan_le16_to_cpu(padd_ba_rsp->block_ack_tmo);
1802 padd_ba_rsp->ssn = (wlan_le16_to_cpu(padd_ba_rsp->ssn)) & SSN_MASK;
1803 padd_ba_rsp->status_code = wlan_le16_to_cpu(padd_ba_rsp->status_code);
1804
1805 tid = (padd_ba_rsp->block_ack_param_set & BLOCKACKPARAM_TID_MASK) >>
1806 BLOCKACKPARAM_TID_POS;
1807 tid_down = wlan_get_wmm_tid_down(priv, tid);
1808 ra_list = wlan_wmm_get_ralist_node(priv, tid_down,
1809 padd_ba_rsp->peer_mac_addr);
1810 if (padd_ba_rsp->status_code == BA_RESULT_SUCCESS) {
1811 ptx_ba_tbl = wlan_11n_get_txbastream_tbl(
1812 priv, tid, padd_ba_rsp->peer_mac_addr, MTRUE);
1813 if (ptx_ba_tbl) {
1814 PRINTM(MCMND,
1815 "ADDBA REQ: " MACSTR
1816 " tid=%d ssn=%d win_size=%d,amsdu=%d\n",
1817 MAC2STR(padd_ba_rsp->peer_mac_addr), tid,
1818 padd_ba_rsp->ssn,
1819 ((padd_ba_rsp->block_ack_param_set &
1820 BLOCKACKPARAM_WINSIZE_MASK) >>
1821 BLOCKACKPARAM_WINSIZE_POS),
1822 padd_ba_rsp->block_ack_param_set &
1823 BLOCKACKPARAM_AMSDU_SUPP_MASK);
1824 ptx_ba_tbl->ba_status = BA_STREAM_SETUP_COMPLETE;
1825 if ((padd_ba_rsp->block_ack_param_set &
1826 BLOCKACKPARAM_AMSDU_SUPP_MASK) &&
1827 priv->add_ba_param.tx_amsdu &&
1828 (priv->aggr_prio_tbl[tid].amsdu !=
1829 BA_STREAM_NOT_ALLOWED))
1830 ptx_ba_tbl->amsdu = MTRUE;
1831 else
1832 ptx_ba_tbl->amsdu = MFALSE;
1833 if (ra_list) {
1834 ra_list->amsdu_in_ampdu = ptx_ba_tbl->amsdu;
1835 ra_list->ba_status = BA_STREAM_SETUP_COMPLETE;
1836 }
1837 } else {
1838 PRINTM(MERROR, "BA stream not created\n");
1839 }
1840 } else {
1841 if (ra_list) {
1842 ra_list->amsdu_in_ampdu = MFALSE;
1843 ra_list->ba_status = BA_STREAM_NOT_SETUP;
1844 }
1845 mlan_11n_delete_bastream_tbl(priv, tid,
1846 padd_ba_rsp->peer_mac_addr,
1847 TYPE_DELBA_SENT, MTRUE, 0);
1848 if (padd_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) {
1849 #ifdef UAP_SUPPORT
1850 if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
1851 disable_station_ampdu(
1852 priv, tid, padd_ba_rsp->peer_mac_addr);
1853 #endif /* UAP_SUPPORT */
1854 if (ra_list && ra_list->is_tdls_link)
1855 disable_station_ampdu(
1856 priv, tid, padd_ba_rsp->peer_mac_addr);
1857 priv->aggr_prio_tbl[tid].ampdu_ap =
1858 BA_STREAM_NOT_ALLOWED;
1859
1860 } else {
1861 if (ra_list) {
1862 ra_list->packet_count = 0;
1863 ra_list->ba_packet_threshold =
1864 wlan_get_random_ba_threshold(
1865 priv->adapter);
1866 }
1867 }
1868 }
1869
1870 LEAVE();
1871 return MLAN_STATUS_SUCCESS;
1872 }
1873
1874 /**
1875 * @brief This function restore tx_pause flag
1876 *
1877 * @param priv A pointer to mlan_private structure
1878 * @param flag MTRUE/MFALSE;
1879 *
1880 * @return N/A
1881 */
wlan_set_tx_pause_flag(mlan_private * priv,t_u8 flag)1882 void wlan_set_tx_pause_flag(mlan_private *priv, t_u8 flag)
1883 {
1884 mlan_private *pmpriv = MNULL;
1885 t_u8 i;
1886 for (i = 0; i < priv->adapter->priv_num; i++) {
1887 pmpriv = priv->adapter->priv[i];
1888 if (pmpriv)
1889 pmpriv->tx_pause = flag;
1890 }
1891 }
1892
1893 /**
1894 * @brief This function prepares command of reconfigure tx buf
1895 *
1896 * @param priv A pointer to mlan_private structure
1897 * @param cmd A pointer to HostCmd_DS_COMMAND structure
1898 * @param cmd_action The action: GET or SET
1899 * @param pdata_buf A pointer to data buffer
1900 *
1901 * @return MLAN_STATUS_SUCCESS
1902 */
wlan_cmd_recfg_tx_buf(mlan_private * priv,HostCmd_DS_COMMAND * cmd,int cmd_action,void * pdata_buf)1903 mlan_status wlan_cmd_recfg_tx_buf(mlan_private *priv, HostCmd_DS_COMMAND *cmd,
1904 int cmd_action, void *pdata_buf)
1905 {
1906 HostCmd_DS_TXBUF_CFG *ptx_buf = &cmd->params.tx_buf;
1907 t_u16 action = (t_u16)cmd_action;
1908 t_u16 buf_size = *((t_u16 *)pdata_buf);
1909
1910 ENTER();
1911 cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RECONFIGURE_TX_BUFF);
1912 cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_TXBUF_CFG) + S_DS_GEN);
1913 ptx_buf->action = wlan_cpu_to_le16(action);
1914 switch (action) {
1915 case HostCmd_ACT_GEN_SET:
1916 PRINTM(MCMND, "set tx_buf = %d\n", buf_size);
1917 ptx_buf->buff_size = wlan_cpu_to_le16(buf_size);
1918 /** stop tx traffic */
1919 wlan_set_tx_pause_flag(priv, MTRUE);
1920 break;
1921 case HostCmd_ACT_GEN_GET:
1922 default:
1923 ptx_buf->buff_size = 0;
1924 break;
1925 }
1926 LEAVE();
1927 return MLAN_STATUS_SUCCESS;
1928 }
1929
1930 /**
1931 * @brief This function prepares command of amsdu aggr control
1932 *
1933 * @param priv A pointer to mlan_private structure
1934 * @param cmd A pointer to HostCmd_DS_COMMAND structure
1935 * @param cmd_action The action: GET or SET
1936 * @param pdata_buf A pointer to data buffer
1937 *
1938 * @return MLAN_STATUS_SUCCESS
1939 */
wlan_cmd_amsdu_aggr_ctrl(mlan_private * priv,HostCmd_DS_COMMAND * cmd,int cmd_action,void * pdata_buf)1940 mlan_status wlan_cmd_amsdu_aggr_ctrl(mlan_private *priv,
1941 HostCmd_DS_COMMAND *cmd, int cmd_action,
1942 void *pdata_buf)
1943 {
1944 HostCmd_DS_AMSDU_AGGR_CTRL *pamsdu_ctrl = &cmd->params.amsdu_aggr_ctrl;
1945 t_u16 action = (t_u16)cmd_action;
1946 mlan_ds_11n_amsdu_aggr_ctrl *aa_ctrl =
1947 (mlan_ds_11n_amsdu_aggr_ctrl *)pdata_buf;
1948
1949 ENTER();
1950
1951 cmd->command = wlan_cpu_to_le16(HostCmd_CMD_AMSDU_AGGR_CTRL);
1952 cmd->size =
1953 wlan_cpu_to_le16(sizeof(HostCmd_DS_AMSDU_AGGR_CTRL) + S_DS_GEN);
1954 pamsdu_ctrl->action = wlan_cpu_to_le16(action);
1955 switch (action) {
1956 case HostCmd_ACT_GEN_SET:
1957 pamsdu_ctrl->enable = wlan_cpu_to_le16(aa_ctrl->enable);
1958 pamsdu_ctrl->curr_buf_size = 0;
1959 break;
1960 case HostCmd_ACT_GEN_GET:
1961 default:
1962 pamsdu_ctrl->curr_buf_size = 0;
1963 break;
1964 }
1965 LEAVE();
1966 return MLAN_STATUS_SUCCESS;
1967 }
1968
1969 /**
1970 * @brief This function handles the command response of amsdu aggr ctrl
1971 *
1972 * @param pmpriv A pointer to mlan_private structure
1973 * @param resp A pointer to HostCmd_DS_COMMAND
1974 * @param pioctl_buf A pointer to mlan_ioctl_req structure
1975 *
1976 * @return MLAN_STATUS_SUCCESS
1977 */
wlan_ret_amsdu_aggr_ctrl(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)1978 mlan_status wlan_ret_amsdu_aggr_ctrl(pmlan_private pmpriv,
1979 HostCmd_DS_COMMAND *resp,
1980 mlan_ioctl_req *pioctl_buf)
1981 {
1982 mlan_ds_11n_cfg *cfg = MNULL;
1983 HostCmd_DS_AMSDU_AGGR_CTRL *amsdu_ctrl = &resp->params.amsdu_aggr_ctrl;
1984
1985 ENTER();
1986
1987 if (pioctl_buf) {
1988 cfg = (mlan_ds_11n_cfg *)pioctl_buf->pbuf;
1989 cfg->param.amsdu_aggr_ctrl.enable =
1990 wlan_le16_to_cpu(amsdu_ctrl->enable);
1991 cfg->param.amsdu_aggr_ctrl.curr_buf_size =
1992 wlan_le16_to_cpu(amsdu_ctrl->curr_buf_size);
1993 }
1994 LEAVE();
1995 return MLAN_STATUS_SUCCESS;
1996 }
1997
1998 /**
1999 * @brief This function prepares 11n cfg command
2000 *
2001 * @param pmpriv A pointer to mlan_private structure
2002 * @param cmd A pointer to HostCmd_DS_COMMAND structure
2003 * @param cmd_action the action: GET or SET
2004 * @param pdata_buf A pointer to data buffer
2005 * @return MLAN_STATUS_SUCCESS
2006 */
wlan_cmd_11n_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)2007 mlan_status wlan_cmd_11n_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
2008 t_u16 cmd_action, t_void *pdata_buf)
2009 {
2010 HostCmd_DS_11N_CFG *htcfg = &cmd->params.htcfg;
2011 mlan_ds_11n_tx_cfg *txcfg = (mlan_ds_11n_tx_cfg *)pdata_buf;
2012
2013 ENTER();
2014 cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11N_CFG);
2015 cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_11N_CFG) + S_DS_GEN);
2016 htcfg->action = wlan_cpu_to_le16(cmd_action);
2017 htcfg->ht_tx_cap = wlan_cpu_to_le16(txcfg->httxcap);
2018 htcfg->ht_tx_info = wlan_cpu_to_le16(txcfg->httxinfo);
2019 htcfg->misc_config = wlan_cpu_to_le16(txcfg->misc_cfg);
2020 LEAVE();
2021 return MLAN_STATUS_SUCCESS;
2022 }
2023
2024 /**
2025 * @brief This function handles the command response of 11ncfg
2026 *
2027 * @param pmpriv A pointer to mlan_private structure
2028 * @param resp A pointer to HostCmd_DS_COMMAND
2029 * @param pioctl_buf A pointer to mlan_ioctl_req structure
2030 *
2031 * @return MLAN_STATUS_SUCCESS
2032 */
wlan_ret_11n_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)2033 mlan_status wlan_ret_11n_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
2034 mlan_ioctl_req *pioctl_buf)
2035 {
2036 mlan_ds_11n_cfg *cfg = MNULL;
2037 HostCmd_DS_11N_CFG *htcfg = &resp->params.htcfg;
2038
2039 ENTER();
2040 if (pioctl_buf &&
2041 (wlan_le16_to_cpu(htcfg->action) == HostCmd_ACT_GEN_GET)) {
2042 cfg = (mlan_ds_11n_cfg *)pioctl_buf->pbuf;
2043 cfg->param.tx_cfg.httxcap = wlan_le16_to_cpu(htcfg->ht_tx_cap);
2044 cfg->param.tx_cfg.httxinfo =
2045 wlan_le16_to_cpu(htcfg->ht_tx_info);
2046 cfg->param.tx_cfg.misc_cfg =
2047 wlan_le16_to_cpu(htcfg->misc_config);
2048 }
2049 LEAVE();
2050 return MLAN_STATUS_SUCCESS;
2051 }
2052
2053 /**
2054 * @brief This function prepares reject addba req command
2055 *
2056 * @param pmpriv A pointer to mlan_private structure
2057 * @param cmd A pointer to HostCmd_DS_COMMAND structure
2058 * @param cmd_action the action: GET or SET
2059 * @param pdata_buf A pointer to data buffer
2060 * @return MLAN_STATUS_SUCCESS
2061 */
wlan_cmd_reject_addba_req(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)2062 mlan_status wlan_cmd_reject_addba_req(pmlan_private pmpriv,
2063 HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
2064 t_void *pdata_buf)
2065 {
2066 HostCmd_DS_REJECT_ADDBA_REQ *preject_addba_req =
2067 &cmd->params.rejectaddbareq;
2068 mlan_ds_reject_addba_req *prejaddbareq =
2069 (mlan_ds_reject_addba_req *)pdata_buf;
2070
2071 ENTER();
2072 cmd->command = wlan_cpu_to_le16(HostCmd_CMD_REJECT_ADDBA_REQ);
2073 cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_REJECT_ADDBA_REQ) +
2074 S_DS_GEN);
2075 preject_addba_req->action = wlan_cpu_to_le16(cmd_action);
2076 preject_addba_req->conditions =
2077 wlan_cpu_to_le32(prejaddbareq->conditions);
2078 LEAVE();
2079 return MLAN_STATUS_SUCCESS;
2080 }
2081
2082 /**
2083 * @brief This function handles the command response of reject addba req
2084 *
2085 * @param pmpriv A pointer to mlan_private structure
2086 * @param resp A pointer to HostCmd_DS_COMMAND
2087 * @param pioctl_buf A pointer to mlan_ioctl_req structure
2088 *
2089 * @return MLAN_STATUS_SUCCESS
2090 */
wlan_ret_reject_addba_req(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)2091 mlan_status wlan_ret_reject_addba_req(pmlan_private pmpriv,
2092 HostCmd_DS_COMMAND *resp,
2093 mlan_ioctl_req *pioctl_buf)
2094 {
2095 mlan_ds_11n_cfg *cfg = MNULL;
2096 HostCmd_DS_REJECT_ADDBA_REQ *preject_addba_req =
2097 &resp->params.rejectaddbareq;
2098
2099 ENTER();
2100 if (pioctl_buf && (wlan_le16_to_cpu(preject_addba_req->action) ==
2101 HostCmd_ACT_GEN_GET)) {
2102 cfg = (mlan_ds_11n_cfg *)pioctl_buf->pbuf;
2103 cfg->param.reject_addba_req.conditions =
2104 wlan_le32_to_cpu(preject_addba_req->conditions);
2105 }
2106 LEAVE();
2107 return MLAN_STATUS_SUCCESS;
2108 }
2109
2110 /**
2111 * @brief This function prepares TX BF configuration command
2112 *
2113 * @param pmpriv A pointer to mlan_private structure
2114 * @param cmd A pointer to HostCmd_DS_COMMAND structure
2115 * @param cmd_action The action: GET or SET
2116 * @param pdata_buf A pointer to data buffer
2117 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2118 */
wlan_cmd_tx_bf_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)2119 mlan_status wlan_cmd_tx_bf_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
2120 t_u16 cmd_action, t_void *pdata_buf)
2121 {
2122 pmlan_adapter pmadapter = pmpriv->adapter;
2123 HostCmd_DS_TX_BF_CFG *txbfcfg = &cmd->params.tx_bf_cfg;
2124 mlan_ds_11n_tx_bf_cfg *txbf = (mlan_ds_11n_tx_bf_cfg *)pdata_buf;
2125
2126 ENTER();
2127
2128 cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TX_BF_CFG);
2129 cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_TX_BF_CFG) + S_DS_GEN);
2130
2131 if (txbf->bf_action == SET_GET_BF_PERIODICITY) {
2132 memcpy_ext(pmadapter, txbfcfg->body.bf_periodicity.peer_mac,
2133 txbf->body.bf_periodicity[0].peer_mac,
2134 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
2135 }
2136 txbfcfg->action = wlan_cpu_to_le16(txbf->action);
2137 txbfcfg->bf_action = wlan_cpu_to_le16(txbf->bf_action);
2138 if (cmd_action == HostCmd_ACT_GEN_SET) {
2139 switch (txbf->bf_action) {
2140 case BF_GLOBAL_CONFIGURATION:
2141 txbfcfg->body.bf_global_cfg.bf_enbl =
2142 txbf->body.bf_global_cfg.bf_enbl;
2143 txbfcfg->body.bf_global_cfg.sounding_enbl =
2144 txbf->body.bf_global_cfg.sounding_enbl;
2145 txbfcfg->body.bf_global_cfg.fb_type =
2146 txbf->body.bf_global_cfg.fb_type;
2147 txbfcfg->body.bf_global_cfg.snr_threshold =
2148 txbf->body.bf_global_cfg.snr_threshold;
2149 txbfcfg->body.bf_global_cfg.sounding_interval =
2150 wlan_cpu_to_le16(txbf->body.bf_global_cfg
2151 .sounding_interval);
2152 txbfcfg->body.bf_global_cfg.bf_mode =
2153 txbf->body.bf_global_cfg.bf_mode;
2154 break;
2155 case TRIGGER_SOUNDING_FOR_PEER:
2156 memcpy_ext(pmadapter,
2157 txbfcfg->body.bf_sound_args.peer_mac,
2158 txbf->body.bf_sound[0].peer_mac,
2159 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
2160 break;
2161 case SET_GET_BF_PERIODICITY:
2162 txbfcfg->body.bf_periodicity.interval =
2163 wlan_cpu_to_le16(
2164 txbf->body.bf_periodicity->interval);
2165 break;
2166 case TX_BF_FOR_PEER_ENBL:
2167 memcpy_ext(pmadapter, txbfcfg->body.tx_bf_peer.peer_mac,
2168 txbf->body.tx_bf_peer[0].peer_mac,
2169 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
2170 txbfcfg->body.tx_bf_peer.bf_enbl =
2171 txbf->body.tx_bf_peer[0].bf_enbl;
2172 txbfcfg->body.tx_bf_peer.sounding_enbl =
2173 txbf->body.tx_bf_peer[0].sounding_enbl;
2174 txbfcfg->body.tx_bf_peer.fb_type =
2175 txbf->body.tx_bf_peer[0].fb_type;
2176 break;
2177 case SET_SNR_THR_PEER:
2178 memcpy_ext(pmadapter, txbfcfg->body.bf_snr.peer_mac,
2179 txbf->body.bf_snr[0].peer_mac,
2180 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
2181 txbfcfg->body.bf_snr.snr = txbf->body.bf_snr[0].snr;
2182 break;
2183 default:
2184 LEAVE();
2185 return MLAN_STATUS_FAILURE;
2186 }
2187 }
2188
2189 LEAVE();
2190 return MLAN_STATUS_SUCCESS;
2191 }
2192
2193 /**
2194 * @brief This function handles the command response
2195 * of TX BF configuration
2196 *
2197 * @param pmpriv A pointer to mlan_private structure
2198 * @param resp A pointer to HostCmd_DS_COMMAND
2199 * @param pioctl_buf A pointer to mlan_ioctl_req structure
2200 *
2201 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2202 */
wlan_ret_tx_bf_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)2203 mlan_status wlan_ret_tx_bf_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
2204 mlan_ioctl_req *pioctl_buf)
2205 {
2206 pmlan_adapter pmadapter = pmpriv->adapter;
2207 HostCmd_DS_TX_BF_CFG *txbfcfg = &resp->params.tx_bf_cfg;
2208 mlan_ds_11n_cfg *cfg_11n = MNULL;
2209 mlan_ds_11n_tx_bf_cfg *txbf = MNULL;
2210 bf_peer_args *tx_bf_peer;
2211 bf_snr_thr_t *bf_snr;
2212 int i;
2213
2214 ENTER();
2215
2216 if (pioctl_buf) {
2217 cfg_11n = (mlan_ds_11n_cfg *)pioctl_buf->pbuf;
2218 txbf = (mlan_ds_11n_tx_bf_cfg *)&cfg_11n->param.tx_bf;
2219 txbf->bf_action = wlan_le16_to_cpu(txbfcfg->bf_action);
2220 switch (txbf->bf_action) {
2221 case BF_GLOBAL_CONFIGURATION:
2222 txbf->body.bf_global_cfg.bf_enbl =
2223 txbfcfg->body.bf_global_cfg.bf_enbl;
2224 txbf->body.bf_global_cfg.sounding_enbl =
2225 txbfcfg->body.bf_global_cfg.sounding_enbl;
2226 txbf->body.bf_global_cfg.fb_type =
2227 txbfcfg->body.bf_global_cfg.fb_type;
2228 txbf->body.bf_global_cfg.snr_threshold =
2229 txbfcfg->body.bf_global_cfg.snr_threshold;
2230 txbf->body.bf_global_cfg.sounding_interval =
2231 wlan_le16_to_cpu(txbfcfg->body.bf_global_cfg
2232 .sounding_interval);
2233 txbf->body.bf_global_cfg.bf_mode =
2234 txbfcfg->body.bf_global_cfg.bf_mode;
2235 break;
2236 case TRIGGER_SOUNDING_FOR_PEER:
2237 memcpy_ext(pmadapter, txbf->body.bf_sound[0].peer_mac,
2238 txbfcfg->body.bf_sound_args.peer_mac,
2239 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
2240 txbf->body.bf_sound[0].status =
2241 txbfcfg->body.bf_sound_args.status;
2242 break;
2243 case SET_GET_BF_PERIODICITY:
2244 memcpy_ext(pmadapter,
2245 txbf->body.bf_periodicity->peer_mac,
2246 txbfcfg->body.bf_periodicity.peer_mac,
2247 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
2248 txbf->body.bf_periodicity->interval = wlan_le16_to_cpu(
2249 txbfcfg->body.bf_periodicity.interval);
2250 break;
2251 case TX_BF_FOR_PEER_ENBL:
2252 txbf->no_of_peers = *(t_u8 *)&txbfcfg->body;
2253 tx_bf_peer = (bf_peer_args *)((t_u8 *)&txbfcfg->body +
2254 sizeof(t_u8));
2255 for (i = 0; i < (int)txbf->no_of_peers; i++) {
2256 memcpy_ext(pmadapter,
2257 txbf->body.tx_bf_peer[i].peer_mac,
2258 (t_u8 *)tx_bf_peer->peer_mac,
2259 MLAN_MAC_ADDR_LENGTH,
2260 MLAN_MAC_ADDR_LENGTH);
2261 txbf->body.tx_bf_peer[i].bf_enbl =
2262 tx_bf_peer->bf_enbl;
2263 txbf->body.tx_bf_peer[i].sounding_enbl =
2264 tx_bf_peer->sounding_enbl;
2265 txbf->body.tx_bf_peer[i].fb_type =
2266 tx_bf_peer->fb_type;
2267 tx_bf_peer++;
2268 }
2269 break;
2270 case SET_SNR_THR_PEER:
2271 txbf->no_of_peers = *(t_u8 *)&txbfcfg->body;
2272 bf_snr = (bf_snr_thr_t *)((t_u8 *)&txbfcfg->body +
2273 sizeof(t_u8));
2274 for (i = 0; i < (int)txbf->no_of_peers; i++) {
2275 memcpy_ext(pmadapter,
2276 txbf->body.bf_snr[i].peer_mac,
2277 (t_u8 *)bf_snr->peer_mac,
2278 MLAN_MAC_ADDR_LENGTH,
2279 MLAN_MAC_ADDR_LENGTH);
2280 txbf->body.bf_snr[i].snr = bf_snr->snr;
2281 bf_snr++;
2282 }
2283 break;
2284 default:
2285 LEAVE();
2286 return MLAN_STATUS_FAILURE;
2287 }
2288 }
2289
2290 LEAVE();
2291 return MLAN_STATUS_SUCCESS;
2292 }
2293
2294 /**
2295 * @brief Get second channel offset
2296 *
2297 * @param chan channel num
2298 * @return second channel offset
2299 */
wlan_get_second_channel_offset(mlan_private * priv,int chan)2300 t_u8 wlan_get_second_channel_offset(mlan_private *priv, int chan)
2301 {
2302 t_u8 chan2Offset = SEC_CHAN_NONE;
2303
2304 /* Special Case: 20Mhz-only Channel */
2305 if (priv->adapter->region_code != COUNTRY_CODE_US && chan == 165)
2306 return chan2Offset;
2307
2308 switch (chan) {
2309 case 36:
2310 case 44:
2311 case 52:
2312 case 60:
2313 case 100:
2314 case 108:
2315 case 116:
2316 case 124:
2317 case 132:
2318 case 140:
2319 case 149:
2320 case 157:
2321 case 165:
2322 case 173:
2323 chan2Offset = SEC_CHAN_ABOVE;
2324 break;
2325 case 40:
2326 case 48:
2327 case 56:
2328 case 64:
2329 case 104:
2330 case 112:
2331 case 120:
2332 case 128:
2333 case 136:
2334 case 144:
2335 case 153:
2336 case 161:
2337 case 169:
2338 case 177:
2339 chan2Offset = SEC_CHAN_BELOW;
2340 break;
2341 }
2342 return chan2Offset;
2343 }
2344
2345 #ifdef STA_SUPPORT
2346 /**
2347 * @brief validate the channel offset for Infra/Ad-hoc band configuration
2348 *
2349 * @param pmpriv A pointer to mlan_private structure
2350 * @param band band
2351 * @param chan primary channel
2352 * @param chan_bw channel bandwidth
2353 *
2354 * @return channel offset (NO_SEC_CHANNEL, SEC_CHANNEL_ABOVE,
2355 * SEC_CHANNEL_BELOW)
2356 */
wlan_validate_chan_offset(mlan_private * pmpriv,t_u16 band,t_u32 chan,t_u8 chan_bw)2357 t_u8 wlan_validate_chan_offset(mlan_private *pmpriv, t_u16 band, t_u32 chan,
2358 t_u8 chan_bw)
2359 {
2360 t_u8 chan_offset;
2361 pmlan_adapter pmadapter = pmpriv->adapter;
2362
2363 if (chan_bw == CHANNEL_BW_40MHZ_ABOVE)
2364 chan_offset = SEC_CHAN_ABOVE;
2365 else if (chan_bw == CHANNEL_BW_40MHZ_BELOW)
2366 chan_offset = SEC_CHAN_BELOW;
2367 else
2368 chan_offset = SEC_CHAN_NONE;
2369
2370 /* validation */
2371 if (chan_offset != SEC_CHAN_NONE) {
2372 if (band & BAND_GN) {
2373 if ((chan == 1) || (chan == 2) || (chan == 3) ||
2374 (chan == 4))
2375 chan_offset = SEC_CHAN_ABOVE;
2376 else if ((chan == 10) || (chan == 11) || (chan == 12) ||
2377 (chan == 13))
2378 chan_offset = SEC_CHAN_BELOW;
2379
2380 /* check if channel 12 is supported in the region */
2381 if (!wlan_find_cfp_by_band_and_channel(pmadapter, band,
2382 12))
2383 if ((chan == 8) || (chan == 9))
2384 chan_offset = SEC_CHAN_BELOW;
2385 } else if (band & BAND_AN)
2386 chan_offset =
2387 wlan_get_second_channel_offset(pmpriv, chan);
2388 }
2389 return chan_offset;
2390 }
2391
2392 /**
2393 * @brief This function check if ht40 is allowed in current region
2394 *
2395 * @param pmpriv A pointer to mlan_private structure
2396 * @param pbss_desc A pointer to BSSDescriptor_t structure
2397 *
2398 * @return MTRUE/MFALSE
2399 */
wlan_check_chan_width_ht40_by_region(mlan_private * pmpriv,BSSDescriptor_t * pbss_desc)2400 static int wlan_check_chan_width_ht40_by_region(mlan_private *pmpriv,
2401 BSSDescriptor_t *pbss_desc)
2402 {
2403 pmlan_adapter pmadapter = pmpriv->adapter;
2404 int i = 0;
2405 int cover_pri_chan = MFALSE;
2406 t_u8 pri_chan;
2407 t_u8 chan_offset;
2408 t_u8 num_cfp;
2409
2410 ENTER();
2411
2412 if (pbss_desc->pht_info == MNULL) {
2413 PRINTM(MERROR, "ht_info pointer NULL, force use HT20\n");
2414 LEAVE();
2415 return MFALSE;
2416 }
2417 if (pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS &&
2418 pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS) {
2419 LEAVE();
2420 return MFALSE;
2421 }
2422
2423 pri_chan = pbss_desc->pht_info->ht_info.pri_chan;
2424 chan_offset = GET_SECONDARYCHAN(pbss_desc->pht_info->ht_info.field2);
2425 if ((chan_offset == SEC_CHAN_ABOVE) &&
2426 (pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40PLUS)) {
2427 pmpriv->curr_chan_flags |=
2428 CHAN_FLAGS_NO_HT40MINUS | CHAN_FLAGS_NO_80MHZ;
2429 return MFALSE;
2430 }
2431 if ((chan_offset == SEC_CHAN_BELOW) &&
2432 (pmpriv->curr_chan_flags & CHAN_FLAGS_NO_HT40MINUS)) {
2433 pmpriv->curr_chan_flags |=
2434 CHAN_FLAGS_NO_HT40PLUS | CHAN_FLAGS_NO_80MHZ;
2435 return MFALSE;
2436 }
2437 if (pmpriv->curr_chan_flags & CHAN_FLAGS_MAX)
2438 return MTRUE;
2439
2440 num_cfp = pmadapter->region_channel[0].num_cfp;
2441
2442 if ((pbss_desc->bss_band & (BAND_B | BAND_G)) &&
2443 pmadapter->region_channel[0].valid) {
2444 for (i = 0; i < num_cfp; i++) {
2445 if (pri_chan ==
2446 pmadapter->region_channel[0].pcfp[i].channel) {
2447 cover_pri_chan = MTRUE;
2448 break;
2449 }
2450 }
2451 if (!cover_pri_chan) {
2452 PRINTM(MERROR, "Invalid channel, force use HT20\n");
2453 LEAVE();
2454 return MFALSE;
2455 }
2456
2457 if (chan_offset == SEC_CHAN_ABOVE) {
2458 if (pri_chan > num_cfp - 4) {
2459 PRINTM(MERROR,
2460 "Invalid second channel offset, force use HT20\n");
2461 LEAVE();
2462 return MFALSE;
2463 }
2464 }
2465 }
2466 LEAVE();
2467 return MTRUE;
2468 }
2469
2470 /**
2471 * @brief This function append the 802_11N tlv
2472 *
2473 * @param pmpriv A pointer to mlan_private structure
2474 * @param pbss_desc A pointer to BSSDescriptor_t structure
2475 * @param ppbuffer A Pointer to command buffer pointer
2476 *
2477 * @return bytes added to the buffer
2478 */
wlan_cmd_append_11n_tlv(mlan_private * pmpriv,BSSDescriptor_t * pbss_desc,t_u8 ** ppbuffer)2479 int wlan_cmd_append_11n_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc,
2480 t_u8 **ppbuffer)
2481 {
2482 pmlan_adapter pmadapter = pmpriv->adapter;
2483 MrvlIETypes_HTCap_t *pht_cap;
2484 MrvlIEtypes_ChanListParamSet_t *pchan_list;
2485 MrvlIETypes_2040BSSCo_t *p2040_bss_co;
2486 MrvlIETypes_ExtCap_t *pext_cap;
2487 t_u32 usr_dot_11n_dev_cap, orig_usr_dot_11n_dev_cap = 0;
2488 t_u8 usr_dot_11ac_bw;
2489 int ret_len = 0;
2490
2491 ENTER();
2492
2493 /* Null Checks */
2494 if (ppbuffer == MNULL) {
2495 LEAVE();
2496 return 0;
2497 }
2498 if (*ppbuffer == MNULL) {
2499 LEAVE();
2500 return 0;
2501 }
2502 if (pbss_desc == MNULL) {
2503 LEAVE();
2504 return 0;
2505 }
2506
2507 if (pbss_desc->bss_band & BAND_A)
2508 usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_a;
2509 else
2510 usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_bg;
2511
2512 if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
2513 usr_dot_11ac_bw = BW_FOLLOW_VHTCAP;
2514 else
2515 usr_dot_11ac_bw = pmpriv->usr_dot_11ac_bw;
2516 if ((pbss_desc->bss_band & (BAND_B | BAND_G | BAND_A)) &&
2517 ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
2518 !wlan_check_chan_width_ht40_by_region(pmpriv, pbss_desc)) {
2519 orig_usr_dot_11n_dev_cap = usr_dot_11n_dev_cap;
2520 RESETSUPP_CHANWIDTH40(usr_dot_11n_dev_cap);
2521 RESET_40MHZ_INTOLARENT(usr_dot_11n_dev_cap);
2522 RESETSUPP_SHORTGI40(usr_dot_11n_dev_cap);
2523 pmpriv->usr_dot_11n_dev_cap_bg = usr_dot_11n_dev_cap;
2524 pbss_desc->curr_bandwidth = BW_20MHZ;
2525 }
2526 if (pbss_desc->pht_cap) {
2527 pht_cap = (MrvlIETypes_HTCap_t *)*ppbuffer;
2528 memset(pmadapter, pht_cap, 0, sizeof(MrvlIETypes_HTCap_t));
2529 pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
2530 pht_cap->header.len = sizeof(HTCap_t);
2531 memcpy_ext(pmadapter,
2532 (t_u8 *)pht_cap + sizeof(MrvlIEtypesHeader_t),
2533 (t_u8 *)pbss_desc->pht_cap +
2534 sizeof(IEEEtypes_Header_t),
2535 pht_cap->header.len, pht_cap->header.len);
2536
2537 pht_cap->ht_cap.ht_cap_info =
2538 wlan_le16_to_cpu(pht_cap->ht_cap.ht_cap_info);
2539 pht_cap->ht_cap.ht_ext_cap =
2540 wlan_le16_to_cpu(pht_cap->ht_cap.ht_ext_cap);
2541 wlan_fill_ht_cap_tlv(pmpriv, pht_cap, pbss_desc->bss_band,
2542 MTRUE);
2543
2544 /** check if need support 80+80MHZ */
2545 /** reset the 2 spatial stream rate for 80 + 80 Mhz */
2546 if (wlan_is_80_80_support(pmpriv, pbss_desc))
2547 pht_cap->ht_cap.supported_mcs_set[1] = 0;
2548 HEXDUMP("HT_CAPABILITIES IE", (t_u8 *)pht_cap,
2549 sizeof(MrvlIETypes_HTCap_t));
2550 *ppbuffer += sizeof(MrvlIETypes_HTCap_t);
2551 ret_len += sizeof(MrvlIETypes_HTCap_t);
2552 pht_cap->header.len = wlan_cpu_to_le16(pht_cap->header.len);
2553 } else {
2554 // AP don't support 11N
2555 LEAVE();
2556 return 0;
2557 }
2558
2559 if (pbss_desc->pht_info) {
2560 pchan_list = (MrvlIEtypes_ChanListParamSet_t *)*ppbuffer;
2561 memset(pmadapter, pchan_list, 0,
2562 sizeof(MrvlIEtypes_ChanListParamSet_t));
2563 pchan_list->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
2564 pchan_list->header.len =
2565 sizeof(MrvlIEtypes_ChanListParamSet_t) -
2566 sizeof(MrvlIEtypesHeader_t);
2567 pchan_list->chan_scan_param[0].chan_number =
2568 pbss_desc->pht_info->ht_info.pri_chan;
2569 pchan_list->chan_scan_param[0].bandcfg.chanBand =
2570 wlan_band_to_radio_type(pbss_desc->bss_band);
2571 /* support the VHT if the network to be join has the VHT
2572 * operation */
2573 if (ISSUPP_11ACENABLED(pmadapter->fw_cap_info) &&
2574 (usr_dot_11ac_bw == BW_FOLLOW_VHTCAP) &&
2575 (!(pmpriv->curr_chan_flags & CHAN_FLAGS_NO_80MHZ)) &&
2576 wlan_11ac_bandconfig_allowed(pmpriv, pbss_desc->bss_band) &&
2577 pbss_desc->pvht_oprat &&
2578 pbss_desc->pvht_oprat->chan_width == VHT_OPER_CHWD_80MHZ) {
2579 pchan_list->chan_scan_param[0].bandcfg.chanWidth =
2580 CHAN_BW_80MHZ;
2581 pchan_list->chan_scan_param[0].bandcfg.chan2Offset =
2582 GET_SECONDARYCHAN(
2583 pbss_desc->pht_info->ht_info.field2);
2584 pbss_desc->curr_bandwidth = BW_80MHZ;
2585 } else if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
2586 ISALLOWED_CHANWIDTH40(
2587 pbss_desc->pht_info->ht_info.field2) &&
2588 wlan_check_chan_width_ht40_by_region(pmpriv,
2589 pbss_desc)) {
2590 pchan_list->chan_scan_param[0].bandcfg.chan2Offset =
2591 GET_SECONDARYCHAN(
2592 pbss_desc->pht_info->ht_info.field2);
2593 pbss_desc->curr_bandwidth = BW_40MHZ;
2594 pchan_list->chan_scan_param[0].bandcfg.chanWidth =
2595 CHAN_BW_40MHZ;
2596 }
2597 pchan_list->chan_scan_param[0].bandcfg.scanMode =
2598 SCAN_MODE_USER;
2599 HEXDUMP("ChanList", (t_u8 *)pchan_list,
2600 sizeof(MrvlIEtypes_ChanListParamSet_t));
2601 HEXDUMP("pht_info", (t_u8 *)pbss_desc->pht_info,
2602 sizeof(MrvlIETypes_HTInfo_t) - 2);
2603 *ppbuffer += sizeof(MrvlIEtypes_ChanListParamSet_t);
2604 ret_len += sizeof(MrvlIEtypes_ChanListParamSet_t);
2605 pchan_list->header.len =
2606 wlan_cpu_to_le16(pchan_list->header.len);
2607 }
2608
2609 if (pbss_desc->pbss_co_2040) {
2610 p2040_bss_co = (MrvlIETypes_2040BSSCo_t *)*ppbuffer;
2611 memset(pmadapter, p2040_bss_co, 0,
2612 sizeof(MrvlIETypes_2040BSSCo_t));
2613 p2040_bss_co->header.type = wlan_cpu_to_le16(BSSCO_2040);
2614 p2040_bss_co->header.len = sizeof(BSSCo2040_t);
2615
2616 memcpy_ext(pmadapter,
2617 (t_u8 *)p2040_bss_co + sizeof(MrvlIEtypesHeader_t),
2618 (t_u8 *)pbss_desc->pbss_co_2040 +
2619 sizeof(IEEEtypes_Header_t),
2620 p2040_bss_co->header.len, p2040_bss_co->header.len);
2621
2622 HEXDUMP("20/40 BSS Coexistence IE", (t_u8 *)p2040_bss_co,
2623 sizeof(MrvlIETypes_2040BSSCo_t));
2624 *ppbuffer += sizeof(MrvlIETypes_2040BSSCo_t);
2625 ret_len += sizeof(MrvlIETypes_2040BSSCo_t);
2626 p2040_bss_co->header.len =
2627 wlan_cpu_to_le16(p2040_bss_co->header.len);
2628 }
2629
2630 if (pbss_desc->pext_cap) {
2631 pext_cap = (MrvlIETypes_ExtCap_t *)*ppbuffer;
2632 memset(pmadapter, pext_cap, 0, sizeof(MrvlIETypes_ExtCap_t));
2633 pext_cap->header.type = wlan_cpu_to_le16(EXT_CAPABILITY);
2634 pext_cap->header.len = sizeof(ExtCap_t);
2635
2636 memcpy_ext(pmadapter,
2637 (t_u8 *)pext_cap + sizeof(MrvlIEtypesHeader_t),
2638 (t_u8 *)&pmpriv->ext_cap, sizeof(ExtCap_t),
2639 pext_cap->header.len);
2640 if (pbss_desc && pbss_desc->multi_bssid_ap)
2641 SET_EXTCAP_MULTI_BSSID(pext_cap->ext_cap);
2642 if (!pmadapter->ecsa_enable)
2643 RESET_EXTCAP_EXT_CHANNEL_SWITCH(pext_cap->ext_cap);
2644 else
2645 SET_EXTCAP_EXT_CHANNEL_SWITCH(pext_cap->ext_cap);
2646
2647 HEXDUMP("Extended Capabilities IE", (t_u8 *)pext_cap,
2648 sizeof(MrvlIETypes_ExtCap_t));
2649 *ppbuffer += sizeof(MrvlIETypes_ExtCap_t);
2650 ret_len += sizeof(MrvlIETypes_ExtCap_t);
2651 pext_cap->header.len = wlan_cpu_to_le16(pext_cap->header.len);
2652 } else if (wlan_is_ext_capa_support(pmpriv) ||
2653 (pmpriv->config_bands & BAND_AAC)) {
2654 wlan_add_ext_capa_info_ie(pmpriv, pbss_desc, ppbuffer);
2655 ret_len += sizeof(MrvlIETypes_ExtCap_t);
2656 }
2657 PRINTM(MCMND, "curr_bandwidth=%d\n", pbss_desc->curr_bandwidth);
2658 if (orig_usr_dot_11n_dev_cap)
2659 pmpriv->usr_dot_11n_dev_cap_bg = orig_usr_dot_11n_dev_cap;
2660
2661 LEAVE();
2662 return ret_len;
2663 }
2664
2665 #endif /* STA_SUPPORT */
2666
2667 /**
2668 * @brief 11n configuration handler
2669 *
2670 * @param pmadapter A pointer to mlan_adapter structure
2671 * @param pioctl_req A pointer to ioctl request buffer
2672 *
2673 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
2674 */
wlan_11n_cfg_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2675 mlan_status wlan_11n_cfg_ioctl(pmlan_adapter pmadapter,
2676 pmlan_ioctl_req pioctl_req)
2677 {
2678 mlan_status status = MLAN_STATUS_SUCCESS;
2679 mlan_ds_11n_cfg *cfg = MNULL;
2680
2681 ENTER();
2682
2683 if (pioctl_req->buf_len < sizeof(mlan_ds_11n_cfg)) {
2684 PRINTM(MINFO, "MLAN bss IOCTL length is too short.\n");
2685 pioctl_req->data_read_written = 0;
2686 pioctl_req->buf_len_needed = sizeof(mlan_ds_11n_cfg);
2687 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
2688 LEAVE();
2689 return MLAN_STATUS_RESOURCE;
2690 }
2691 cfg = (mlan_ds_11n_cfg *)pioctl_req->pbuf;
2692 switch (cfg->sub_command) {
2693 case MLAN_OID_11N_CFG_TX:
2694 status = wlan_11n_ioctl_httxcfg(pmadapter, pioctl_req);
2695 break;
2696 case MLAN_OID_11N_HTCAP_CFG:
2697 status = wlan_11n_ioctl_htusrcfg(pmadapter, pioctl_req);
2698 break;
2699 case MLAN_OID_11N_CFG_AGGR_PRIO_TBL:
2700 status = wlan_11n_ioctl_aggr_prio_tbl(pmadapter, pioctl_req);
2701 break;
2702 case MLAN_OID_11N_CFG_ADDBA_REJECT:
2703 status = wlan_11n_ioctl_addba_reject(pmadapter, pioctl_req);
2704 break;
2705 case MLAN_OID_11N_CFG_ADDBA_PARAM:
2706 status = wlan_11n_ioctl_addba_param(pmadapter, pioctl_req);
2707 break;
2708 case MLAN_OID_11N_CFG_DELBA:
2709 status = wlan_11n_ioctl_delba(pmadapter, pioctl_req);
2710 break;
2711 case MLAN_OID_11N_CFG_REJECT_ADDBA_REQ:
2712 status = wlan_11n_ioctl_rejectaddbareq(pmadapter, pioctl_req);
2713 break;
2714 case MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE:
2715 status = wlan_11n_ioctl_max_tx_buf_size(pmadapter, pioctl_req);
2716 break;
2717 case MLAN_OID_11N_CFG_AMSDU_AGGR_CTRL:
2718 status = wlan_11n_ioctl_amsdu_aggr_ctrl(pmadapter, pioctl_req);
2719 break;
2720 case MLAN_OID_11N_CFG_SUPPORTED_MCS_SET:
2721 status =
2722 wlan_11n_ioctl_supported_mcs_set(pmadapter, pioctl_req);
2723 break;
2724 case MLAN_OID_11N_CFG_TX_BF_CAP:
2725 status = wlan_11n_ioctl_tx_bf_cap(pmadapter, pioctl_req);
2726 break;
2727 case MLAN_OID_11N_CFG_TX_BF_CFG:
2728 status = wlan_11n_ioctl_tx_bf_cfg(pmadapter, pioctl_req);
2729 break;
2730 case MLAN_OID_11N_CFG_STREAM_CFG:
2731 status = wlan_11n_ioctl_stream_cfg(pmadapter, pioctl_req);
2732 break;
2733 case MLAN_OID_11N_CFG_COEX_RX_WINSIZE:
2734 status = wlan_11n_ioctl_coex_rx_winsize(pmadapter, pioctl_req);
2735 break;
2736 case MLAN_OID_11N_CFG_TX_AGGR_CTRL:
2737 status = wlan_11n_ioctl_txaggrctrl(pmadapter, pioctl_req);
2738 break;
2739 case MLAN_OID_11N_CFG_IBSS_AMPDU_PARAM:
2740 status = wlan_11n_ioctl_ibss_ampdu_param(pmadapter, pioctl_req);
2741 break;
2742 case MLAN_OID_11N_CFG_MIN_BA_THRESHOLD:
2743 status = wlan_11n_ioctl_min_ba_threshold_cfg(pmadapter,
2744 pioctl_req);
2745 break;
2746 default:
2747 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
2748 status = MLAN_STATUS_FAILURE;
2749 break;
2750 }
2751 LEAVE();
2752 return status;
2753 }
2754
2755 /**
2756 * @brief This function will delete the given entry in Tx BA Stream table
2757 *
2758 * @param priv Pointer to mlan_private
2759 * @param ptx_tbl Pointer to tx ba stream entry to delete
2760 *
2761 * @return N/A
2762 */
wlan_11n_delete_txbastream_tbl_entry(mlan_private * priv,TxBAStreamTbl * ptx_tbl)2763 void wlan_11n_delete_txbastream_tbl_entry(mlan_private *priv,
2764 TxBAStreamTbl *ptx_tbl)
2765 {
2766 pmlan_adapter pmadapter = priv->adapter;
2767
2768 ENTER();
2769
2770 if (!ptx_tbl || !wlan_is_txbastreamptr_valid(priv, ptx_tbl))
2771 goto exit;
2772 PRINTM(MINFO, "Delete BA stream table entry: %p\n", ptx_tbl);
2773 util_unlink_list(pmadapter->pmoal_handle, &priv->tx_ba_stream_tbl_ptr,
2774 (pmlan_linked_list)ptx_tbl, MNULL, MNULL);
2775 pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
2776 (t_u8 *)ptx_tbl);
2777 exit:
2778 LEAVE();
2779 }
2780
2781 /**
2782 * @brief This function will delete all the entries in Tx BA Stream table
2783 *
2784 * @param priv A pointer to mlan_private
2785 *
2786 * @return N/A
2787 */
wlan_11n_deleteall_txbastream_tbl(mlan_private * priv)2788 void wlan_11n_deleteall_txbastream_tbl(mlan_private *priv)
2789 {
2790 int i;
2791 TxBAStreamTbl *del_tbl_ptr = MNULL;
2792
2793 ENTER();
2794
2795 wlan_request_ralist_lock(priv);
2796 while ((del_tbl_ptr = (TxBAStreamTbl *)util_peek_list(
2797 priv->adapter->pmoal_handle,
2798 &priv->tx_ba_stream_tbl_ptr, MNULL, MNULL))) {
2799 wlan_11n_delete_txbastream_tbl_entry(priv, del_tbl_ptr);
2800 }
2801
2802 util_init_list((pmlan_linked_list)&priv->tx_ba_stream_tbl_ptr);
2803 wlan_release_ralist_lock(priv);
2804 for (i = 0; i < MAX_NUM_TID; ++i) {
2805 priv->aggr_prio_tbl[i].ampdu_ap =
2806 priv->aggr_prio_tbl[i].ampdu_user;
2807 }
2808
2809 LEAVE();
2810 }
2811
2812 /**
2813 * @brief This function will return the pointer to an entry in BA Stream
2814 * table which matches the give RA/TID pair
2815 *
2816 * @param priv A pointer to mlan_private
2817 * @param tid TID to find in reordering table
2818 * @param ra RA to find in reordering table
2819 * @param lock flag for request the spin_lock
2820 *
2821 * @return A pointer to first entry matching RA/TID in BA stream
2822 * NULL if not found
2823 */
wlan_11n_get_txbastream_tbl(mlan_private * priv,int tid,t_u8 * ra,int lock)2824 TxBAStreamTbl *wlan_11n_get_txbastream_tbl(mlan_private *priv, int tid,
2825 t_u8 *ra, int lock)
2826 {
2827 TxBAStreamTbl *ptx_tbl;
2828 pmlan_adapter pmadapter = priv->adapter;
2829
2830 ENTER();
2831
2832 if (lock)
2833 wlan_request_ralist_lock(priv);
2834 ptx_tbl = (TxBAStreamTbl *)util_peek_list(pmadapter->pmoal_handle,
2835 &priv->tx_ba_stream_tbl_ptr,
2836 MNULL, MNULL);
2837 if (!ptx_tbl) {
2838 if (lock)
2839 wlan_release_ralist_lock(priv);
2840 LEAVE();
2841 return MNULL;
2842 }
2843
2844 while (ptx_tbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
2845 PRINTM(MDAT_D, "get_txbastream_tbl TID %d\n", ptx_tbl->tid);
2846 DBG_HEXDUMP(MDAT_D, "RA", ptx_tbl->ra, MLAN_MAC_ADDR_LENGTH);
2847
2848 if ((!memcmp(pmadapter, ptx_tbl->ra, ra,
2849 MLAN_MAC_ADDR_LENGTH)) &&
2850 (ptx_tbl->tid == tid)) {
2851 if (lock)
2852 wlan_release_ralist_lock(priv);
2853 LEAVE();
2854 return ptx_tbl;
2855 }
2856
2857 ptx_tbl = ptx_tbl->pnext;
2858 }
2859 if (lock)
2860 wlan_release_ralist_lock(priv);
2861 LEAVE();
2862 return MNULL;
2863 }
2864
2865 /**
2866 * @brief This function will create a entry in tx ba stream table for the
2867 * given RA/TID.
2868 *
2869 * @param priv A pointer to mlan_private
2870 * @param ra RA to find in reordering table
2871 * @param tid TID to find in reordering table
2872 * @param ba_status BA stream status to create the stream with
2873 *
2874 * @return N/A
2875 */
wlan_11n_create_txbastream_tbl(mlan_private * priv,t_u8 * ra,int tid,baStatus_e ba_status)2876 void wlan_11n_create_txbastream_tbl(mlan_private *priv, t_u8 *ra, int tid,
2877 baStatus_e ba_status)
2878 {
2879 TxBAStreamTbl *new_node = MNULL;
2880 pmlan_adapter pmadapter = priv->adapter;
2881 raListTbl *ra_list = MNULL;
2882 int tid_down;
2883
2884 ENTER();
2885
2886 PRINTM(MDAT_D, "create_txbastream_tbl TID %d\n", tid);
2887 DBG_HEXDUMP(MDAT_D, "RA", ra, MLAN_MAC_ADDR_LENGTH);
2888
2889 if (pmadapter->callbacks.moal_malloc(
2890 pmadapter->pmoal_handle, sizeof(TxBAStreamTbl),
2891 MLAN_MEM_DEF | MLAN_MEM_FLAG_ATOMIC, (t_u8 **)&new_node)) {
2892 PRINTM(MERROR,
2893 "wlan_11n_create_txbastream_tbl Failed to allocate new_node\n");
2894 LEAVE();
2895 return;
2896 }
2897 tid_down = wlan_get_wmm_tid_down(priv, tid);
2898 ra_list = wlan_wmm_get_ralist_node(priv, tid_down, ra);
2899 if (ra_list) {
2900 ra_list->amsdu_in_ampdu = MFALSE;
2901 ra_list->ba_status = ba_status;
2902 }
2903 util_init_list((pmlan_linked_list)new_node);
2904
2905 new_node->tid = tid;
2906 new_node->ba_status = ba_status;
2907 memcpy_ext(pmadapter, new_node->ra, ra, MLAN_MAC_ADDR_LENGTH,
2908 MLAN_MAC_ADDR_LENGTH);
2909
2910 util_enqueue_list_tail(pmadapter->pmoal_handle,
2911 &priv->tx_ba_stream_tbl_ptr,
2912 (pmlan_linked_list)new_node, MNULL, MNULL);
2913
2914 LEAVE();
2915 }
2916
2917 /**
2918 * @brief This function will send a block ack to given tid/ra
2919 *
2920 * @param priv A pointer to mlan_private
2921 * @param tid TID to send the ADDBA
2922 * @param peer_mac MAC address to send the ADDBA
2923 *
2924 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2925 */
wlan_send_addba(mlan_private * priv,int tid,t_u8 * peer_mac)2926 int wlan_send_addba(mlan_private *priv, int tid, t_u8 *peer_mac)
2927 {
2928 HostCmd_DS_11N_ADDBA_REQ add_ba_req;
2929 static t_u8 dialog_tok;
2930 mlan_status ret;
2931
2932 ENTER();
2933
2934 PRINTM(MCMND, "Send addba: TID %d\n", tid);
2935 DBG_HEXDUMP(MCMD_D, "Send addba RA", peer_mac, MLAN_MAC_ADDR_LENGTH);
2936
2937 add_ba_req.block_ack_param_set = (t_u16)(
2938 (tid << BLOCKACKPARAM_TID_POS) |
2939 (priv->add_ba_param.tx_win_size << BLOCKACKPARAM_WINSIZE_POS) |
2940 IMMEDIATE_BLOCK_ACK);
2941 /** enable AMSDU inside AMPDU */
2942 if (priv->add_ba_param.tx_amsdu &&
2943 (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED))
2944 add_ba_req.block_ack_param_set |= BLOCKACKPARAM_AMSDU_SUPP_MASK;
2945 add_ba_req.block_ack_tmo = (t_u16)priv->add_ba_param.timeout;
2946
2947 ++dialog_tok;
2948
2949 if (dialog_tok == 0)
2950 dialog_tok = 1;
2951
2952 add_ba_req.dialog_token = dialog_tok;
2953 memcpy_ext(priv->adapter, &add_ba_req.peer_mac_addr, peer_mac,
2954 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
2955
2956 /* We don't wait for the response of this command */
2957 ret = wlan_prepare_cmd(priv, HostCmd_CMD_11N_ADDBA_REQ, 0, 0, MNULL,
2958 &add_ba_req);
2959
2960 LEAVE();
2961 return ret;
2962 }
2963
2964 /**
2965 * @brief This function will delete a block ack to given tid/ra
2966 *
2967 * @param priv A pointer to mlan_private
2968 * @param pioctl_req A pointer to ioctl request buffer
2969 * @param tid TID to send the ADDBA
2970 * @param peer_mac MAC address to send the ADDBA
2971 * @param initiator MTRUE if we have initiated ADDBA, MFALSE otherwise
2972 *
2973 * @return MLAN_STATUS_PENDING --success, otherwise fail
2974 */
wlan_send_delba(mlan_private * priv,pmlan_ioctl_req pioctl_req,int tid,t_u8 * peer_mac,int initiator)2975 int wlan_send_delba(mlan_private *priv, pmlan_ioctl_req pioctl_req, int tid,
2976 t_u8 *peer_mac, int initiator)
2977 {
2978 HostCmd_DS_11N_DELBA delba;
2979 mlan_status ret;
2980
2981 ENTER();
2982
2983 memset(priv->adapter, &delba, 0, sizeof(delba));
2984 delba.del_ba_param_set = (tid << DELBA_TID_POS);
2985
2986 if (initiator)
2987 DELBA_INITIATOR(delba.del_ba_param_set);
2988 else
2989 DELBA_RECIPIENT(delba.del_ba_param_set);
2990
2991 memcpy_ext(priv->adapter, &delba.peer_mac_addr, peer_mac,
2992 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
2993
2994 ret = wlan_prepare_cmd(priv, HostCmd_CMD_11N_DELBA, HostCmd_ACT_GEN_SET,
2995 0, (t_void *)pioctl_req, (t_void *)&delba);
2996
2997 if (ret == MLAN_STATUS_SUCCESS)
2998 ret = MLAN_STATUS_PENDING;
2999
3000 LEAVE();
3001 return ret;
3002 }
3003
3004 /**
3005 * @brief This function handles the command response of
3006 * delete a block ack request
3007 *
3008 * @param priv A pointer to mlan_private structure
3009 * @param del_ba A pointer to command response buffer
3010 *
3011 * @return N/A
3012 */
wlan_11n_delete_bastream(mlan_private * priv,t_u8 * del_ba)3013 void wlan_11n_delete_bastream(mlan_private *priv, t_u8 *del_ba)
3014 {
3015 HostCmd_DS_11N_DELBA *pdel_ba = (HostCmd_DS_11N_DELBA *)del_ba;
3016 int tid;
3017
3018 ENTER();
3019
3020 DBG_HEXDUMP(MCMD_D, "Delba:", (t_u8 *)pdel_ba, 20);
3021 pdel_ba->del_ba_param_set = wlan_le16_to_cpu(pdel_ba->del_ba_param_set);
3022 pdel_ba->reason_code = wlan_le16_to_cpu(pdel_ba->reason_code);
3023
3024 tid = pdel_ba->del_ba_param_set >> DELBA_TID_POS;
3025
3026 mlan_11n_delete_bastream_tbl(priv, tid, pdel_ba->peer_mac_addr,
3027 TYPE_DELBA_RECEIVE,
3028 INITIATOR_BIT(pdel_ba->del_ba_param_set),
3029 pdel_ba->reason_code);
3030
3031 LEAVE();
3032 }
3033
3034 /**
3035 * @brief Get Rx reordering table
3036 *
3037 * @param priv A pointer to mlan_private structure
3038 * @param buf A pointer to rx_reorder_tbl structure
3039 * @return number of rx reorder table entry
3040 */
wlan_get_rxreorder_tbl(mlan_private * priv,rx_reorder_tbl * buf)3041 int wlan_get_rxreorder_tbl(mlan_private *priv, rx_reorder_tbl *buf)
3042 {
3043 int i;
3044 rx_reorder_tbl *ptbl = buf;
3045 RxReorderTbl *rx_reorder_tbl_ptr;
3046 int count = 0;
3047 ENTER();
3048 priv->adapter->callbacks.moal_spin_lock(priv->adapter->pmoal_handle,
3049 priv->rx_reorder_tbl_ptr.plock);
3050 rx_reorder_tbl_ptr =
3051 (RxReorderTbl *)util_peek_list(priv->adapter->pmoal_handle,
3052 &priv->rx_reorder_tbl_ptr, MNULL,
3053 MNULL);
3054 if (!rx_reorder_tbl_ptr) {
3055 priv->adapter->callbacks.moal_spin_unlock(
3056 priv->adapter->pmoal_handle,
3057 priv->rx_reorder_tbl_ptr.plock);
3058 LEAVE();
3059 return count;
3060 }
3061 while (rx_reorder_tbl_ptr !=
3062 (RxReorderTbl *)&priv->rx_reorder_tbl_ptr) {
3063 ptbl->tid = (t_u16)rx_reorder_tbl_ptr->tid;
3064 memcpy_ext(priv->adapter, ptbl->ta, rx_reorder_tbl_ptr->ta,
3065 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
3066 ptbl->start_win = rx_reorder_tbl_ptr->start_win;
3067 ptbl->win_size = rx_reorder_tbl_ptr->win_size;
3068
3069 ptbl->amsdu = rx_reorder_tbl_ptr->amsdu;
3070 for (i = 0; i < rx_reorder_tbl_ptr->win_size; ++i) {
3071 if (rx_reorder_tbl_ptr->rx_reorder_ptr[i])
3072 ptbl->buffer[i] = MTRUE;
3073 else
3074 ptbl->buffer[i] = MFALSE;
3075 }
3076 rx_reorder_tbl_ptr = rx_reorder_tbl_ptr->pnext;
3077 ptbl++;
3078 count++;
3079 if (count >= MLAN_MAX_RX_BASTREAM_SUPPORTED)
3080 break;
3081 }
3082 priv->adapter->callbacks.moal_spin_unlock(
3083 priv->adapter->pmoal_handle, priv->rx_reorder_tbl_ptr.plock);
3084 LEAVE();
3085 return count;
3086 }
3087
3088 /**
3089 * @brief Get transmit BA stream table
3090 *
3091 * @param priv A pointer to mlan_private structure
3092 * @param buf A pointer to tx_ba_stream_tbl structure
3093 * @return number of ba stream table entry
3094 */
wlan_get_txbastream_tbl(mlan_private * priv,tx_ba_stream_tbl * buf)3095 int wlan_get_txbastream_tbl(mlan_private *priv, tx_ba_stream_tbl *buf)
3096 {
3097 TxBAStreamTbl *ptxtbl;
3098 tx_ba_stream_tbl *ptbl = buf;
3099 int count = 0;
3100 t_u32 bastream_max = 0;
3101
3102 ENTER();
3103
3104 wlan_request_ralist_lock(priv);
3105 ptxtbl = (TxBAStreamTbl *)util_peek_list(priv->adapter->pmoal_handle,
3106 &priv->tx_ba_stream_tbl_ptr,
3107 MNULL, MNULL);
3108 if (!ptxtbl) {
3109 wlan_release_ralist_lock(priv);
3110 LEAVE();
3111 return count;
3112 }
3113 bastream_max = ISSUPP_GETTXBASTREAM(priv->adapter->hw_dot_11n_dev_cap);
3114 if (bastream_max == 0)
3115 bastream_max = MLAN_MAX_TX_BASTREAM_DEFAULT;
3116
3117 while (ptxtbl != (TxBAStreamTbl *)&priv->tx_ba_stream_tbl_ptr) {
3118 ptbl->tid = (t_u16)ptxtbl->tid;
3119 PRINTM(MINFO, "tid=%d\n", ptbl->tid);
3120 memcpy_ext(priv->adapter, ptbl->ra, ptxtbl->ra,
3121 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
3122 ptbl->amsdu = ptxtbl->amsdu;
3123 ptxtbl = ptxtbl->pnext;
3124 ptbl++;
3125 count++;
3126 if (count >= (int)bastream_max)
3127 break;
3128 }
3129 wlan_release_ralist_lock(priv);
3130 LEAVE();
3131 return count;
3132 }
3133
3134 /**
3135 * @brief This function check if 11AC is allowed in bandcfg
3136 *
3137 * @param pmpriv A pointer to mlan_private structure
3138 * @param bss_band bss band
3139 *
3140 * @return 0--not allowed, other value allowed
3141 */
wlan_11n_bandconfig_allowed(mlan_private * pmpriv,t_u16 bss_band)3142 t_u8 wlan_11n_bandconfig_allowed(mlan_private *pmpriv, t_u16 bss_band)
3143 {
3144 if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) {
3145 if (bss_band & BAND_G)
3146 return (pmpriv->adapter->adhoc_start_band & BAND_GN);
3147 else if (bss_band & BAND_A)
3148 return (pmpriv->adapter->adhoc_start_band & BAND_AN);
3149 } else {
3150 if (bss_band & BAND_G)
3151 return (pmpriv->config_bands & BAND_GN);
3152 else if (bss_band & BAND_A)
3153 return (pmpriv->config_bands & BAND_AN);
3154 }
3155 return 0;
3156 }
3157
3158 /**
3159 * @brief This function cleans up txbastream_tbl for specific station
3160 *
3161 * @param priv A pointer to mlan_private
3162 * @param ra RA to find in txbastream_tbl
3163 * @return N/A
3164 */
wlan_11n_cleanup_txbastream_tbl(mlan_private * priv,t_u8 * ra)3165 void wlan_11n_cleanup_txbastream_tbl(mlan_private *priv, t_u8 *ra)
3166 {
3167 TxBAStreamTbl *ptx_tbl = MNULL;
3168 t_u8 i;
3169 ENTER();
3170
3171 wlan_request_ralist_lock(priv);
3172 for (i = 0; i < MAX_NUM_TID; ++i) {
3173 ptx_tbl = wlan_11n_get_txbastream_tbl(priv, i, ra, MFALSE);
3174 if (ptx_tbl)
3175 wlan_11n_delete_txbastream_tbl_entry(priv, ptx_tbl);
3176 }
3177 wlan_release_ralist_lock(priv);
3178 LEAVE();
3179 return;
3180 }
3181
wlan_update_11n_cap(mlan_private * pmpriv)3182 void wlan_update_11n_cap(mlan_private *pmpriv)
3183 {
3184 mlan_adapter *pmadapter = pmpriv->adapter;
3185
3186 pmpriv->usr_dev_mcs_support = pmadapter->hw_dev_mcs_support;
3187 pmpriv->usr_dot_11n_dev_cap_bg =
3188 pmadapter->hw_dot_11n_dev_cap & DEFAULT_11N_CAP_MASK_BG;
3189 pmpriv->usr_dot_11n_dev_cap_a =
3190 pmadapter->hw_dot_11n_dev_cap & DEFAULT_11N_CAP_MASK_A;
3191 }
3192