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