1*4882a593Smuzhiyun /** @file moal_uap.c
2*4882a593Smuzhiyun *
3*4882a593Smuzhiyun * @brief This file contains the major functions in UAP
4*4882a593Smuzhiyun * driver.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright 2008-2022 NXP
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * This software file (the File) is distributed by NXP
10*4882a593Smuzhiyun * under the terms of the GNU General Public License Version 2, June 1991
11*4882a593Smuzhiyun * (the License). You may use, redistribute and/or modify the File in
12*4882a593Smuzhiyun * accordance with the terms and conditions of the License, a copy of which
13*4882a593Smuzhiyun * is available by writing to the Free Software Foundation, Inc.,
14*4882a593Smuzhiyun * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
15*4882a593Smuzhiyun * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
16*4882a593Smuzhiyun *
17*4882a593Smuzhiyun * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
18*4882a593Smuzhiyun * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
19*4882a593Smuzhiyun * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
20*4882a593Smuzhiyun * this warranty disclaimer.
21*4882a593Smuzhiyun *
22*4882a593Smuzhiyun */
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun /********************************************************
25*4882a593Smuzhiyun Change log:
26*4882a593Smuzhiyun 10/21/2008: initial version
27*4882a593Smuzhiyun ********************************************************/
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #include "moal_main.h"
30*4882a593Smuzhiyun #include "moal_uap.h"
31*4882a593Smuzhiyun #ifdef SDIO
32*4882a593Smuzhiyun #include "moal_sdio.h"
33*4882a593Smuzhiyun #endif /* SDIO */
34*4882a593Smuzhiyun #include "moal_eth_ioctl.h"
35*4882a593Smuzhiyun #if defined(STA_CFG80211) && defined(UAP_CFG80211)
36*4882a593Smuzhiyun #include "moal_cfg80211.h"
37*4882a593Smuzhiyun #endif
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun /********************************************************
40*4882a593Smuzhiyun Local Variables
41*4882a593Smuzhiyun ********************************************************/
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun /********************************************************
44*4882a593Smuzhiyun Global Variables
45*4882a593Smuzhiyun ********************************************************/
46*4882a593Smuzhiyun /********************************************************
47*4882a593Smuzhiyun Local Functions
48*4882a593Smuzhiyun ********************************************************/
49*4882a593Smuzhiyun /**
50*4882a593Smuzhiyun * @brief uap addba parameter handler
51*4882a593Smuzhiyun *
52*4882a593Smuzhiyun * @param dev A pointer to net_device structure
53*4882a593Smuzhiyun * @param req A pointer to ifreq structure
54*4882a593Smuzhiyun * @return 0 --success, otherwise fail
55*4882a593Smuzhiyun */
woal_uap_addba_param(struct net_device * dev,struct ifreq * req)56*4882a593Smuzhiyun static int woal_uap_addba_param(struct net_device *dev, struct ifreq *req)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
59*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
60*4882a593Smuzhiyun mlan_ds_11n_cfg *cfg_11n = NULL;
61*4882a593Smuzhiyun uap_addba_param param;
62*4882a593Smuzhiyun int ret = 0;
63*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun ENTER();
66*4882a593Smuzhiyun memset(¶m, 0, sizeof(param));
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun /* Sanity check */
69*4882a593Smuzhiyun if (req->ifr_data == NULL) {
70*4882a593Smuzhiyun PRINTM(MERROR, "uap_addba_param() corrupt data\n");
71*4882a593Smuzhiyun ret = -EFAULT;
72*4882a593Smuzhiyun goto done;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
75*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
76*4882a593Smuzhiyun ret = -EFAULT;
77*4882a593Smuzhiyun goto done;
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun PRINTM(MIOCTL,
80*4882a593Smuzhiyun "addba param: action=%d, timeout=%d, txwinsize=%d, rxwinsize=%d txamsdu=%d rxamsdu=%d\n",
81*4882a593Smuzhiyun (int)param.action, (int)param.timeout, (int)param.txwinsize,
82*4882a593Smuzhiyun (int)param.rxwinsize, (int)param.txamsdu, (int)param.rxamsdu);
83*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
84*4882a593Smuzhiyun if (ioctl_req == NULL) {
85*4882a593Smuzhiyun LEAVE();
86*4882a593Smuzhiyun return -ENOMEM;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
89*4882a593Smuzhiyun cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_PARAM;
90*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun if (!param.action)
93*4882a593Smuzhiyun /* Get addba param from MLAN */
94*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_GET;
95*4882a593Smuzhiyun else {
96*4882a593Smuzhiyun /* Set addba param in MLAN */
97*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
98*4882a593Smuzhiyun cfg_11n->param.addba_param.timeout = param.timeout;
99*4882a593Smuzhiyun cfg_11n->param.addba_param.txwinsize = param.txwinsize;
100*4882a593Smuzhiyun cfg_11n->param.addba_param.rxwinsize = param.rxwinsize;
101*4882a593Smuzhiyun cfg_11n->param.addba_param.txamsdu = param.txamsdu;
102*4882a593Smuzhiyun cfg_11n->param.addba_param.rxamsdu = param.rxamsdu;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
105*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
106*4882a593Smuzhiyun ret = -EFAULT;
107*4882a593Smuzhiyun goto done;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun param.timeout = cfg_11n->param.addba_param.timeout;
110*4882a593Smuzhiyun param.txwinsize = cfg_11n->param.addba_param.txwinsize;
111*4882a593Smuzhiyun param.rxwinsize = cfg_11n->param.addba_param.rxwinsize;
112*4882a593Smuzhiyun param.txamsdu = cfg_11n->param.addba_param.txamsdu;
113*4882a593Smuzhiyun param.rxamsdu = cfg_11n->param.addba_param.rxamsdu;
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /* Copy to user */
116*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
117*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
118*4882a593Smuzhiyun ret = -EFAULT;
119*4882a593Smuzhiyun goto done;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun done:
122*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
123*4882a593Smuzhiyun kfree(ioctl_req);
124*4882a593Smuzhiyun LEAVE();
125*4882a593Smuzhiyun return ret;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun /**
129*4882a593Smuzhiyun * @brief uap aggr priority tbl
130*4882a593Smuzhiyun *
131*4882a593Smuzhiyun * @param dev A pointer to net_device structure
132*4882a593Smuzhiyun * @param req A pointer to ifreq structure
133*4882a593Smuzhiyun * @return 0 --success, otherwise fail
134*4882a593Smuzhiyun */
woal_uap_aggr_priotbl(struct net_device * dev,struct ifreq * req)135*4882a593Smuzhiyun static int woal_uap_aggr_priotbl(struct net_device *dev, struct ifreq *req)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
138*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
139*4882a593Smuzhiyun mlan_ds_11n_cfg *cfg_11n = NULL;
140*4882a593Smuzhiyun uap_aggr_prio_tbl param;
141*4882a593Smuzhiyun int ret = 0;
142*4882a593Smuzhiyun int i = 0;
143*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun ENTER();
146*4882a593Smuzhiyun memset(¶m, 0, sizeof(param));
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun /* Sanity check */
149*4882a593Smuzhiyun if (req->ifr_data == NULL) {
150*4882a593Smuzhiyun PRINTM(MERROR, "woal_uap_aggr_priotbl() corrupt data\n");
151*4882a593Smuzhiyun ret = -EFAULT;
152*4882a593Smuzhiyun goto done;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
155*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
156*4882a593Smuzhiyun ret = -EFAULT;
157*4882a593Smuzhiyun goto done;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "aggr_prio_tbl", (t_u8 *)¶m, sizeof(param));
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
162*4882a593Smuzhiyun if (ioctl_req == NULL) {
163*4882a593Smuzhiyun LEAVE();
164*4882a593Smuzhiyun return -ENOMEM;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
167*4882a593Smuzhiyun cfg_11n->sub_command = MLAN_OID_11N_CFG_AGGR_PRIO_TBL;
168*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun if (!param.action) {
171*4882a593Smuzhiyun /* Get aggr_prio_tbl from MLAN */
172*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_GET;
173*4882a593Smuzhiyun } else {
174*4882a593Smuzhiyun /* Set aggr_prio_tbl in MLAN */
175*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
176*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; i++) {
177*4882a593Smuzhiyun cfg_11n->param.aggr_prio_tbl.ampdu[i] = param.ampdu[i];
178*4882a593Smuzhiyun cfg_11n->param.aggr_prio_tbl.amsdu[i] = param.amsdu[i];
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
182*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
183*4882a593Smuzhiyun ret = -EFAULT;
184*4882a593Smuzhiyun goto done;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; i++) {
187*4882a593Smuzhiyun param.ampdu[i] = cfg_11n->param.aggr_prio_tbl.ampdu[i];
188*4882a593Smuzhiyun param.amsdu[i] = cfg_11n->param.aggr_prio_tbl.amsdu[i];
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun /* Copy to user */
191*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
192*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
193*4882a593Smuzhiyun ret = -EFAULT;
194*4882a593Smuzhiyun goto done;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun done:
197*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
198*4882a593Smuzhiyun kfree(ioctl_req);
199*4882a593Smuzhiyun LEAVE();
200*4882a593Smuzhiyun return ret;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun /**
204*4882a593Smuzhiyun * @brief uap addba reject tbl
205*4882a593Smuzhiyun *
206*4882a593Smuzhiyun * @param dev A pointer to net_device structure
207*4882a593Smuzhiyun * @param req A pointer to ifreq structure
208*4882a593Smuzhiyun * @return 0 --success, otherwise fail
209*4882a593Smuzhiyun */
woal_uap_addba_reject(struct net_device * dev,struct ifreq * req)210*4882a593Smuzhiyun static int woal_uap_addba_reject(struct net_device *dev, struct ifreq *req)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
213*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
214*4882a593Smuzhiyun mlan_ds_11n_cfg *cfg_11n = NULL;
215*4882a593Smuzhiyun addba_reject_para param;
216*4882a593Smuzhiyun int ret = 0;
217*4882a593Smuzhiyun int i = 0;
218*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun ENTER();
221*4882a593Smuzhiyun memset(¶m, 0, sizeof(param));
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun /* Sanity check */
224*4882a593Smuzhiyun if (req->ifr_data == NULL) {
225*4882a593Smuzhiyun PRINTM(MERROR, "woal_uap_addba_reject() corrupt data\n");
226*4882a593Smuzhiyun ret = -EFAULT;
227*4882a593Smuzhiyun goto done;
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
230*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
231*4882a593Smuzhiyun ret = -EFAULT;
232*4882a593Smuzhiyun goto done;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "addba_reject tbl", (t_u8 *)¶m, sizeof(param));
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
237*4882a593Smuzhiyun if (ioctl_req == NULL) {
238*4882a593Smuzhiyun LEAVE();
239*4882a593Smuzhiyun return -ENOMEM;
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
242*4882a593Smuzhiyun cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_REJECT;
243*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun if (!param.action) {
246*4882a593Smuzhiyun /* Get addba_reject tbl from MLAN */
247*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_GET;
248*4882a593Smuzhiyun } else {
249*4882a593Smuzhiyun /* Set addba_reject tbl in MLAN */
250*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
251*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; i++)
252*4882a593Smuzhiyun cfg_11n->param.addba_reject[i] = param.addba_reject[i];
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
255*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
256*4882a593Smuzhiyun ret = -EFAULT;
257*4882a593Smuzhiyun goto done;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun for (i = 0; i < MAX_NUM_TID; i++)
260*4882a593Smuzhiyun param.addba_reject[i] = cfg_11n->param.addba_reject[i];
261*4882a593Smuzhiyun /* Copy to user */
262*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
263*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
264*4882a593Smuzhiyun ret = -EFAULT;
265*4882a593Smuzhiyun goto done;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun done:
268*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
269*4882a593Smuzhiyun kfree(ioctl_req);
270*4882a593Smuzhiyun LEAVE();
271*4882a593Smuzhiyun return ret;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun /**
275*4882a593Smuzhiyun * @brief uap get_fw_info handler
276*4882a593Smuzhiyun *
277*4882a593Smuzhiyun * @param dev A pointer to net_device structure
278*4882a593Smuzhiyun * @param req A pointer to ifreq structure
279*4882a593Smuzhiyun * @return 0 --success, otherwise fail
280*4882a593Smuzhiyun */
woal_uap_get_fw_info(struct net_device * dev,struct ifreq * req)281*4882a593Smuzhiyun static int woal_uap_get_fw_info(struct net_device *dev, struct ifreq *req)
282*4882a593Smuzhiyun {
283*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
284*4882a593Smuzhiyun uap_fw_info fw;
285*4882a593Smuzhiyun mlan_fw_info fw_info;
286*4882a593Smuzhiyun int ret = 0;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun ENTER();
289*4882a593Smuzhiyun memset(&fw, 0, sizeof(fw));
290*4882a593Smuzhiyun memset(&fw_info, 0, sizeof(fw_info));
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun /* Sanity check */
293*4882a593Smuzhiyun if (req->ifr_data == NULL) {
294*4882a593Smuzhiyun PRINTM(MERROR, "woal_uap_get_fw_info() corrupt data\n");
295*4882a593Smuzhiyun ret = -EFAULT;
296*4882a593Smuzhiyun goto done;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun if (copy_from_user(&fw, req->ifr_data, sizeof(fw))) {
299*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
300*4882a593Smuzhiyun ret = -EFAULT;
301*4882a593Smuzhiyun goto done;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
304*4882a593Smuzhiyun woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info)) {
305*4882a593Smuzhiyun ret = -EFAULT;
306*4882a593Smuzhiyun goto done;
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun fw.fw_release_number = fw_info.fw_ver;
309*4882a593Smuzhiyun fw.hw_dev_mcs_support = fw_info.hw_dev_mcs_support;
310*4882a593Smuzhiyun fw.fw_bands = fw_info.fw_bands;
311*4882a593Smuzhiyun fw.region_code = fw_info.region_code;
312*4882a593Smuzhiyun fw.hw_dot_11n_dev_cap = fw_info.hw_dot_11n_dev_cap;
313*4882a593Smuzhiyun /* Copy to user */
314*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, &fw, sizeof(fw))) {
315*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
316*4882a593Smuzhiyun ret = -EFAULT;
317*4882a593Smuzhiyun goto done;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun done:
320*4882a593Smuzhiyun LEAVE();
321*4882a593Smuzhiyun return ret;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun /**
325*4882a593Smuzhiyun * @brief configure deep sleep
326*4882a593Smuzhiyun *
327*4882a593Smuzhiyun * @param dev A pointer to net_device structure
328*4882a593Smuzhiyun * @param req A pointer to ifreq structure
329*4882a593Smuzhiyun * @return 0 --success, otherwise fail
330*4882a593Smuzhiyun */
woal_uap_deep_sleep(struct net_device * dev,struct ifreq * req)331*4882a593Smuzhiyun static int woal_uap_deep_sleep(struct net_device *dev, struct ifreq *req)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
334*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
335*4882a593Smuzhiyun mlan_ds_pm_cfg *pm = NULL;
336*4882a593Smuzhiyun deep_sleep_para param;
337*4882a593Smuzhiyun int ret = 0;
338*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun ENTER();
341*4882a593Smuzhiyun memset(¶m, 0, sizeof(param));
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun /* Sanity check */
344*4882a593Smuzhiyun if (req->ifr_data == NULL) {
345*4882a593Smuzhiyun PRINTM(MERROR, "woal_uap_deep_sleep() corrupt data\n");
346*4882a593Smuzhiyun ret = -EFAULT;
347*4882a593Smuzhiyun goto done;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
350*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
351*4882a593Smuzhiyun ret = -EFAULT;
352*4882a593Smuzhiyun goto done;
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "deep_sleep_para", (t_u8 *)¶m, sizeof(param));
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
357*4882a593Smuzhiyun if (ioctl_req == NULL) {
358*4882a593Smuzhiyun LEAVE();
359*4882a593Smuzhiyun return -ENOMEM;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun pm = (mlan_ds_pm_cfg *)ioctl_req->pbuf;
362*4882a593Smuzhiyun pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP;
363*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_PM_CFG;
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun if (!param.action) {
366*4882a593Smuzhiyun /* Get deep_sleep status from MLAN */
367*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_GET;
368*4882a593Smuzhiyun } else {
369*4882a593Smuzhiyun /* Set deep_sleep in MLAN */
370*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
371*4882a593Smuzhiyun if (param.deep_sleep == MTRUE) {
372*4882a593Smuzhiyun pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_ON;
373*4882a593Smuzhiyun pm->param.auto_deep_sleep.idletime = param.idle_time;
374*4882a593Smuzhiyun } else {
375*4882a593Smuzhiyun pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_OFF;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
379*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
380*4882a593Smuzhiyun ret = -EFAULT;
381*4882a593Smuzhiyun goto done;
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun if (pm->param.auto_deep_sleep.auto_ds == DEEP_SLEEP_ON)
384*4882a593Smuzhiyun param.deep_sleep = MTRUE;
385*4882a593Smuzhiyun else
386*4882a593Smuzhiyun param.deep_sleep = MFALSE;
387*4882a593Smuzhiyun param.idle_time = pm->param.auto_deep_sleep.idletime;
388*4882a593Smuzhiyun /* Copy to user */
389*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
390*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
391*4882a593Smuzhiyun ret = -EFAULT;
392*4882a593Smuzhiyun goto done;
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun done:
395*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
396*4882a593Smuzhiyun kfree(ioctl_req);
397*4882a593Smuzhiyun LEAVE();
398*4882a593Smuzhiyun return ret;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun /**
402*4882a593Smuzhiyun * @brief configure band steering
403*4882a593Smuzhiyun *
404*4882a593Smuzhiyun * @param dev A pointer to net_device structure
405*4882a593Smuzhiyun * @param req A pointer to ifreq structure
406*4882a593Smuzhiyun * @return 0 --success, otherwise fail
407*4882a593Smuzhiyun */
woal_uap_band_steer(struct net_device * dev,struct ifreq * req)408*4882a593Smuzhiyun static int woal_uap_band_steer(struct net_device *dev, struct ifreq *req)
409*4882a593Smuzhiyun {
410*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
411*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
412*4882a593Smuzhiyun mlan_ds_misc_cfg *pm = NULL;
413*4882a593Smuzhiyun band_steer_para param;
414*4882a593Smuzhiyun int ret = 0;
415*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
416*4882a593Smuzhiyun ENTER();
417*4882a593Smuzhiyun memset(¶m, 0, sizeof(param));
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun /* Sanity check */
420*4882a593Smuzhiyun if (req->ifr_data == NULL) {
421*4882a593Smuzhiyun PRINTM(MERROR, "woal_uap_band_steer() corrupt data\n");
422*4882a593Smuzhiyun ret = -EFAULT;
423*4882a593Smuzhiyun goto done;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
426*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
427*4882a593Smuzhiyun ret = -EFAULT;
428*4882a593Smuzhiyun goto done;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "band_steer_para", (t_u8 *)¶m, sizeof(param));
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_band_steer_cfg));
433*4882a593Smuzhiyun if (ioctl_req == NULL) {
434*4882a593Smuzhiyun LEAVE();
435*4882a593Smuzhiyun return -ENOMEM;
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun pm = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
438*4882a593Smuzhiyun pm->sub_command = MLAN_OID_MISC_BAND_STEERING;
439*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun pm->param.band_steer_cfg.action = param.action;
442*4882a593Smuzhiyun pm->param.band_steer_cfg.block_2g_prb_req = param.block_2g_prb_req;
443*4882a593Smuzhiyun pm->param.band_steer_cfg.state = param.state;
444*4882a593Smuzhiyun pm->param.band_steer_cfg.max_btm_req_allowed =
445*4882a593Smuzhiyun param.max_btm_req_allowed;
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
448*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
449*4882a593Smuzhiyun ret = -EFAULT;
450*4882a593Smuzhiyun goto done;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun param.action = pm->param.band_steer_cfg.action;
454*4882a593Smuzhiyun param.block_2g_prb_req = pm->param.band_steer_cfg.block_2g_prb_req;
455*4882a593Smuzhiyun param.state = pm->param.band_steer_cfg.state;
456*4882a593Smuzhiyun param.max_btm_req_allowed =
457*4882a593Smuzhiyun pm->param.band_steer_cfg.max_btm_req_allowed;
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun /* Copy to user */
460*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
461*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
462*4882a593Smuzhiyun ret = -EFAULT;
463*4882a593Smuzhiyun goto done;
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun done:
466*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
467*4882a593Smuzhiyun kfree(ioctl_req);
468*4882a593Smuzhiyun LEAVE();
469*4882a593Smuzhiyun return ret;
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun /**
473*4882a593Smuzhiyun * @brief configure beacon stuck detect mechanism
474*4882a593Smuzhiyun *
475*4882a593Smuzhiyun * @param dev A pointer to net_device structure
476*4882a593Smuzhiyun * @param req A pointer to ifreq structure
477*4882a593Smuzhiyun * @return 0 --success, otherwise fail
478*4882a593Smuzhiyun */
woal_uap_beacon_stuck(struct net_device * dev,struct ifreq * req)479*4882a593Smuzhiyun static int woal_uap_beacon_stuck(struct net_device *dev, struct ifreq *req)
480*4882a593Smuzhiyun {
481*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
482*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
483*4882a593Smuzhiyun mlan_ds_misc_cfg *pm = NULL;
484*4882a593Smuzhiyun beacon_stuck_detect_para param;
485*4882a593Smuzhiyun int ret = 0;
486*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun ENTER();
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun memset(¶m, 0, sizeof(param));
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun /* Sanity check */
493*4882a593Smuzhiyun if (req->ifr_data == NULL) {
494*4882a593Smuzhiyun PRINTM(MERROR, "woal_uap_beacon_stuck() corrupt data\n");
495*4882a593Smuzhiyun ret = -EFAULT;
496*4882a593Smuzhiyun goto done;
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
500*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
501*4882a593Smuzhiyun ret = -EFAULT;
502*4882a593Smuzhiyun goto done;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "beacon_stuck_detect_para", (t_u8 *)¶m,
506*4882a593Smuzhiyun sizeof(param));
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(
509*4882a593Smuzhiyun sizeof(mlan_ds_beacon_stuck_param_cfg));
510*4882a593Smuzhiyun if (ioctl_req == NULL) {
511*4882a593Smuzhiyun LEAVE();
512*4882a593Smuzhiyun return -ENOMEM;
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun pm = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
516*4882a593Smuzhiyun pm->sub_command = MLAN_OID_MISC_BEACON_STUCK;
517*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun pm->param.beacon_stuck_cfg.action = param.action;
520*4882a593Smuzhiyun pm->param.beacon_stuck_cfg.beacon_stuck_detect_count =
521*4882a593Smuzhiyun param.beacon_stuck_detect_count;
522*4882a593Smuzhiyun pm->param.beacon_stuck_cfg.recovery_confirm_count =
523*4882a593Smuzhiyun param.recovery_confirm_count;
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
528*4882a593Smuzhiyun ret = -EFAULT;
529*4882a593Smuzhiyun goto done;
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun param.action = pm->param.beacon_stuck_cfg.action;
533*4882a593Smuzhiyun param.beacon_stuck_detect_count =
534*4882a593Smuzhiyun pm->param.beacon_stuck_cfg.beacon_stuck_detect_count;
535*4882a593Smuzhiyun param.recovery_confirm_count =
536*4882a593Smuzhiyun pm->param.beacon_stuck_cfg.recovery_confirm_count;
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun /* Copy to user */
539*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
540*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
541*4882a593Smuzhiyun ret = -EFAULT;
542*4882a593Smuzhiyun goto done;
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun done:
546*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
547*4882a593Smuzhiyun kfree(ioctl_req);
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun LEAVE();
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun return ret;
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun /**
555*4882a593Smuzhiyun * @brief configure tx_pause settings
556*4882a593Smuzhiyun *
557*4882a593Smuzhiyun * @param dev A pointer to net_device structure
558*4882a593Smuzhiyun * @param req A pointer to ifreq structure
559*4882a593Smuzhiyun * @return 0 --success, otherwise fail
560*4882a593Smuzhiyun */
woal_uap_txdatapause(struct net_device * dev,struct ifreq * req)561*4882a593Smuzhiyun static int woal_uap_txdatapause(struct net_device *dev, struct ifreq *req)
562*4882a593Smuzhiyun {
563*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
564*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
565*4882a593Smuzhiyun mlan_ds_misc_cfg *misc = NULL;
566*4882a593Smuzhiyun tx_data_pause_para param;
567*4882a593Smuzhiyun int ret = 0;
568*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun ENTER();
571*4882a593Smuzhiyun memset(¶m, 0, sizeof(param));
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun /* Sanity check */
574*4882a593Smuzhiyun if (req->ifr_data == NULL) {
575*4882a593Smuzhiyun PRINTM(MERROR, "woal_uap_txdatapause corrupt data\n");
576*4882a593Smuzhiyun ret = -EFAULT;
577*4882a593Smuzhiyun goto done;
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
580*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
581*4882a593Smuzhiyun ret = -EFAULT;
582*4882a593Smuzhiyun goto done;
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "tx_data_pause_para", (t_u8 *)¶m,
585*4882a593Smuzhiyun sizeof(param));
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
588*4882a593Smuzhiyun if (ioctl_req == NULL) {
589*4882a593Smuzhiyun LEAVE();
590*4882a593Smuzhiyun return -ENOMEM;
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
593*4882a593Smuzhiyun misc->sub_command = MLAN_OID_MISC_TX_DATAPAUSE;
594*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun if (!param.action) {
597*4882a593Smuzhiyun /* Get Tx data pause status from MLAN */
598*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_GET;
599*4882a593Smuzhiyun } else {
600*4882a593Smuzhiyun /* Set Tx data pause in MLAN */
601*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
602*4882a593Smuzhiyun misc->param.tx_datapause.tx_pause = param.txpause;
603*4882a593Smuzhiyun misc->param.tx_datapause.tx_buf_cnt = param.txbufcnt;
604*4882a593Smuzhiyun }
605*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
606*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
607*4882a593Smuzhiyun ret = -EFAULT;
608*4882a593Smuzhiyun goto done;
609*4882a593Smuzhiyun }
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun param.txpause = misc->param.tx_datapause.tx_pause;
612*4882a593Smuzhiyun param.txbufcnt = misc->param.tx_datapause.tx_buf_cnt;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun /* Copy to user */
615*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
616*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
617*4882a593Smuzhiyun ret = -EFAULT;
618*4882a593Smuzhiyun goto done;
619*4882a593Smuzhiyun }
620*4882a593Smuzhiyun done:
621*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
622*4882a593Smuzhiyun kfree(ioctl_req);
623*4882a593Smuzhiyun LEAVE();
624*4882a593Smuzhiyun return ret;
625*4882a593Smuzhiyun }
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun #ifdef SDIO
628*4882a593Smuzhiyun /**
629*4882a593Smuzhiyun * @brief uap sdcmd52rw ioctl handler
630*4882a593Smuzhiyun *
631*4882a593Smuzhiyun * @param dev A pointer to net_device structure
632*4882a593Smuzhiyun * @param req A pointer to ifreq structure
633*4882a593Smuzhiyun * @return 0 --success, otherwise fail
634*4882a593Smuzhiyun */
woal_uap_sdcmd52_rw(struct net_device * dev,struct ifreq * req)635*4882a593Smuzhiyun static int woal_uap_sdcmd52_rw(struct net_device *dev, struct ifreq *req)
636*4882a593Smuzhiyun {
637*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
638*4882a593Smuzhiyun sdcmd52_para param;
639*4882a593Smuzhiyun t_u8 func, data = 0;
640*4882a593Smuzhiyun int ret = 0, reg;
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun ENTER();
643*4882a593Smuzhiyun memset(¶m, 0, sizeof(param));
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun /* Sanity check */
646*4882a593Smuzhiyun if (req->ifr_data == NULL) {
647*4882a593Smuzhiyun PRINTM(MERROR, "woal_uap_sdcmd52_rw() corrupt data\n");
648*4882a593Smuzhiyun ret = -EFAULT;
649*4882a593Smuzhiyun goto done;
650*4882a593Smuzhiyun }
651*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
652*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
653*4882a593Smuzhiyun ret = -EFAULT;
654*4882a593Smuzhiyun goto done;
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun func = (t_u8)param.cmd52_params[0];
658*4882a593Smuzhiyun reg = (t_u32)param.cmd52_params[1];
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun if (!param.action) {
661*4882a593Smuzhiyun PRINTM(MINFO, "Cmd52 read, func=%d, reg=0x%08X\n", func, reg);
662*4882a593Smuzhiyun #ifdef SDIO_MMC
663*4882a593Smuzhiyun sdio_claim_host(
664*4882a593Smuzhiyun ((struct sdio_mmc_card *)priv->phandle->card)->func);
665*4882a593Smuzhiyun if (func)
666*4882a593Smuzhiyun data = sdio_readb(
667*4882a593Smuzhiyun ((struct sdio_mmc_card *)priv->phandle->card)
668*4882a593Smuzhiyun ->func,
669*4882a593Smuzhiyun reg, &ret);
670*4882a593Smuzhiyun else
671*4882a593Smuzhiyun data = sdio_f0_readb(
672*4882a593Smuzhiyun ((struct sdio_mmc_card *)priv->phandle->card)
673*4882a593Smuzhiyun ->func,
674*4882a593Smuzhiyun reg, &ret);
675*4882a593Smuzhiyun sdio_release_host(
676*4882a593Smuzhiyun ((struct sdio_mmc_card *)priv->phandle->card)->func);
677*4882a593Smuzhiyun if (ret) {
678*4882a593Smuzhiyun PRINTM(MERROR,
679*4882a593Smuzhiyun "sdio_readb: reading register 0x%X failed\n",
680*4882a593Smuzhiyun reg);
681*4882a593Smuzhiyun goto done;
682*4882a593Smuzhiyun }
683*4882a593Smuzhiyun #else
684*4882a593Smuzhiyun if (sdio_read_ioreg(priv->phandle->card, func, reg, &data) <
685*4882a593Smuzhiyun 0) {
686*4882a593Smuzhiyun PRINTM(MERROR,
687*4882a593Smuzhiyun "sdio_read_ioreg: reading register 0x%X failed\n",
688*4882a593Smuzhiyun reg);
689*4882a593Smuzhiyun ret = MLAN_STATUS_FAILURE;
690*4882a593Smuzhiyun goto done;
691*4882a593Smuzhiyun }
692*4882a593Smuzhiyun #endif
693*4882a593Smuzhiyun param.cmd52_params[2] = data;
694*4882a593Smuzhiyun } else {
695*4882a593Smuzhiyun data = (t_u8)param.cmd52_params[2];
696*4882a593Smuzhiyun PRINTM(MINFO, "Cmd52 write, func=%d, reg=0x%08X, data=0x%02X\n",
697*4882a593Smuzhiyun func, reg, data);
698*4882a593Smuzhiyun #ifdef SDIO_MMC
699*4882a593Smuzhiyun sdio_claim_host(
700*4882a593Smuzhiyun ((struct sdio_mmc_card *)priv->phandle->card)->func);
701*4882a593Smuzhiyun if (func)
702*4882a593Smuzhiyun sdio_writeb(
703*4882a593Smuzhiyun ((struct sdio_mmc_card *)priv->phandle->card)
704*4882a593Smuzhiyun ->func,
705*4882a593Smuzhiyun data, reg, &ret);
706*4882a593Smuzhiyun else
707*4882a593Smuzhiyun sdio_f0_writeb(
708*4882a593Smuzhiyun ((struct sdio_mmc_card *)priv->phandle->card)
709*4882a593Smuzhiyun ->func,
710*4882a593Smuzhiyun data, reg, &ret);
711*4882a593Smuzhiyun sdio_release_host(
712*4882a593Smuzhiyun ((struct sdio_mmc_card *)priv->phandle->card)->func);
713*4882a593Smuzhiyun if (ret) {
714*4882a593Smuzhiyun PRINTM(MERROR,
715*4882a593Smuzhiyun "sdio_writeb: writing register 0x%X failed\n",
716*4882a593Smuzhiyun reg);
717*4882a593Smuzhiyun goto done;
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun #else
720*4882a593Smuzhiyun if (sdio_write_ioreg(priv->phandle->card, func, reg, data) <
721*4882a593Smuzhiyun 0) {
722*4882a593Smuzhiyun PRINTM(MERROR,
723*4882a593Smuzhiyun "sdio_write_ioreg: writing register 0x%X failed\n",
724*4882a593Smuzhiyun reg);
725*4882a593Smuzhiyun ret = MLAN_STATUS_FAILURE;
726*4882a593Smuzhiyun goto done;
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun #endif
729*4882a593Smuzhiyun }
730*4882a593Smuzhiyun /* Copy to user */
731*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
732*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
733*4882a593Smuzhiyun ret = -EFAULT;
734*4882a593Smuzhiyun }
735*4882a593Smuzhiyun done:
736*4882a593Smuzhiyun LEAVE();
737*4882a593Smuzhiyun return ret;
738*4882a593Smuzhiyun }
739*4882a593Smuzhiyun #endif
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun /**
742*4882a593Smuzhiyun * @brief enable/disable 11h
743*4882a593Smuzhiyun *
744*4882a593Smuzhiyun * @param enable MTRUE/MFALSE
745*4882a593Smuzhiyun * @return 0 --success, otherwise fail
746*4882a593Smuzhiyun */
woal_uap_11h_ctrl(moal_private * priv,t_u32 enable)747*4882a593Smuzhiyun int woal_uap_11h_ctrl(moal_private *priv, t_u32 enable)
748*4882a593Smuzhiyun {
749*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
750*4882a593Smuzhiyun mlan_ds_snmp_mib *snmp = NULL;
751*4882a593Smuzhiyun int ret = 0;
752*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
753*4882a593Smuzhiyun ENTER();
754*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
755*4882a593Smuzhiyun if (ioctl_req == NULL) {
756*4882a593Smuzhiyun LEAVE();
757*4882a593Smuzhiyun return -ENOMEM;
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun snmp = (mlan_ds_snmp_mib *)ioctl_req->pbuf;
760*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_SNMP_MIB;
761*4882a593Smuzhiyun snmp->sub_command = MLAN_OID_SNMP_MIB_DOT11H;
762*4882a593Smuzhiyun snmp->param.oid_value = enable;
763*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
764*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
765*4882a593Smuzhiyun ret = -EFAULT;
766*4882a593Smuzhiyun goto done;
767*4882a593Smuzhiyun }
768*4882a593Smuzhiyun done:
769*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
770*4882a593Smuzhiyun kfree(ioctl_req);
771*4882a593Smuzhiyun LEAVE();
772*4882a593Smuzhiyun return ret;
773*4882a593Smuzhiyun }
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun /**
776*4882a593Smuzhiyun * @brief configure snmp mib
777*4882a593Smuzhiyun *
778*4882a593Smuzhiyun * @param dev A pointer to net_device structure
779*4882a593Smuzhiyun * @param req A pointer to ifreq structure
780*4882a593Smuzhiyun * @return 0 --success, otherwise fail
781*4882a593Smuzhiyun */
woal_uap_snmp_mib(struct net_device * dev,struct ifreq * req)782*4882a593Smuzhiyun static int woal_uap_snmp_mib(struct net_device *dev, struct ifreq *req)
783*4882a593Smuzhiyun {
784*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
785*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
786*4882a593Smuzhiyun mlan_ds_snmp_mib *snmp = NULL;
787*4882a593Smuzhiyun snmp_mib_para param;
788*4882a593Smuzhiyun t_u8 value[MAX_SNMP_VALUE_SIZE];
789*4882a593Smuzhiyun int ret = 0;
790*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun ENTER();
793*4882a593Smuzhiyun memset(¶m, 0, sizeof(param));
794*4882a593Smuzhiyun memset(value, 0, MAX_SNMP_VALUE_SIZE);
795*4882a593Smuzhiyun
796*4882a593Smuzhiyun /* Sanity check */
797*4882a593Smuzhiyun if (req->ifr_data == NULL) {
798*4882a593Smuzhiyun PRINTM(MERROR, "woal_uap_snmp_mib() corrupt data\n");
799*4882a593Smuzhiyun ret = -EFAULT;
800*4882a593Smuzhiyun goto done;
801*4882a593Smuzhiyun }
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun /* Copy from user */
804*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
805*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
806*4882a593Smuzhiyun ret = -EFAULT;
807*4882a593Smuzhiyun goto done;
808*4882a593Smuzhiyun }
809*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "snmp_mib_para", (t_u8 *)¶m, sizeof(param));
810*4882a593Smuzhiyun if (param.action) {
811*4882a593Smuzhiyun if (copy_from_user(value, req->ifr_data + sizeof(param),
812*4882a593Smuzhiyun MIN(param.oid_val_len,
813*4882a593Smuzhiyun MAX_SNMP_VALUE_SIZE))) {
814*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
815*4882a593Smuzhiyun ret = -EFAULT;
816*4882a593Smuzhiyun goto done;
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "snmp_mib_para value", value,
819*4882a593Smuzhiyun MIN(param.oid_val_len, sizeof(t_u32)));
820*4882a593Smuzhiyun }
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
823*4882a593Smuzhiyun if (ioctl_req == NULL) {
824*4882a593Smuzhiyun LEAVE();
825*4882a593Smuzhiyun return -ENOMEM;
826*4882a593Smuzhiyun }
827*4882a593Smuzhiyun snmp = (mlan_ds_snmp_mib *)ioctl_req->pbuf;
828*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_SNMP_MIB;
829*4882a593Smuzhiyun switch (param.oid) {
830*4882a593Smuzhiyun case OID_80211D_ENABLE:
831*4882a593Smuzhiyun snmp->sub_command = MLAN_OID_SNMP_MIB_DOT11D;
832*4882a593Smuzhiyun break;
833*4882a593Smuzhiyun case OID_80211H_ENABLE:
834*4882a593Smuzhiyun snmp->sub_command = MLAN_OID_SNMP_MIB_DOT11H;
835*4882a593Smuzhiyun break;
836*4882a593Smuzhiyun default:
837*4882a593Smuzhiyun ret = -EINVAL;
838*4882a593Smuzhiyun PRINTM(MERROR, "%s: Unsupported SNMP_MIB OID (%d).\n", __func__,
839*4882a593Smuzhiyun param.oid);
840*4882a593Smuzhiyun goto done;
841*4882a593Smuzhiyun }
842*4882a593Smuzhiyun
843*4882a593Smuzhiyun if (!param.action) {
844*4882a593Smuzhiyun /* Get mib value from MLAN */
845*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_GET;
846*4882a593Smuzhiyun } else {
847*4882a593Smuzhiyun /* Set mib value to MLAN */
848*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
849*4882a593Smuzhiyun snmp->param.oid_value = *(t_u32 *)value;
850*4882a593Smuzhiyun }
851*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
852*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
853*4882a593Smuzhiyun ret = -EFAULT;
854*4882a593Smuzhiyun goto done;
855*4882a593Smuzhiyun }
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun /* Copy to user */
858*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
859*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
860*4882a593Smuzhiyun ret = -EFAULT;
861*4882a593Smuzhiyun goto done;
862*4882a593Smuzhiyun }
863*4882a593Smuzhiyun if (!param.action) { /* GET */
864*4882a593Smuzhiyun if (copy_to_user(req->ifr_data + sizeof(param),
865*4882a593Smuzhiyun &snmp->param.oid_value,
866*4882a593Smuzhiyun MIN(param.oid_val_len, sizeof(t_u32)))) {
867*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
868*4882a593Smuzhiyun ret = -EFAULT;
869*4882a593Smuzhiyun goto done;
870*4882a593Smuzhiyun }
871*4882a593Smuzhiyun }
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun done:
874*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
875*4882a593Smuzhiyun kfree(ioctl_req);
876*4882a593Smuzhiyun LEAVE();
877*4882a593Smuzhiyun return ret;
878*4882a593Smuzhiyun }
879*4882a593Smuzhiyun
880*4882a593Smuzhiyun /**
881*4882a593Smuzhiyun * @brief configure domain info
882*4882a593Smuzhiyun *
883*4882a593Smuzhiyun * @param dev A pointer to net_device structure
884*4882a593Smuzhiyun * @param req A pointer to ifreq structure
885*4882a593Smuzhiyun * @return 0 --success, otherwise fail
886*4882a593Smuzhiyun */
woal_uap_domain_info(struct net_device * dev,struct ifreq * req)887*4882a593Smuzhiyun static int woal_uap_domain_info(struct net_device *dev, struct ifreq *req)
888*4882a593Smuzhiyun {
889*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
890*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
891*4882a593Smuzhiyun mlan_ds_11d_cfg *cfg11d = NULL;
892*4882a593Smuzhiyun domain_info_para param;
893*4882a593Smuzhiyun t_u8 tlv[MAX_DOMAIN_TLV_LEN + MAX_REG_DOMAIN_TLV_LEN];
894*4882a593Smuzhiyun t_u16 tlv_data_len = 0;
895*4882a593Smuzhiyun int ret = 0;
896*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun ENTER();
899*4882a593Smuzhiyun memset(¶m, 0, sizeof(param));
900*4882a593Smuzhiyun memset(tlv, 0, MAX_DOMAIN_TLV_LEN + MAX_REG_DOMAIN_TLV_LEN);
901*4882a593Smuzhiyun
902*4882a593Smuzhiyun /* Sanity check */
903*4882a593Smuzhiyun if (req->ifr_data == NULL) {
904*4882a593Smuzhiyun PRINTM(MERROR, "woal_uap_domain_info() corrupt data\n");
905*4882a593Smuzhiyun ret = -EFAULT;
906*4882a593Smuzhiyun goto done;
907*4882a593Smuzhiyun }
908*4882a593Smuzhiyun
909*4882a593Smuzhiyun /* Copy from user */
910*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
911*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
912*4882a593Smuzhiyun ret = -EFAULT;
913*4882a593Smuzhiyun goto done;
914*4882a593Smuzhiyun }
915*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "domain_info_para", (t_u8 *)¶m, sizeof(param));
916*4882a593Smuzhiyun if (param.action) {
917*4882a593Smuzhiyun /* get tlv header */
918*4882a593Smuzhiyun if (copy_from_user(tlv, req->ifr_data + sizeof(param),
919*4882a593Smuzhiyun TLV_HEADER_LEN)) {
920*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
921*4882a593Smuzhiyun ret = -EFAULT;
922*4882a593Smuzhiyun goto done;
923*4882a593Smuzhiyun }
924*4882a593Smuzhiyun tlv_data_len = ((t_u16 *)(tlv))[1];
925*4882a593Smuzhiyun tlv_data_len += MAX_REG_DOMAIN_TLV_LEN;
926*4882a593Smuzhiyun if ((TLV_HEADER_LEN + tlv_data_len) > (int)sizeof(tlv)) {
927*4882a593Smuzhiyun PRINTM(MERROR, "TLV buffer is overflowed");
928*4882a593Smuzhiyun ret = -EINVAL;
929*4882a593Smuzhiyun goto done;
930*4882a593Smuzhiyun }
931*4882a593Smuzhiyun /* get full tlv */
932*4882a593Smuzhiyun if (copy_from_user(tlv, req->ifr_data + sizeof(param),
933*4882a593Smuzhiyun TLV_HEADER_LEN + tlv_data_len)) {
934*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
935*4882a593Smuzhiyun ret = -EFAULT;
936*4882a593Smuzhiyun goto done;
937*4882a593Smuzhiyun }
938*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "domain_info_para tlv", tlv,
939*4882a593Smuzhiyun TLV_HEADER_LEN + tlv_data_len);
940*4882a593Smuzhiyun }
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11d_cfg));
943*4882a593Smuzhiyun if (ioctl_req == NULL) {
944*4882a593Smuzhiyun LEAVE();
945*4882a593Smuzhiyun return -ENOMEM;
946*4882a593Smuzhiyun }
947*4882a593Smuzhiyun cfg11d = (mlan_ds_11d_cfg *)ioctl_req->pbuf;
948*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_11D_CFG;
949*4882a593Smuzhiyun cfg11d->sub_command = MLAN_OID_11D_DOMAIN_INFO;
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun if (!param.action) {
952*4882a593Smuzhiyun /* Get mib value from MLAN */
953*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_GET;
954*4882a593Smuzhiyun } else {
955*4882a593Smuzhiyun /* Set mib value to MLAN */
956*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
957*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, cfg11d->param.domain_tlv, tlv,
958*4882a593Smuzhiyun TLV_HEADER_LEN + tlv_data_len,
959*4882a593Smuzhiyun sizeof(cfg11d->param.domain_tlv));
960*4882a593Smuzhiyun }
961*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
962*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
963*4882a593Smuzhiyun ret = -EFAULT;
964*4882a593Smuzhiyun goto done;
965*4882a593Smuzhiyun }
966*4882a593Smuzhiyun
967*4882a593Smuzhiyun /* Copy to user */
968*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
969*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
970*4882a593Smuzhiyun ret = -EFAULT;
971*4882a593Smuzhiyun goto done;
972*4882a593Smuzhiyun }
973*4882a593Smuzhiyun if (!param.action) { /* GET */
974*4882a593Smuzhiyun tlv_data_len = ((t_u16 *)(cfg11d->param.domain_tlv))[1];
975*4882a593Smuzhiyun if (copy_to_user(req->ifr_data + sizeof(param),
976*4882a593Smuzhiyun &cfg11d->param.domain_tlv,
977*4882a593Smuzhiyun TLV_HEADER_LEN + tlv_data_len)) {
978*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
979*4882a593Smuzhiyun ret = -EFAULT;
980*4882a593Smuzhiyun goto done;
981*4882a593Smuzhiyun }
982*4882a593Smuzhiyun }
983*4882a593Smuzhiyun
984*4882a593Smuzhiyun done:
985*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
986*4882a593Smuzhiyun kfree(ioctl_req);
987*4882a593Smuzhiyun LEAVE();
988*4882a593Smuzhiyun return ret;
989*4882a593Smuzhiyun }
990*4882a593Smuzhiyun
991*4882a593Smuzhiyun /**
992*4882a593Smuzhiyun * @brief configure dfs testing settings
993*4882a593Smuzhiyun *
994*4882a593Smuzhiyun * @param dev A pointer to net_device structure
995*4882a593Smuzhiyun * @param req A pointer to ifreq structure
996*4882a593Smuzhiyun * @return 0 --success, otherwise fail
997*4882a593Smuzhiyun */
woal_uap_dfs_testing(struct net_device * dev,struct ifreq * req)998*4882a593Smuzhiyun static int woal_uap_dfs_testing(struct net_device *dev, struct ifreq *req)
999*4882a593Smuzhiyun {
1000*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1001*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
1002*4882a593Smuzhiyun mlan_ds_11h_cfg *cfg11h = NULL;
1003*4882a593Smuzhiyun dfs_testing_para param;
1004*4882a593Smuzhiyun int ret = 0;
1005*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
1006*4882a593Smuzhiyun
1007*4882a593Smuzhiyun ENTER();
1008*4882a593Smuzhiyun memset(¶m, 0, sizeof(param));
1009*4882a593Smuzhiyun
1010*4882a593Smuzhiyun /* Sanity check */
1011*4882a593Smuzhiyun if (req->ifr_data == NULL) {
1012*4882a593Smuzhiyun PRINTM(MERROR, "woal_uap_dfs_testing() corrupt data\n");
1013*4882a593Smuzhiyun ret = -EFAULT;
1014*4882a593Smuzhiyun goto done;
1015*4882a593Smuzhiyun }
1016*4882a593Smuzhiyun
1017*4882a593Smuzhiyun /* Copy from user */
1018*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
1019*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
1020*4882a593Smuzhiyun ret = -EFAULT;
1021*4882a593Smuzhiyun goto done;
1022*4882a593Smuzhiyun }
1023*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "dfs_testing_para", (t_u8 *)¶m, sizeof(param));
1024*4882a593Smuzhiyun
1025*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
1026*4882a593Smuzhiyun if (ioctl_req == NULL) {
1027*4882a593Smuzhiyun LEAVE();
1028*4882a593Smuzhiyun return -ENOMEM;
1029*4882a593Smuzhiyun }
1030*4882a593Smuzhiyun cfg11h = (mlan_ds_11h_cfg *)ioctl_req->pbuf;
1031*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_11H_CFG;
1032*4882a593Smuzhiyun cfg11h->sub_command = MLAN_OID_11H_DFS_TESTING;
1033*4882a593Smuzhiyun
1034*4882a593Smuzhiyun if (!param.action) {
1035*4882a593Smuzhiyun /* Get mib value from MLAN */
1036*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_GET;
1037*4882a593Smuzhiyun } else {
1038*4882a593Smuzhiyun /* Set mib value to MLAN */
1039*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
1040*4882a593Smuzhiyun cfg11h->param.dfs_testing.usr_cac_period_msec =
1041*4882a593Smuzhiyun param.usr_cac_period * 1000;
1042*4882a593Smuzhiyun cfg11h->param.dfs_testing.usr_nop_period_sec =
1043*4882a593Smuzhiyun param.usr_nop_period;
1044*4882a593Smuzhiyun cfg11h->param.dfs_testing.usr_no_chan_change =
1045*4882a593Smuzhiyun param.no_chan_change;
1046*4882a593Smuzhiyun cfg11h->param.dfs_testing.usr_fixed_new_chan =
1047*4882a593Smuzhiyun param.fixed_new_chan;
1048*4882a593Smuzhiyun cfg11h->param.dfs_testing.usr_cac_restart = param.cac_restart;
1049*4882a593Smuzhiyun priv->phandle->cac_restart = param.cac_restart;
1050*4882a593Smuzhiyun priv->phandle->cac_period_jiffies = param.usr_cac_period * HZ;
1051*4882a593Smuzhiyun priv->user_cac_period_msec =
1052*4882a593Smuzhiyun cfg11h->param.dfs_testing.usr_cac_period_msec;
1053*4882a593Smuzhiyun }
1054*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1055*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
1056*4882a593Smuzhiyun ret = -EFAULT;
1057*4882a593Smuzhiyun goto done;
1058*4882a593Smuzhiyun }
1059*4882a593Smuzhiyun
1060*4882a593Smuzhiyun if (!param.action) { /* GET */
1061*4882a593Smuzhiyun param.usr_cac_period =
1062*4882a593Smuzhiyun cfg11h->param.dfs_testing.usr_cac_period_msec / 1000;
1063*4882a593Smuzhiyun param.usr_nop_period =
1064*4882a593Smuzhiyun cfg11h->param.dfs_testing.usr_nop_period_sec;
1065*4882a593Smuzhiyun param.no_chan_change =
1066*4882a593Smuzhiyun cfg11h->param.dfs_testing.usr_no_chan_change;
1067*4882a593Smuzhiyun param.fixed_new_chan =
1068*4882a593Smuzhiyun cfg11h->param.dfs_testing.usr_fixed_new_chan;
1069*4882a593Smuzhiyun param.cac_restart = cfg11h->param.dfs_testing.usr_cac_restart;
1070*4882a593Smuzhiyun }
1071*4882a593Smuzhiyun /* Copy to user */
1072*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
1073*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
1074*4882a593Smuzhiyun ret = -EFAULT;
1075*4882a593Smuzhiyun goto done;
1076*4882a593Smuzhiyun }
1077*4882a593Smuzhiyun
1078*4882a593Smuzhiyun done:
1079*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
1080*4882a593Smuzhiyun kfree(ioctl_req);
1081*4882a593Smuzhiyun LEAVE();
1082*4882a593Smuzhiyun return ret;
1083*4882a593Smuzhiyun }
1084*4882a593Smuzhiyun
1085*4882a593Smuzhiyun /**
1086*4882a593Smuzhiyun * @brief uap channel NOP status check ioctl handler
1087*4882a593Smuzhiyun *
1088*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
1089*4882a593Smuzhiyun * @param wait_option Wait option
1090*4882a593Smuzhiyun * @param data BSS control type
1091*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1092*4882a593Smuzhiyun */
woal_uap_get_channel_nop_info(moal_private * priv,t_u8 wait_option,mlan_ds_11h_chan_nop_info * ch_info)1093*4882a593Smuzhiyun int woal_uap_get_channel_nop_info(moal_private *priv, t_u8 wait_option,
1094*4882a593Smuzhiyun mlan_ds_11h_chan_nop_info *ch_info)
1095*4882a593Smuzhiyun {
1096*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
1097*4882a593Smuzhiyun mlan_ds_11h_cfg *ds_11hcfg = NULL;
1098*4882a593Smuzhiyun
1099*4882a593Smuzhiyun int ret = 0;
1100*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
1101*4882a593Smuzhiyun
1102*4882a593Smuzhiyun ENTER();
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun if (!ch_info) {
1105*4882a593Smuzhiyun PRINTM(MERROR, "Invalid chan_info\n");
1106*4882a593Smuzhiyun LEAVE();
1107*4882a593Smuzhiyun return -EFAULT;
1108*4882a593Smuzhiyun }
1109*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
1110*4882a593Smuzhiyun if (req == NULL) {
1111*4882a593Smuzhiyun ret = -ENOMEM;
1112*4882a593Smuzhiyun goto done;
1113*4882a593Smuzhiyun }
1114*4882a593Smuzhiyun
1115*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_11H_CFG;
1116*4882a593Smuzhiyun req->action = MLAN_ACT_GET;
1117*4882a593Smuzhiyun
1118*4882a593Smuzhiyun ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
1119*4882a593Smuzhiyun ds_11hcfg->sub_command = MLAN_OID_11H_CHAN_NOP_INFO;
1120*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &ds_11hcfg->param.ch_nop_info, ch_info,
1121*4882a593Smuzhiyun sizeof(mlan_ds_11h_chan_nop_info),
1122*4882a593Smuzhiyun sizeof(ds_11hcfg->param.ch_nop_info));
1123*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, wait_option);
1124*4882a593Smuzhiyun if (status == MLAN_STATUS_FAILURE) {
1125*4882a593Smuzhiyun ret = -EFAULT;
1126*4882a593Smuzhiyun goto done;
1127*4882a593Smuzhiyun }
1128*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, ch_info, &ds_11hcfg->param.ch_nop_info,
1129*4882a593Smuzhiyun sizeof(mlan_ds_11h_chan_nop_info),
1130*4882a593Smuzhiyun sizeof(mlan_ds_11h_chan_nop_info));
1131*4882a593Smuzhiyun
1132*4882a593Smuzhiyun done:
1133*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
1134*4882a593Smuzhiyun kfree(req);
1135*4882a593Smuzhiyun LEAVE();
1136*4882a593Smuzhiyun return ret;
1137*4882a593Smuzhiyun }
1138*4882a593Smuzhiyun
1139*4882a593Smuzhiyun /**
1140*4882a593Smuzhiyun * @brief configure channel switch count
1141*4882a593Smuzhiyun *
1142*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1143*4882a593Smuzhiyun * @param req A pointer to ifreq structure
1144*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1145*4882a593Smuzhiyun */
woal_uap_chan_switch_count_cfg(struct net_device * dev,struct ifreq * req)1146*4882a593Smuzhiyun static int woal_uap_chan_switch_count_cfg(struct net_device *dev,
1147*4882a593Smuzhiyun struct ifreq *req)
1148*4882a593Smuzhiyun {
1149*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1150*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
1151*4882a593Smuzhiyun mlan_ds_11h_cfg *cfg11h = NULL;
1152*4882a593Smuzhiyun cscount_cfg_t param;
1153*4882a593Smuzhiyun int ret = 0;
1154*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
1155*4882a593Smuzhiyun
1156*4882a593Smuzhiyun ENTER();
1157*4882a593Smuzhiyun memset(¶m, 0, sizeof(param));
1158*4882a593Smuzhiyun
1159*4882a593Smuzhiyun /* Sanity check */
1160*4882a593Smuzhiyun if (req->ifr_data == NULL) {
1161*4882a593Smuzhiyun PRINTM(MERROR, "%s corrupt data\n", __func__);
1162*4882a593Smuzhiyun ret = -EFAULT;
1163*4882a593Smuzhiyun goto done;
1164*4882a593Smuzhiyun }
1165*4882a593Smuzhiyun
1166*4882a593Smuzhiyun /* Copy from user */
1167*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
1168*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
1169*4882a593Smuzhiyun ret = -EFAULT;
1170*4882a593Smuzhiyun goto done;
1171*4882a593Smuzhiyun }
1172*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "cscount_cfg_t", (t_u8 *)¶m, sizeof(param));
1173*4882a593Smuzhiyun
1174*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
1175*4882a593Smuzhiyun if (ioctl_req == NULL) {
1176*4882a593Smuzhiyun LEAVE();
1177*4882a593Smuzhiyun return -ENOMEM;
1178*4882a593Smuzhiyun }
1179*4882a593Smuzhiyun cfg11h = (mlan_ds_11h_cfg *)ioctl_req->pbuf;
1180*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_11H_CFG;
1181*4882a593Smuzhiyun cfg11h->sub_command = MLAN_OID_11H_CHAN_SWITCH_COUNT;
1182*4882a593Smuzhiyun
1183*4882a593Smuzhiyun if (!param.action) {
1184*4882a593Smuzhiyun /* Get mib value from MLAN */
1185*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_GET;
1186*4882a593Smuzhiyun } else {
1187*4882a593Smuzhiyun /* Set mib value to MLAN */
1188*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
1189*4882a593Smuzhiyun cfg11h->param.cs_count = param.cs_count;
1190*4882a593Smuzhiyun }
1191*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1192*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
1193*4882a593Smuzhiyun ret = -EFAULT;
1194*4882a593Smuzhiyun goto done;
1195*4882a593Smuzhiyun }
1196*4882a593Smuzhiyun
1197*4882a593Smuzhiyun if (!param.action) { /* GET */
1198*4882a593Smuzhiyun param.cs_count = cfg11h->param.cs_count;
1199*4882a593Smuzhiyun }
1200*4882a593Smuzhiyun /* Copy to user */
1201*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
1202*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
1203*4882a593Smuzhiyun ret = -EFAULT;
1204*4882a593Smuzhiyun goto done;
1205*4882a593Smuzhiyun }
1206*4882a593Smuzhiyun
1207*4882a593Smuzhiyun done:
1208*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
1209*4882a593Smuzhiyun kfree(ioctl_req);
1210*4882a593Smuzhiyun LEAVE();
1211*4882a593Smuzhiyun return ret;
1212*4882a593Smuzhiyun }
1213*4882a593Smuzhiyun
1214*4882a593Smuzhiyun /**
1215*4882a593Smuzhiyun * @brief Configure TX beamforming support
1216*4882a593Smuzhiyun *
1217*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1218*4882a593Smuzhiyun * @param req A pointer to ifreq structure
1219*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1220*4882a593Smuzhiyun */
woal_uap_tx_bf_cfg(struct net_device * dev,struct ifreq * req)1221*4882a593Smuzhiyun static int woal_uap_tx_bf_cfg(struct net_device *dev, struct ifreq *req)
1222*4882a593Smuzhiyun {
1223*4882a593Smuzhiyun int ret = 0;
1224*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1225*4882a593Smuzhiyun mlan_ds_11n_tx_bf_cfg bf_cfg;
1226*4882a593Smuzhiyun tx_bf_cfg_para_hdr param;
1227*4882a593Smuzhiyun t_u16 action = 0;
1228*4882a593Smuzhiyun
1229*4882a593Smuzhiyun ENTER();
1230*4882a593Smuzhiyun
1231*4882a593Smuzhiyun memset(¶m, 0, sizeof(param));
1232*4882a593Smuzhiyun memset(&bf_cfg, 0, sizeof(bf_cfg));
1233*4882a593Smuzhiyun
1234*4882a593Smuzhiyun /* Sanity check */
1235*4882a593Smuzhiyun if (req->ifr_data == NULL) {
1236*4882a593Smuzhiyun PRINTM(MERROR, "woal_uap_tx_bf_cfg corrupt data\n");
1237*4882a593Smuzhiyun ret = -EFAULT;
1238*4882a593Smuzhiyun goto done;
1239*4882a593Smuzhiyun }
1240*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
1241*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
1242*4882a593Smuzhiyun ret = -EFAULT;
1243*4882a593Smuzhiyun goto done;
1244*4882a593Smuzhiyun }
1245*4882a593Smuzhiyun if (!param.action)
1246*4882a593Smuzhiyun /* Get BF configurations */
1247*4882a593Smuzhiyun action = MLAN_ACT_GET;
1248*4882a593Smuzhiyun else
1249*4882a593Smuzhiyun /* Set BF configurations */
1250*4882a593Smuzhiyun action = MLAN_ACT_SET;
1251*4882a593Smuzhiyun if (copy_from_user(&bf_cfg, req->ifr_data + sizeof(tx_bf_cfg_para_hdr),
1252*4882a593Smuzhiyun sizeof(bf_cfg))) {
1253*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
1254*4882a593Smuzhiyun ret = -EFAULT;
1255*4882a593Smuzhiyun goto done;
1256*4882a593Smuzhiyun }
1257*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "bf_cfg", (t_u8 *)&bf_cfg, sizeof(bf_cfg));
1258*4882a593Smuzhiyun
1259*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1260*4882a593Smuzhiyun woal_set_get_tx_bf_cfg(priv, action, &bf_cfg)) {
1261*4882a593Smuzhiyun ret = -EFAULT;
1262*4882a593Smuzhiyun goto done;
1263*4882a593Smuzhiyun }
1264*4882a593Smuzhiyun
1265*4882a593Smuzhiyun /* Copy to user */
1266*4882a593Smuzhiyun if (copy_to_user(req->ifr_data + sizeof(tx_bf_cfg_para_hdr), &bf_cfg,
1267*4882a593Smuzhiyun sizeof(bf_cfg))) {
1268*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
1269*4882a593Smuzhiyun ret = -EFAULT;
1270*4882a593Smuzhiyun goto done;
1271*4882a593Smuzhiyun }
1272*4882a593Smuzhiyun
1273*4882a593Smuzhiyun done:
1274*4882a593Smuzhiyun LEAVE();
1275*4882a593Smuzhiyun return ret;
1276*4882a593Smuzhiyun }
1277*4882a593Smuzhiyun
1278*4882a593Smuzhiyun /**
1279*4882a593Smuzhiyun * @brief Set/Get 11n configurations
1280*4882a593Smuzhiyun *
1281*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1282*4882a593Smuzhiyun * @param req A pointer to ifreq structure
1283*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1284*4882a593Smuzhiyun */
woal_uap_ht_tx_cfg(struct net_device * dev,struct ifreq * req)1285*4882a593Smuzhiyun static int woal_uap_ht_tx_cfg(struct net_device *dev, struct ifreq *req)
1286*4882a593Smuzhiyun {
1287*4882a593Smuzhiyun int ret = 0;
1288*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1289*4882a593Smuzhiyun mlan_ds_11n_cfg *cfg_11n = NULL;
1290*4882a593Smuzhiyun mlan_ds_11n_tx_cfg httx_cfg;
1291*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
1292*4882a593Smuzhiyun ht_tx_cfg_para_hdr param;
1293*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
1294*4882a593Smuzhiyun
1295*4882a593Smuzhiyun ENTER();
1296*4882a593Smuzhiyun
1297*4882a593Smuzhiyun memset(¶m, 0, sizeof(ht_tx_cfg_para_hdr));
1298*4882a593Smuzhiyun memset(&httx_cfg, 0, sizeof(mlan_ds_11n_tx_cfg));
1299*4882a593Smuzhiyun
1300*4882a593Smuzhiyun /* Sanity check */
1301*4882a593Smuzhiyun if (req->ifr_data == NULL) {
1302*4882a593Smuzhiyun PRINTM(MERROR, "woal_uap_ht_tx_cfg corrupt data\n");
1303*4882a593Smuzhiyun ret = -EFAULT;
1304*4882a593Smuzhiyun goto done;
1305*4882a593Smuzhiyun }
1306*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(ht_tx_cfg_para_hdr))) {
1307*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
1308*4882a593Smuzhiyun ret = -EFAULT;
1309*4882a593Smuzhiyun goto done;
1310*4882a593Smuzhiyun }
1311*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
1312*4882a593Smuzhiyun if (ioctl_req == NULL) {
1313*4882a593Smuzhiyun ret = -ENOMEM;
1314*4882a593Smuzhiyun goto done;
1315*4882a593Smuzhiyun }
1316*4882a593Smuzhiyun cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
1317*4882a593Smuzhiyun cfg_11n->sub_command = MLAN_OID_11N_CFG_TX;
1318*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
1319*4882a593Smuzhiyun if (copy_from_user(&httx_cfg,
1320*4882a593Smuzhiyun req->ifr_data + sizeof(ht_tx_cfg_para_hdr),
1321*4882a593Smuzhiyun sizeof(mlan_ds_11n_tx_cfg))) {
1322*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
1323*4882a593Smuzhiyun ret = -EFAULT;
1324*4882a593Smuzhiyun goto done;
1325*4882a593Smuzhiyun }
1326*4882a593Smuzhiyun if (!param.action) {
1327*4882a593Smuzhiyun /* Get 11n tx parameters from MLAN */
1328*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_GET;
1329*4882a593Smuzhiyun } else {
1330*4882a593Smuzhiyun /* Set HT Tx configurations */
1331*4882a593Smuzhiyun cfg_11n->param.tx_cfg.httxcap = httx_cfg.httxcap;
1332*4882a593Smuzhiyun PRINTM(MINFO, "SET: httxcap:0x%x\n", httx_cfg.httxcap);
1333*4882a593Smuzhiyun /* Update 11n tx parameters in MLAN */
1334*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
1335*4882a593Smuzhiyun }
1336*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1337*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
1338*4882a593Smuzhiyun ret = -EFAULT;
1339*4882a593Smuzhiyun goto done;
1340*4882a593Smuzhiyun }
1341*4882a593Smuzhiyun if (ioctl_req->action == MLAN_ACT_GET) {
1342*4882a593Smuzhiyun httx_cfg.httxcap = cfg_11n->param.tx_cfg.httxcap;
1343*4882a593Smuzhiyun PRINTM(MINFO, "GET: httxcap:0x%x\n", httx_cfg.httxcap);
1344*4882a593Smuzhiyun }
1345*4882a593Smuzhiyun /* Copy to user */
1346*4882a593Smuzhiyun if (copy_to_user(req->ifr_data + sizeof(ht_tx_cfg_para_hdr), &httx_cfg,
1347*4882a593Smuzhiyun sizeof(mlan_ds_11n_tx_cfg))) {
1348*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
1349*4882a593Smuzhiyun ret = -EFAULT;
1350*4882a593Smuzhiyun goto done;
1351*4882a593Smuzhiyun }
1352*4882a593Smuzhiyun done:
1353*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
1354*4882a593Smuzhiyun kfree(ioctl_req);
1355*4882a593Smuzhiyun LEAVE();
1356*4882a593Smuzhiyun return ret;
1357*4882a593Smuzhiyun }
1358*4882a593Smuzhiyun
1359*4882a593Smuzhiyun /**
1360*4882a593Smuzhiyun * @brief Set/Get Set/Get 11AC configurations
1361*4882a593Smuzhiyun *
1362*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1363*4882a593Smuzhiyun * @param req A pointer to ifreq structure
1364*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1365*4882a593Smuzhiyun */
woal_uap_vht_cfg(struct net_device * dev,struct ifreq * req)1366*4882a593Smuzhiyun static int woal_uap_vht_cfg(struct net_device *dev, struct ifreq *req)
1367*4882a593Smuzhiyun {
1368*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1369*4882a593Smuzhiyun int ret = 0, resbuf_len = 0;
1370*4882a593Smuzhiyun mlan_ds_11ac_cfg *cfg_11ac = NULL;
1371*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
1372*4882a593Smuzhiyun mlan_ds_11ac_vht_cfg *vhtcfg = NULL, vht_cfg;
1373*4882a593Smuzhiyun t_u8 *respbuf = NULL;
1374*4882a593Smuzhiyun vht_cfg_para_hdr param;
1375*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
1376*4882a593Smuzhiyun #define CMD_RESPBUF_LEN 2048
1377*4882a593Smuzhiyun gfp_t flag;
1378*4882a593Smuzhiyun
1379*4882a593Smuzhiyun ENTER();
1380*4882a593Smuzhiyun
1381*4882a593Smuzhiyun memset(¶m, 0, sizeof(vht_cfg_para_hdr));
1382*4882a593Smuzhiyun
1383*4882a593Smuzhiyun flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
1384*4882a593Smuzhiyun respbuf = kzalloc(CMD_RESPBUF_LEN, flag);
1385*4882a593Smuzhiyun if (!respbuf) {
1386*4882a593Smuzhiyun ret = -ENOMEM;
1387*4882a593Smuzhiyun goto done;
1388*4882a593Smuzhiyun }
1389*4882a593Smuzhiyun
1390*4882a593Smuzhiyun /* Sanity check */
1391*4882a593Smuzhiyun if (req->ifr_data == NULL) {
1392*4882a593Smuzhiyun PRINTM(MERROR, "woal_uap_ht_tx_cfg corrupt data\n");
1393*4882a593Smuzhiyun ret = -EFAULT;
1394*4882a593Smuzhiyun goto done;
1395*4882a593Smuzhiyun }
1396*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(vht_cfg_para_hdr))) {
1397*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
1398*4882a593Smuzhiyun ret = -EFAULT;
1399*4882a593Smuzhiyun goto done;
1400*4882a593Smuzhiyun }
1401*4882a593Smuzhiyun
1402*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11ac_cfg));
1403*4882a593Smuzhiyun if (ioctl_req == NULL) {
1404*4882a593Smuzhiyun ret = -ENOMEM;
1405*4882a593Smuzhiyun goto done;
1406*4882a593Smuzhiyun }
1407*4882a593Smuzhiyun cfg_11ac = (mlan_ds_11ac_cfg *)ioctl_req->pbuf;
1408*4882a593Smuzhiyun cfg_11ac->sub_command = MLAN_OID_11AC_VHT_CFG;
1409*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_11AC_CFG;
1410*4882a593Smuzhiyun if (copy_from_user(&vht_cfg, req->ifr_data + sizeof(vht_cfg_para_hdr),
1411*4882a593Smuzhiyun sizeof(mlan_ds_11ac_vht_cfg))) {
1412*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
1413*4882a593Smuzhiyun ret = -EFAULT;
1414*4882a593Smuzhiyun goto done;
1415*4882a593Smuzhiyun }
1416*4882a593Smuzhiyun if (vht_cfg.band == BAND_SELECT_BOTH) {
1417*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.band = (BAND_SELECT_BG | BAND_SELECT_A);
1418*4882a593Smuzhiyun } else {
1419*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.band = vht_cfg.band;
1420*4882a593Smuzhiyun }
1421*4882a593Smuzhiyun if (!param.action) {
1422*4882a593Smuzhiyun /* GET operation */
1423*4882a593Smuzhiyun if (vht_cfg.band == BAND_SELECT_BOTH) {
1424*4882a593Smuzhiyun /* if get both bands, get BG first */
1425*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.band = BAND_SELECT_BG;
1426*4882a593Smuzhiyun }
1427*4882a593Smuzhiyun PRINTM(MINFO, "GET: vhtcfg band: 0x%x\n",
1428*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.band);
1429*4882a593Smuzhiyun if (priv->bss_role == MLAN_BSS_ROLE_UAP)
1430*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.txrx = MLAN_RADIO_RX;
1431*4882a593Smuzhiyun else
1432*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.txrx = vht_cfg.txrx;
1433*4882a593Smuzhiyun PRINTM(MINFO, "GET: vhtcfg txrx: 0x%x\n",
1434*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.txrx);
1435*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_GET;
1436*4882a593Smuzhiyun } else {
1437*4882a593Smuzhiyun /* Band */
1438*4882a593Smuzhiyun if (vht_cfg.band == BAND_SELECT_BOTH)
1439*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.band =
1440*4882a593Smuzhiyun (BAND_SELECT_BG | BAND_SELECT_A);
1441*4882a593Smuzhiyun else
1442*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.band = vht_cfg.band;
1443*4882a593Smuzhiyun PRINTM(MINFO, "SET: vhtcfg band: 0x%x\n",
1444*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.band);
1445*4882a593Smuzhiyun /* Tx/Rx */
1446*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.txrx = vht_cfg.txrx;
1447*4882a593Smuzhiyun PRINTM(MINFO, "SET: vhtcfg txrx: 0x%x\n",
1448*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.txrx);
1449*4882a593Smuzhiyun /* BW cfg */
1450*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.bwcfg = vht_cfg.bwcfg;
1451*4882a593Smuzhiyun PRINTM(MINFO, "SET: vhtcfg bw cfg:0x%x\n",
1452*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.bwcfg);
1453*4882a593Smuzhiyun
1454*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.vht_cap_info = vht_cfg.vht_cap_info;
1455*4882a593Smuzhiyun PRINTM(MINFO, "SET: vhtcfg vht_cap_info:0x%x\n",
1456*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.vht_cap_info);
1457*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.vht_tx_mcs = vht_cfg.vht_tx_mcs;
1458*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.vht_rx_mcs = vht_cfg.vht_rx_mcs;
1459*4882a593Smuzhiyun /* Update 11AC parameters in MLAN */
1460*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
1461*4882a593Smuzhiyun }
1462*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1463*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
1464*4882a593Smuzhiyun ret = -EFAULT;
1465*4882a593Smuzhiyun goto done;
1466*4882a593Smuzhiyun }
1467*4882a593Smuzhiyun
1468*4882a593Smuzhiyun /* number of vhtcfg entries */
1469*4882a593Smuzhiyun *respbuf = 1;
1470*4882a593Smuzhiyun vhtcfg = (mlan_ds_11ac_vht_cfg *)(respbuf + 1);
1471*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, vhtcfg, &cfg_11ac->param.vht_cfg,
1472*4882a593Smuzhiyun sizeof(mlan_ds_11ac_vht_cfg),
1473*4882a593Smuzhiyun sizeof(mlan_ds_11ac_vht_cfg));
1474*4882a593Smuzhiyun resbuf_len = 1 + sizeof(mlan_ds_11ac_vht_cfg);
1475*4882a593Smuzhiyun
1476*4882a593Smuzhiyun if ((ioctl_req->action == MLAN_ACT_GET) &&
1477*4882a593Smuzhiyun (vht_cfg.band == BAND_SELECT_BOTH)) {
1478*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.band = BAND_SELECT_A;
1479*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1480*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
1481*4882a593Smuzhiyun ret = -EFAULT;
1482*4882a593Smuzhiyun goto done;
1483*4882a593Smuzhiyun }
1484*4882a593Smuzhiyun /* number of vhtcfg entries */
1485*4882a593Smuzhiyun *respbuf = 2;
1486*4882a593Smuzhiyun vhtcfg++;
1487*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, vhtcfg, &cfg_11ac->param.vht_cfg,
1488*4882a593Smuzhiyun sizeof(mlan_ds_11ac_vht_cfg),
1489*4882a593Smuzhiyun sizeof(mlan_ds_11ac_vht_cfg));
1490*4882a593Smuzhiyun resbuf_len += sizeof(mlan_ds_11ac_vht_cfg);
1491*4882a593Smuzhiyun }
1492*4882a593Smuzhiyun if (ioctl_req->action == MLAN_ACT_GET) {
1493*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, respbuf, resbuf_len)) {
1494*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed\n");
1495*4882a593Smuzhiyun ret = -EFAULT;
1496*4882a593Smuzhiyun }
1497*4882a593Smuzhiyun }
1498*4882a593Smuzhiyun done:
1499*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
1500*4882a593Smuzhiyun kfree(ioctl_req);
1501*4882a593Smuzhiyun if (respbuf)
1502*4882a593Smuzhiyun kfree(respbuf);
1503*4882a593Smuzhiyun LEAVE();
1504*4882a593Smuzhiyun return ret;
1505*4882a593Smuzhiyun }
1506*4882a593Smuzhiyun
1507*4882a593Smuzhiyun /**
1508*4882a593Smuzhiyun * @brief uap hs_cfg ioctl handler
1509*4882a593Smuzhiyun *
1510*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1511*4882a593Smuzhiyun * @param req A pointer to ifreq structure
1512*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1513*4882a593Smuzhiyun */
woal_uap_hs_cfg(struct net_device * dev,struct ifreq * req,BOOLEAN invoke_hostcmd)1514*4882a593Smuzhiyun static int woal_uap_hs_cfg(struct net_device *dev, struct ifreq *req,
1515*4882a593Smuzhiyun BOOLEAN invoke_hostcmd)
1516*4882a593Smuzhiyun {
1517*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1518*4882a593Smuzhiyun mlan_ds_hs_cfg hscfg;
1519*4882a593Smuzhiyun ds_hs_cfg hs_cfg;
1520*4882a593Smuzhiyun mlan_bss_info bss_info;
1521*4882a593Smuzhiyun t_u16 action;
1522*4882a593Smuzhiyun int ret = 0;
1523*4882a593Smuzhiyun
1524*4882a593Smuzhiyun ENTER();
1525*4882a593Smuzhiyun
1526*4882a593Smuzhiyun memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg));
1527*4882a593Smuzhiyun memset(&hs_cfg, 0, sizeof(ds_hs_cfg));
1528*4882a593Smuzhiyun
1529*4882a593Smuzhiyun /* Sanity check */
1530*4882a593Smuzhiyun if (req->ifr_data == NULL) {
1531*4882a593Smuzhiyun PRINTM(MERROR, "uap_hs_cfg() corrupt data\n");
1532*4882a593Smuzhiyun ret = -EFAULT;
1533*4882a593Smuzhiyun goto done;
1534*4882a593Smuzhiyun }
1535*4882a593Smuzhiyun if (copy_from_user(&hs_cfg, req->ifr_data, sizeof(ds_hs_cfg))) {
1536*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
1537*4882a593Smuzhiyun ret = -EFAULT;
1538*4882a593Smuzhiyun goto done;
1539*4882a593Smuzhiyun }
1540*4882a593Smuzhiyun
1541*4882a593Smuzhiyun PRINTM(MIOCTL,
1542*4882a593Smuzhiyun "ioctl hscfg: flags=0x%x condition=0x%x gpio=%d gap=0x%x\n",
1543*4882a593Smuzhiyun hs_cfg.flags, hs_cfg.conditions, (int)hs_cfg.gpio, hs_cfg.gap);
1544*4882a593Smuzhiyun
1545*4882a593Smuzhiyun /* HS config is blocked if HS is already activated */
1546*4882a593Smuzhiyun if ((hs_cfg.flags & HS_CFG_FLAG_CONDITION) &&
1547*4882a593Smuzhiyun (hs_cfg.conditions != HOST_SLEEP_CFG_CANCEL ||
1548*4882a593Smuzhiyun invoke_hostcmd == MFALSE)) {
1549*4882a593Smuzhiyun memset(&bss_info, 0, sizeof(bss_info));
1550*4882a593Smuzhiyun woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
1551*4882a593Smuzhiyun if (bss_info.is_hs_configured) {
1552*4882a593Smuzhiyun PRINTM(MERROR, "HS already configured\n");
1553*4882a593Smuzhiyun ret = -EFAULT;
1554*4882a593Smuzhiyun goto done;
1555*4882a593Smuzhiyun }
1556*4882a593Smuzhiyun }
1557*4882a593Smuzhiyun
1558*4882a593Smuzhiyun if (hs_cfg.flags & HS_CFG_FLAG_SET) {
1559*4882a593Smuzhiyun action = MLAN_ACT_SET;
1560*4882a593Smuzhiyun if (hs_cfg.flags != HS_CFG_FLAG_ALL) {
1561*4882a593Smuzhiyun woal_set_get_hs_params(priv, MLAN_ACT_GET,
1562*4882a593Smuzhiyun MOAL_IOCTL_WAIT, &hscfg);
1563*4882a593Smuzhiyun }
1564*4882a593Smuzhiyun if (hs_cfg.flags & HS_CFG_FLAG_CONDITION)
1565*4882a593Smuzhiyun hscfg.conditions = hs_cfg.conditions;
1566*4882a593Smuzhiyun if (hs_cfg.flags & HS_CFG_FLAG_GPIO)
1567*4882a593Smuzhiyun hscfg.gpio = hs_cfg.gpio;
1568*4882a593Smuzhiyun if (hs_cfg.flags & HS_CFG_FLAG_GAP)
1569*4882a593Smuzhiyun hscfg.gap = hs_cfg.gap;
1570*4882a593Smuzhiyun
1571*4882a593Smuzhiyun if (invoke_hostcmd == MTRUE) {
1572*4882a593Smuzhiyun /* Issue IOCTL to set up parameters */
1573*4882a593Smuzhiyun hscfg.is_invoke_hostcmd = MFALSE;
1574*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1575*4882a593Smuzhiyun woal_set_get_hs_params(priv, action,
1576*4882a593Smuzhiyun MOAL_IOCTL_WAIT, &hscfg)) {
1577*4882a593Smuzhiyun ret = -EFAULT;
1578*4882a593Smuzhiyun goto done;
1579*4882a593Smuzhiyun }
1580*4882a593Smuzhiyun }
1581*4882a593Smuzhiyun } else {
1582*4882a593Smuzhiyun action = MLAN_ACT_GET;
1583*4882a593Smuzhiyun }
1584*4882a593Smuzhiyun
1585*4882a593Smuzhiyun /* Issue IOCTL to invoke hostcmd */
1586*4882a593Smuzhiyun hscfg.is_invoke_hostcmd = invoke_hostcmd;
1587*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1588*4882a593Smuzhiyun woal_set_get_hs_params(priv, action, MOAL_IOCTL_WAIT, &hscfg)) {
1589*4882a593Smuzhiyun ret = -EFAULT;
1590*4882a593Smuzhiyun goto done;
1591*4882a593Smuzhiyun }
1592*4882a593Smuzhiyun if (!(hs_cfg.flags & HS_CFG_FLAG_SET)) {
1593*4882a593Smuzhiyun hs_cfg.flags = HS_CFG_FLAG_CONDITION | HS_CFG_FLAG_GPIO |
1594*4882a593Smuzhiyun HS_CFG_FLAG_GAP;
1595*4882a593Smuzhiyun hs_cfg.conditions = hscfg.conditions;
1596*4882a593Smuzhiyun hs_cfg.gpio = hscfg.gpio;
1597*4882a593Smuzhiyun hs_cfg.gap = hscfg.gap;
1598*4882a593Smuzhiyun /* Copy to user */
1599*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, &hs_cfg, sizeof(ds_hs_cfg))) {
1600*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
1601*4882a593Smuzhiyun ret = -EFAULT;
1602*4882a593Smuzhiyun goto done;
1603*4882a593Smuzhiyun }
1604*4882a593Smuzhiyun }
1605*4882a593Smuzhiyun
1606*4882a593Smuzhiyun done:
1607*4882a593Smuzhiyun LEAVE();
1608*4882a593Smuzhiyun return ret;
1609*4882a593Smuzhiyun }
1610*4882a593Smuzhiyun
1611*4882a593Smuzhiyun /**
1612*4882a593Smuzhiyun * @brief Set Host Sleep parameters
1613*4882a593Smuzhiyun *
1614*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
1615*4882a593Smuzhiyun * @param wrq A pointer to iwreq structure
1616*4882a593Smuzhiyun *
1617*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1618*4882a593Smuzhiyun */
woal_uap_hs_set_para(struct net_device * dev,struct ifreq * req)1619*4882a593Smuzhiyun static int woal_uap_hs_set_para(struct net_device *dev, struct ifreq *req)
1620*4882a593Smuzhiyun {
1621*4882a593Smuzhiyun int ret = 0;
1622*4882a593Smuzhiyun
1623*4882a593Smuzhiyun ENTER();
1624*4882a593Smuzhiyun
1625*4882a593Smuzhiyun if (req->ifr_data != NULL) {
1626*4882a593Smuzhiyun ret = woal_uap_hs_cfg(dev, req, MFALSE);
1627*4882a593Smuzhiyun goto done;
1628*4882a593Smuzhiyun } else {
1629*4882a593Smuzhiyun PRINTM(MERROR, "Invalid data\n");
1630*4882a593Smuzhiyun ret = -EINVAL;
1631*4882a593Smuzhiyun goto done;
1632*4882a593Smuzhiyun }
1633*4882a593Smuzhiyun done:
1634*4882a593Smuzhiyun LEAVE();
1635*4882a593Smuzhiyun return ret;
1636*4882a593Smuzhiyun }
1637*4882a593Smuzhiyun
1638*4882a593Smuzhiyun /**
1639*4882a593Smuzhiyun * @brief uap mgmt_frame_control ioctl handler
1640*4882a593Smuzhiyun *
1641*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1642*4882a593Smuzhiyun * @param req A pointer to ifreq structure
1643*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1644*4882a593Smuzhiyun */
woal_uap_mgmt_frame_control(struct net_device * dev,struct ifreq * req)1645*4882a593Smuzhiyun static int woal_uap_mgmt_frame_control(struct net_device *dev,
1646*4882a593Smuzhiyun struct ifreq *req)
1647*4882a593Smuzhiyun {
1648*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1649*4882a593Smuzhiyun int ret = 0;
1650*4882a593Smuzhiyun t_u16 action = 0;
1651*4882a593Smuzhiyun mgmt_frame_ctrl param;
1652*4882a593Smuzhiyun mlan_uap_bss_param *sys_config = NULL;
1653*4882a593Smuzhiyun
1654*4882a593Smuzhiyun ENTER();
1655*4882a593Smuzhiyun
1656*4882a593Smuzhiyun /* Sanity check */
1657*4882a593Smuzhiyun if (req->ifr_data == NULL) {
1658*4882a593Smuzhiyun PRINTM(MERROR, "uap_mgmt_frame_ctrl() corrupt data\n");
1659*4882a593Smuzhiyun ret = -EFAULT;
1660*4882a593Smuzhiyun goto done;
1661*4882a593Smuzhiyun }
1662*4882a593Smuzhiyun
1663*4882a593Smuzhiyun /* Get user data */
1664*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
1665*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
1666*4882a593Smuzhiyun ret = -EFAULT;
1667*4882a593Smuzhiyun goto done;
1668*4882a593Smuzhiyun }
1669*4882a593Smuzhiyun sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
1670*4882a593Smuzhiyun if (!sys_config) {
1671*4882a593Smuzhiyun PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
1672*4882a593Smuzhiyun ret = -EFAULT;
1673*4882a593Smuzhiyun goto done;
1674*4882a593Smuzhiyun }
1675*4882a593Smuzhiyun
1676*4882a593Smuzhiyun if (param.action)
1677*4882a593Smuzhiyun action = MLAN_ACT_SET;
1678*4882a593Smuzhiyun else
1679*4882a593Smuzhiyun action = MLAN_ACT_GET;
1680*4882a593Smuzhiyun if (action == MLAN_ACT_SET) {
1681*4882a593Smuzhiyun /* Initialize the invalid values so that the correct
1682*4882a593Smuzhiyun values below are downloaded to firmware */
1683*4882a593Smuzhiyun woal_set_sys_config_invalid_data(sys_config);
1684*4882a593Smuzhiyun sys_config->mgmt_ie_passthru_mask = param.mask;
1685*4882a593Smuzhiyun }
1686*4882a593Smuzhiyun
1687*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, action,
1688*4882a593Smuzhiyun MOAL_IOCTL_WAIT,
1689*4882a593Smuzhiyun sys_config)) {
1690*4882a593Smuzhiyun ret = -EFAULT;
1691*4882a593Smuzhiyun goto done;
1692*4882a593Smuzhiyun }
1693*4882a593Smuzhiyun
1694*4882a593Smuzhiyun if (action == MLAN_ACT_GET) {
1695*4882a593Smuzhiyun param.mask = sys_config->mgmt_ie_passthru_mask;
1696*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
1697*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed\n");
1698*4882a593Smuzhiyun ret = -EFAULT;
1699*4882a593Smuzhiyun }
1700*4882a593Smuzhiyun }
1701*4882a593Smuzhiyun done:
1702*4882a593Smuzhiyun kfree(sys_config);
1703*4882a593Smuzhiyun LEAVE();
1704*4882a593Smuzhiyun return ret;
1705*4882a593Smuzhiyun }
1706*4882a593Smuzhiyun
1707*4882a593Smuzhiyun /**
1708*4882a593Smuzhiyun * @brief Set/Get tx rate
1709*4882a593Smuzhiyun *
1710*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1711*4882a593Smuzhiyun * @param req A pointer to ifreq structure
1712*4882a593Smuzhiyun *
1713*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1714*4882a593Smuzhiyun */
woal_uap_tx_rate_cfg(struct net_device * dev,struct ifreq * req)1715*4882a593Smuzhiyun static int woal_uap_tx_rate_cfg(struct net_device *dev, struct ifreq *req)
1716*4882a593Smuzhiyun {
1717*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1718*4882a593Smuzhiyun int ret = 0, i = 0;
1719*4882a593Smuzhiyun mlan_ds_rate *rate = NULL;
1720*4882a593Smuzhiyun mlan_ioctl_req *mreq = NULL;
1721*4882a593Smuzhiyun tx_rate_cfg_t tx_rate_config;
1722*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
1723*4882a593Smuzhiyun
1724*4882a593Smuzhiyun ENTER();
1725*4882a593Smuzhiyun
1726*4882a593Smuzhiyun /* Sanity check */
1727*4882a593Smuzhiyun if (req->ifr_data == NULL) {
1728*4882a593Smuzhiyun PRINTM(MERROR, "uap_tx_rate_cfg() corrupt data\n");
1729*4882a593Smuzhiyun ret = -EFAULT;
1730*4882a593Smuzhiyun goto done;
1731*4882a593Smuzhiyun }
1732*4882a593Smuzhiyun
1733*4882a593Smuzhiyun memset(&tx_rate_config, 0, sizeof(tx_rate_cfg_t));
1734*4882a593Smuzhiyun /* Get user data */
1735*4882a593Smuzhiyun if (copy_from_user(&tx_rate_config, req->ifr_data,
1736*4882a593Smuzhiyun sizeof(tx_rate_cfg_t))) {
1737*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
1738*4882a593Smuzhiyun ret = -EFAULT;
1739*4882a593Smuzhiyun goto done;
1740*4882a593Smuzhiyun }
1741*4882a593Smuzhiyun
1742*4882a593Smuzhiyun mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
1743*4882a593Smuzhiyun if (mreq == NULL) {
1744*4882a593Smuzhiyun ret = -ENOMEM;
1745*4882a593Smuzhiyun goto done;
1746*4882a593Smuzhiyun }
1747*4882a593Smuzhiyun rate = (mlan_ds_rate *)mreq->pbuf;
1748*4882a593Smuzhiyun rate->param.rate_cfg.rate_type = MLAN_RATE_INDEX;
1749*4882a593Smuzhiyun rate->sub_command = MLAN_OID_RATE_CFG;
1750*4882a593Smuzhiyun mreq->req_id = MLAN_IOCTL_RATE;
1751*4882a593Smuzhiyun if (!(tx_rate_config.action))
1752*4882a593Smuzhiyun mreq->action = MLAN_ACT_GET;
1753*4882a593Smuzhiyun else {
1754*4882a593Smuzhiyun if ((tx_rate_config.user_data_cnt <= 0) ||
1755*4882a593Smuzhiyun (tx_rate_config.user_data_cnt > 4)) {
1756*4882a593Smuzhiyun PRINTM(MERROR, "Invalid user_data_cnt\n");
1757*4882a593Smuzhiyun ret = -EINVAL;
1758*4882a593Smuzhiyun goto done;
1759*4882a593Smuzhiyun }
1760*4882a593Smuzhiyun
1761*4882a593Smuzhiyun mreq->action = MLAN_ACT_SET;
1762*4882a593Smuzhiyun if (tx_rate_config.rate_format == AUTO_RATE)
1763*4882a593Smuzhiyun rate->param.rate_cfg.is_rate_auto = 1;
1764*4882a593Smuzhiyun else {
1765*4882a593Smuzhiyun if ((tx_rate_config.rate_format < 0) ||
1766*4882a593Smuzhiyun (tx_rate_config.rate < 0)) {
1767*4882a593Smuzhiyun PRINTM(MERROR,
1768*4882a593Smuzhiyun "Invalid format or rate selection\n");
1769*4882a593Smuzhiyun ret = -EINVAL;
1770*4882a593Smuzhiyun goto done;
1771*4882a593Smuzhiyun }
1772*4882a593Smuzhiyun /* rate_format sanity check */
1773*4882a593Smuzhiyun if ((tx_rate_config.rate_format >
1774*4882a593Smuzhiyun MLAN_RATE_FORMAT_HE)) {
1775*4882a593Smuzhiyun PRINTM(MERROR, "Invalid format selection\n");
1776*4882a593Smuzhiyun ret = -EINVAL;
1777*4882a593Smuzhiyun goto done;
1778*4882a593Smuzhiyun }
1779*4882a593Smuzhiyun rate->param.rate_cfg.rate_format =
1780*4882a593Smuzhiyun tx_rate_config.rate_format;
1781*4882a593Smuzhiyun
1782*4882a593Smuzhiyun /* rate sanity check */
1783*4882a593Smuzhiyun if (tx_rate_config.user_data_cnt >= 2) {
1784*4882a593Smuzhiyun if (((tx_rate_config.rate_format ==
1785*4882a593Smuzhiyun MLAN_RATE_FORMAT_LG) &&
1786*4882a593Smuzhiyun (tx_rate_config.rate >
1787*4882a593Smuzhiyun MLAN_RATE_INDEX_OFDM7)) ||
1788*4882a593Smuzhiyun ((tx_rate_config.rate_format ==
1789*4882a593Smuzhiyun MLAN_RATE_FORMAT_HT) &&
1790*4882a593Smuzhiyun (tx_rate_config.rate != 32) &&
1791*4882a593Smuzhiyun (tx_rate_config.rate > 15)) ||
1792*4882a593Smuzhiyun ((tx_rate_config.rate_format ==
1793*4882a593Smuzhiyun MLAN_RATE_FORMAT_VHT) &&
1794*4882a593Smuzhiyun (tx_rate_config.rate >
1795*4882a593Smuzhiyun MLAN_RATE_INDEX_MCS9)) ||
1796*4882a593Smuzhiyun ((tx_rate_config.rate_format ==
1797*4882a593Smuzhiyun MLAN_RATE_FORMAT_HE) &&
1798*4882a593Smuzhiyun (tx_rate_config.rate >
1799*4882a593Smuzhiyun MLAN_RATE_INDEX_MCS11))) {
1800*4882a593Smuzhiyun PRINTM(MERROR,
1801*4882a593Smuzhiyun "Invalid rate selection\n");
1802*4882a593Smuzhiyun ret = -EINVAL;
1803*4882a593Smuzhiyun goto done;
1804*4882a593Smuzhiyun }
1805*4882a593Smuzhiyun rate->param.rate_cfg.rate = tx_rate_config.rate;
1806*4882a593Smuzhiyun }
1807*4882a593Smuzhiyun
1808*4882a593Smuzhiyun /* nss sanity check */
1809*4882a593Smuzhiyun if ((tx_rate_config.rate_format == 2) ||
1810*4882a593Smuzhiyun (tx_rate_config.rate_format == 3)) {
1811*4882a593Smuzhiyun if ((tx_rate_config.nss < 1) ||
1812*4882a593Smuzhiyun (tx_rate_config.nss > 2)) {
1813*4882a593Smuzhiyun PRINTM(MERROR,
1814*4882a593Smuzhiyun "Invalid nss selection %d\n",
1815*4882a593Smuzhiyun tx_rate_config.nss);
1816*4882a593Smuzhiyun ret = -EINVAL;
1817*4882a593Smuzhiyun goto done;
1818*4882a593Smuzhiyun }
1819*4882a593Smuzhiyun rate->param.rate_cfg.nss = tx_rate_config.nss;
1820*4882a593Smuzhiyun }
1821*4882a593Smuzhiyun if (tx_rate_config.user_data_cnt <= 3)
1822*4882a593Smuzhiyun rate->param.rate_cfg.rate_setting = 0xffff;
1823*4882a593Smuzhiyun else
1824*4882a593Smuzhiyun rate->param.rate_cfg.rate_setting =
1825*4882a593Smuzhiyun tx_rate_config.rate_setting;
1826*4882a593Smuzhiyun }
1827*4882a593Smuzhiyun }
1828*4882a593Smuzhiyun
1829*4882a593Smuzhiyun status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
1830*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
1831*4882a593Smuzhiyun ret = -EFAULT;
1832*4882a593Smuzhiyun goto done;
1833*4882a593Smuzhiyun }
1834*4882a593Smuzhiyun if (tx_rate_config.action) {
1835*4882a593Smuzhiyun priv->rate_index = tx_rate_config.action;
1836*4882a593Smuzhiyun } else {
1837*4882a593Smuzhiyun if (rate->param.rate_cfg.is_rate_auto)
1838*4882a593Smuzhiyun tx_rate_config.rate_format = AUTO_RATE;
1839*4882a593Smuzhiyun else {
1840*4882a593Smuzhiyun /* fixed rate */
1841*4882a593Smuzhiyun tx_rate_config.rate_format =
1842*4882a593Smuzhiyun rate->param.rate_cfg.rate_format;
1843*4882a593Smuzhiyun tx_rate_config.rate = rate->param.rate_cfg.rate;
1844*4882a593Smuzhiyun if (rate->param.rate_cfg.rate_format ==
1845*4882a593Smuzhiyun MLAN_RATE_FORMAT_VHT ||
1846*4882a593Smuzhiyun rate->param.rate_cfg.rate_format ==
1847*4882a593Smuzhiyun MLAN_RATE_FORMAT_HE)
1848*4882a593Smuzhiyun tx_rate_config.nss = rate->param.rate_cfg.nss;
1849*4882a593Smuzhiyun tx_rate_config.rate_setting =
1850*4882a593Smuzhiyun rate->param.rate_cfg.rate_setting;
1851*4882a593Smuzhiyun }
1852*4882a593Smuzhiyun for (i = 0; i < MAX_BITMAP_RATES_SIZE; i++) {
1853*4882a593Smuzhiyun tx_rate_config.bitmap_rates[i] =
1854*4882a593Smuzhiyun rate->param.rate_cfg.bitmap_rates[i];
1855*4882a593Smuzhiyun }
1856*4882a593Smuzhiyun
1857*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, &tx_rate_config,
1858*4882a593Smuzhiyun sizeof(tx_rate_cfg_t))) {
1859*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed\n");
1860*4882a593Smuzhiyun ret = -EFAULT;
1861*4882a593Smuzhiyun }
1862*4882a593Smuzhiyun }
1863*4882a593Smuzhiyun done:
1864*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
1865*4882a593Smuzhiyun kfree(mreq);
1866*4882a593Smuzhiyun LEAVE();
1867*4882a593Smuzhiyun return ret;
1868*4882a593Smuzhiyun }
1869*4882a593Smuzhiyun
1870*4882a593Smuzhiyun /**
1871*4882a593Smuzhiyun * @brief Set/Get RF antenna mode
1872*4882a593Smuzhiyun *
1873*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1874*4882a593Smuzhiyun * @param req A pointer to ifreq structure
1875*4882a593Smuzhiyun *
1876*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1877*4882a593Smuzhiyun */
woal_uap_antenna_cfg(struct net_device * dev,struct ifreq * req)1878*4882a593Smuzhiyun static int woal_uap_antenna_cfg(struct net_device *dev, struct ifreq *req)
1879*4882a593Smuzhiyun {
1880*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1881*4882a593Smuzhiyun int ret = 0;
1882*4882a593Smuzhiyun mlan_ds_radio_cfg *radio = NULL;
1883*4882a593Smuzhiyun mlan_ioctl_req *mreq = NULL;
1884*4882a593Smuzhiyun ant_cfg_t antenna_config;
1885*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
1886*4882a593Smuzhiyun
1887*4882a593Smuzhiyun ENTER();
1888*4882a593Smuzhiyun
1889*4882a593Smuzhiyun /* Sanity check */
1890*4882a593Smuzhiyun if (req->ifr_data == NULL) {
1891*4882a593Smuzhiyun PRINTM(MERROR, "uap_antenna_cfg() corrupt data\n");
1892*4882a593Smuzhiyun ret = -EFAULT;
1893*4882a593Smuzhiyun goto done;
1894*4882a593Smuzhiyun }
1895*4882a593Smuzhiyun
1896*4882a593Smuzhiyun memset(&antenna_config, 0, sizeof(ant_cfg_t));
1897*4882a593Smuzhiyun /* Get user data */
1898*4882a593Smuzhiyun if (copy_from_user(&antenna_config, req->ifr_data, sizeof(ant_cfg_t))) {
1899*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
1900*4882a593Smuzhiyun ret = -EFAULT;
1901*4882a593Smuzhiyun goto done;
1902*4882a593Smuzhiyun }
1903*4882a593Smuzhiyun mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
1904*4882a593Smuzhiyun if (mreq == NULL) {
1905*4882a593Smuzhiyun ret = -ENOMEM;
1906*4882a593Smuzhiyun goto done;
1907*4882a593Smuzhiyun }
1908*4882a593Smuzhiyun radio = (mlan_ds_radio_cfg *)mreq->pbuf;
1909*4882a593Smuzhiyun radio->sub_command = MLAN_OID_ANT_CFG;
1910*4882a593Smuzhiyun mreq->req_id = MLAN_IOCTL_RADIO_CFG;
1911*4882a593Smuzhiyun if (!(antenna_config.action))
1912*4882a593Smuzhiyun mreq->action = MLAN_ACT_GET;
1913*4882a593Smuzhiyun else {
1914*4882a593Smuzhiyun mreq->action = MLAN_ACT_SET;
1915*4882a593Smuzhiyun radio->param.ant_cfg.tx_antenna = antenna_config.tx_mode;
1916*4882a593Smuzhiyun radio->param.ant_cfg.rx_antenna = antenna_config.rx_mode;
1917*4882a593Smuzhiyun #if defined(STA_CFG80211) || defined(UAP_CFG80211)
1918*4882a593Smuzhiyun if (IS_CARD9098(priv->phandle->card_type) ||
1919*4882a593Smuzhiyun IS_CARD9097(priv->phandle->card_type)) {
1920*4882a593Smuzhiyun if (IS_STA_CFG80211(
1921*4882a593Smuzhiyun priv->phandle->params.cfg80211_wext))
1922*4882a593Smuzhiyun woal_cfg80211_notify_antcfg(
1923*4882a593Smuzhiyun priv, priv->phandle->wiphy, radio);
1924*4882a593Smuzhiyun }
1925*4882a593Smuzhiyun #endif
1926*4882a593Smuzhiyun }
1927*4882a593Smuzhiyun
1928*4882a593Smuzhiyun status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
1929*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
1930*4882a593Smuzhiyun ret = -EFAULT;
1931*4882a593Smuzhiyun goto done;
1932*4882a593Smuzhiyun }
1933*4882a593Smuzhiyun if (mreq->action == MLAN_ACT_GET) {
1934*4882a593Smuzhiyun antenna_config.tx_mode = radio->param.ant_cfg.tx_antenna;
1935*4882a593Smuzhiyun antenna_config.rx_mode = radio->param.ant_cfg.rx_antenna;
1936*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, &antenna_config,
1937*4882a593Smuzhiyun sizeof(ant_cfg_t))) {
1938*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed\n");
1939*4882a593Smuzhiyun ret = -EFAULT;
1940*4882a593Smuzhiyun }
1941*4882a593Smuzhiyun }
1942*4882a593Smuzhiyun done:
1943*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
1944*4882a593Smuzhiyun kfree(mreq);
1945*4882a593Smuzhiyun LEAVE();
1946*4882a593Smuzhiyun return ret;
1947*4882a593Smuzhiyun }
1948*4882a593Smuzhiyun
1949*4882a593Smuzhiyun /**
1950*4882a593Smuzhiyun * @brief Set/Get HT stream configurations
1951*4882a593Smuzhiyun *
1952*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1953*4882a593Smuzhiyun * @param req A pointer to ifreq structure
1954*4882a593Smuzhiyun *
1955*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1956*4882a593Smuzhiyun */
woal_uap_htstream_cfg(struct net_device * dev,struct ifreq * req)1957*4882a593Smuzhiyun static int woal_uap_htstream_cfg(struct net_device *dev, struct ifreq *req)
1958*4882a593Smuzhiyun {
1959*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1960*4882a593Smuzhiyun int ret = 0;
1961*4882a593Smuzhiyun mlan_ds_11n_cfg *cfg = NULL;
1962*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
1963*4882a593Smuzhiyun htstream_cfg_t htstream_cfg;
1964*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
1965*4882a593Smuzhiyun
1966*4882a593Smuzhiyun ENTER();
1967*4882a593Smuzhiyun
1968*4882a593Smuzhiyun memset(&htstream_cfg, 0, sizeof(htstream_cfg_t));
1969*4882a593Smuzhiyun
1970*4882a593Smuzhiyun /* Sanity check */
1971*4882a593Smuzhiyun if (req->ifr_data == NULL) {
1972*4882a593Smuzhiyun PRINTM(MERROR, "woal_uap_htstream_cfg corrupt data\n");
1973*4882a593Smuzhiyun ret = -EFAULT;
1974*4882a593Smuzhiyun goto done;
1975*4882a593Smuzhiyun }
1976*4882a593Smuzhiyun if (copy_from_user(&htstream_cfg, req->ifr_data,
1977*4882a593Smuzhiyun sizeof(htstream_cfg_t))) {
1978*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
1979*4882a593Smuzhiyun ret = -EFAULT;
1980*4882a593Smuzhiyun goto done;
1981*4882a593Smuzhiyun }
1982*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
1983*4882a593Smuzhiyun if (ioctl_req == NULL) {
1984*4882a593Smuzhiyun ret = -ENOMEM;
1985*4882a593Smuzhiyun goto done;
1986*4882a593Smuzhiyun }
1987*4882a593Smuzhiyun cfg = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
1988*4882a593Smuzhiyun cfg->sub_command = MLAN_OID_11N_CFG_STREAM_CFG;
1989*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
1990*4882a593Smuzhiyun
1991*4882a593Smuzhiyun if (!htstream_cfg.action) {
1992*4882a593Smuzhiyun /* Get operation */
1993*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_GET;
1994*4882a593Smuzhiyun } else {
1995*4882a593Smuzhiyun /* Update HT stream parameter in MLAN */
1996*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
1997*4882a593Smuzhiyun /* Set HT Stream configuration */
1998*4882a593Smuzhiyun cfg->param.stream_cfg = htstream_cfg.stream_cfg;
1999*4882a593Smuzhiyun PRINTM(MINFO, "SET: htstream_cfg:0x%x\n",
2000*4882a593Smuzhiyun cfg->param.stream_cfg);
2001*4882a593Smuzhiyun }
2002*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2003*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
2004*4882a593Smuzhiyun ret = -EFAULT;
2005*4882a593Smuzhiyun goto done;
2006*4882a593Smuzhiyun }
2007*4882a593Smuzhiyun /* Copy to user */
2008*4882a593Smuzhiyun if (ioctl_req->action == MLAN_ACT_GET) {
2009*4882a593Smuzhiyun PRINTM(MINFO, "GET: htstream_cfg:0x%x\n",
2010*4882a593Smuzhiyun htstream_cfg.stream_cfg);
2011*4882a593Smuzhiyun htstream_cfg.stream_cfg = cfg->param.stream_cfg;
2012*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, &htstream_cfg,
2013*4882a593Smuzhiyun sizeof(htstream_cfg_t))) {
2014*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
2015*4882a593Smuzhiyun ret = -EFAULT;
2016*4882a593Smuzhiyun goto done;
2017*4882a593Smuzhiyun }
2018*4882a593Smuzhiyun }
2019*4882a593Smuzhiyun done:
2020*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
2021*4882a593Smuzhiyun kfree(ioctl_req);
2022*4882a593Smuzhiyun LEAVE();
2023*4882a593Smuzhiyun return ret;
2024*4882a593Smuzhiyun }
2025*4882a593Smuzhiyun
2026*4882a593Smuzhiyun /**
2027*4882a593Smuzhiyun * @brief Get DFS_REPEATER mode
2028*4882a593Smuzhiyun *
2029*4882a593Smuzhiyun * @param dev A pointer to net_device structure
2030*4882a593Smuzhiyun * @param req A pointer to ifreq structure
2031*4882a593Smuzhiyun *
2032*4882a593Smuzhiyun * @return 0 --success, otherwise fail
2033*4882a593Smuzhiyun */
woal_uap_dfs_repeater(struct net_device * dev,struct ifreq * req)2034*4882a593Smuzhiyun static int woal_uap_dfs_repeater(struct net_device *dev, struct ifreq *req)
2035*4882a593Smuzhiyun {
2036*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
2037*4882a593Smuzhiyun int ret = 0;
2038*4882a593Smuzhiyun dfs_repeater_mode param;
2039*4882a593Smuzhiyun mlan_ds_misc_cfg *misc = NULL;
2040*4882a593Smuzhiyun mlan_ioctl_req *mreq = NULL;
2041*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
2042*4882a593Smuzhiyun
2043*4882a593Smuzhiyun ENTER();
2044*4882a593Smuzhiyun
2045*4882a593Smuzhiyun /* Sanity check */
2046*4882a593Smuzhiyun if (req->ifr_data == NULL) {
2047*4882a593Smuzhiyun PRINTM(MERROR, "uap_antenna_cfg() corrupt data\n");
2048*4882a593Smuzhiyun ret = -EFAULT;
2049*4882a593Smuzhiyun goto done;
2050*4882a593Smuzhiyun }
2051*4882a593Smuzhiyun
2052*4882a593Smuzhiyun memset(¶m, 0, sizeof(dfs_repeater_mode));
2053*4882a593Smuzhiyun /* Get user data */
2054*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(dfs_repeater_mode))) {
2055*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
2056*4882a593Smuzhiyun ret = -EFAULT;
2057*4882a593Smuzhiyun goto done;
2058*4882a593Smuzhiyun }
2059*4882a593Smuzhiyun mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2060*4882a593Smuzhiyun if (mreq == NULL) {
2061*4882a593Smuzhiyun ret = -ENOMEM;
2062*4882a593Smuzhiyun goto done;
2063*4882a593Smuzhiyun }
2064*4882a593Smuzhiyun misc = (mlan_ds_misc_cfg *)mreq->pbuf;
2065*4882a593Smuzhiyun misc->sub_command = MLAN_OID_MISC_DFS_REAPTER_MODE;
2066*4882a593Smuzhiyun mreq->req_id = MLAN_IOCTL_MISC_CFG;
2067*4882a593Smuzhiyun mreq->action = MLAN_ACT_GET;
2068*4882a593Smuzhiyun
2069*4882a593Smuzhiyun status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
2070*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
2071*4882a593Smuzhiyun ret = -EFAULT;
2072*4882a593Smuzhiyun goto done;
2073*4882a593Smuzhiyun }
2074*4882a593Smuzhiyun param.mode = misc->param.dfs_repeater.mode;
2075*4882a593Smuzhiyun
2076*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, ¶m, sizeof(dfs_repeater_mode))) {
2077*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed\n");
2078*4882a593Smuzhiyun ret = -EFAULT;
2079*4882a593Smuzhiyun }
2080*4882a593Smuzhiyun done:
2081*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
2082*4882a593Smuzhiyun kfree(mreq);
2083*4882a593Smuzhiyun LEAVE();
2084*4882a593Smuzhiyun return ret;
2085*4882a593Smuzhiyun }
2086*4882a593Smuzhiyun
2087*4882a593Smuzhiyun /**
2088*4882a593Smuzhiyun * @brief Issue MLAN_OID_11H_CHAN_REPORT_REQUEST ioctl to cancel dozer
2089*4882a593Smuzhiyun *
2090*4882a593Smuzhiyun * @param priv Pointer to the moal_private driver data struct
2091*4882a593Smuzhiyun * @param action MLAN_ACT_SET/MLAN_ACT_GET
2092*4882a593Smuzhiyun * @param
2093*4882a593Smuzhiyun *
2094*4882a593Smuzhiyun * @return 0 --success, otherwise fail
2095*4882a593Smuzhiyun */
woal_11h_chan_dfs_state(moal_private * priv,t_u8 action,mlan_ds_11h_chan_dfs_state * ch_dfs_state)2096*4882a593Smuzhiyun int woal_11h_chan_dfs_state(moal_private *priv, t_u8 action,
2097*4882a593Smuzhiyun mlan_ds_11h_chan_dfs_state *ch_dfs_state)
2098*4882a593Smuzhiyun {
2099*4882a593Smuzhiyun int ret = 0;
2100*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
2101*4882a593Smuzhiyun mlan_ds_11h_cfg *ds_11hcfg = NULL;
2102*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
2103*4882a593Smuzhiyun #ifdef UAP_CFG80211
2104*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2105*4882a593Smuzhiyun int cfg80211_wext = priv->phandle->params.cfg80211_wext;
2106*4882a593Smuzhiyun #endif
2107*4882a593Smuzhiyun #endif
2108*4882a593Smuzhiyun
2109*4882a593Smuzhiyun ENTER();
2110*4882a593Smuzhiyun #ifdef UAP_CFG80211
2111*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2112*4882a593Smuzhiyun if (action == MLAN_ACT_GET) {
2113*4882a593Smuzhiyun if (IS_UAP_CFG80211(cfg80211_wext)) {
2114*4882a593Smuzhiyun ret = woal_get_wiphy_chan_dfs_state(
2115*4882a593Smuzhiyun priv->phandle->wiphy, ch_dfs_state);
2116*4882a593Smuzhiyun if (!ret) {
2117*4882a593Smuzhiyun LEAVE();
2118*4882a593Smuzhiyun return ret;
2119*4882a593Smuzhiyun }
2120*4882a593Smuzhiyun }
2121*4882a593Smuzhiyun }
2122*4882a593Smuzhiyun #endif
2123*4882a593Smuzhiyun #endif
2124*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
2125*4882a593Smuzhiyun if (req == NULL) {
2126*4882a593Smuzhiyun ret = -ENOMEM;
2127*4882a593Smuzhiyun goto done;
2128*4882a593Smuzhiyun }
2129*4882a593Smuzhiyun ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
2130*4882a593Smuzhiyun
2131*4882a593Smuzhiyun ds_11hcfg->sub_command = MLAN_OID_11H_CHAN_DFS_STATE;
2132*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_11H_CFG;
2133*4882a593Smuzhiyun req->action = action;
2134*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &ds_11hcfg->param.ch_dfs_state,
2135*4882a593Smuzhiyun ch_dfs_state, sizeof(mlan_ds_11h_chan_dfs_state),
2136*4882a593Smuzhiyun sizeof(ds_11hcfg->param.ch_dfs_state));
2137*4882a593Smuzhiyun /* Send Channel Check command and wait until the report is ready */
2138*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2139*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
2140*4882a593Smuzhiyun ret = -EFAULT;
2141*4882a593Smuzhiyun goto done;
2142*4882a593Smuzhiyun }
2143*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, ch_dfs_state,
2144*4882a593Smuzhiyun &ds_11hcfg->param.ch_dfs_state,
2145*4882a593Smuzhiyun sizeof(mlan_ds_11h_chan_dfs_state),
2146*4882a593Smuzhiyun sizeof(mlan_ds_11h_chan_dfs_state));
2147*4882a593Smuzhiyun done:
2148*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
2149*4882a593Smuzhiyun kfree(req);
2150*4882a593Smuzhiyun LEAVE();
2151*4882a593Smuzhiyun return ret;
2152*4882a593Smuzhiyun }
2153*4882a593Smuzhiyun
2154*4882a593Smuzhiyun /**
2155*4882a593Smuzhiyun * @brief find all bonded channel.
2156*4882a593Smuzhiyun *
2157*4882a593Smuzhiyun * @param pri_chan primary channel
2158*4882a593Smuzhiyun * @param bw channel bandwidth
2159*4882a593Smuzhiyun * @param ch_dfs_state a pointer to mlan_ds_11h_chan_dfs_state array
2160*4882a593Smuzhiyun *
2161*4882a593Smuzhiyun * @return number of channel
2162*4882a593Smuzhiyun */
woal_uap_get_dfs_chan(t_u8 pri_chan,t_u8 bw,mlan_ds_11h_chan_dfs_state * ch_dfs_state)2163*4882a593Smuzhiyun static int woal_uap_get_dfs_chan(t_u8 pri_chan, t_u8 bw,
2164*4882a593Smuzhiyun mlan_ds_11h_chan_dfs_state *ch_dfs_state)
2165*4882a593Smuzhiyun {
2166*4882a593Smuzhiyun int ht40_plus[] = {52, 60, 100, 108, 116, 124, 132, 140};
2167*4882a593Smuzhiyun int ht40_minus[] = {56, 64, 104, 112, 120, 128, 136, 144};
2168*4882a593Smuzhiyun int vht80_dfs[4][4] = {{52, 56, 60, 64},
2169*4882a593Smuzhiyun {100, 104, 108, 112},
2170*4882a593Smuzhiyun {116, 120, 124, 128},
2171*4882a593Smuzhiyun {132, 136, 140, 144}};
2172*4882a593Smuzhiyun t_u8 find = false;
2173*4882a593Smuzhiyun int i, j;
2174*4882a593Smuzhiyun t_u8 sec_chan = 0;
2175*4882a593Smuzhiyun mlan_ds_11h_chan_dfs_state *pos = ch_dfs_state;
2176*4882a593Smuzhiyun t_u8 n_chan = 1;
2177*4882a593Smuzhiyun
2178*4882a593Smuzhiyun if (bw == CHAN_BW_20MHZ) {
2179*4882a593Smuzhiyun pos->channel = pri_chan;
2180*4882a593Smuzhiyun } else if (bw == CHAN_BW_40MHZ) {
2181*4882a593Smuzhiyun pos->channel = pri_chan;
2182*4882a593Smuzhiyun pos++;
2183*4882a593Smuzhiyun for (i = 0; i < (sizeof(ht40_minus) / sizeof(int)); i++) {
2184*4882a593Smuzhiyun if (pri_chan == (t_u8)ht40_plus[i]) {
2185*4882a593Smuzhiyun sec_chan = pri_chan + 4;
2186*4882a593Smuzhiyun n_chan = 2;
2187*4882a593Smuzhiyun break;
2188*4882a593Smuzhiyun }
2189*4882a593Smuzhiyun }
2190*4882a593Smuzhiyun for (i = 0; i < (sizeof(ht40_minus) / sizeof(int)); i++) {
2191*4882a593Smuzhiyun if (pri_chan == (t_u8)ht40_minus[i]) {
2192*4882a593Smuzhiyun sec_chan = pri_chan - 4;
2193*4882a593Smuzhiyun n_chan = 2;
2194*4882a593Smuzhiyun break;
2195*4882a593Smuzhiyun }
2196*4882a593Smuzhiyun }
2197*4882a593Smuzhiyun pos->channel = sec_chan;
2198*4882a593Smuzhiyun } else if (bw == CHAN_BW_80MHZ) {
2199*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
2200*4882a593Smuzhiyun for (j = 0; j < 4; j++) {
2201*4882a593Smuzhiyun if (pri_chan == (t_u8)vht80_dfs[i][j]) {
2202*4882a593Smuzhiyun find = true;
2203*4882a593Smuzhiyun break;
2204*4882a593Smuzhiyun }
2205*4882a593Smuzhiyun }
2206*4882a593Smuzhiyun if (find)
2207*4882a593Smuzhiyun break;
2208*4882a593Smuzhiyun }
2209*4882a593Smuzhiyun if (find) {
2210*4882a593Smuzhiyun n_chan = 4;
2211*4882a593Smuzhiyun for (j = 0; j < n_chan; j++) {
2212*4882a593Smuzhiyun pos->channel = (t_u8)vht80_dfs[i][j];
2213*4882a593Smuzhiyun pos++;
2214*4882a593Smuzhiyun }
2215*4882a593Smuzhiyun }
2216*4882a593Smuzhiyun }
2217*4882a593Smuzhiyun return n_chan;
2218*4882a593Smuzhiyun }
2219*4882a593Smuzhiyun
2220*4882a593Smuzhiyun #ifdef UAP_CFG80211
2221*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2222*4882a593Smuzhiyun /**
2223*4882a593Smuzhiyun * @brief update channel dfs state to all wiphy
2224*4882a593Smuzhiyun *
2225*4882a593Smuzhiyun * @param channel given radar channel
2226*4882a593Smuzhiyun * @param bandwidth channel's bandwidth
2227*4882a593Smuzhiyun * @param dfs_state dfs_state
2228*4882a593Smuzhiyun *
2229*4882a593Smuzhiyun * @return N/A
2230*4882a593Smuzhiyun */
woal_update_channels_dfs_state(moal_private * priv,t_u8 channel,t_u8 bandwidth,t_u8 dfs_state)2231*4882a593Smuzhiyun void woal_update_channels_dfs_state(moal_private *priv, t_u8 channel,
2232*4882a593Smuzhiyun t_u8 bandwidth, t_u8 dfs_state)
2233*4882a593Smuzhiyun {
2234*4882a593Smuzhiyun mlan_ds_11h_chan_dfs_state ch_dfs_state[4];
2235*4882a593Smuzhiyun int cfg80211_wext = priv->phandle->params.cfg80211_wext;
2236*4882a593Smuzhiyun t_u8 n_chan;
2237*4882a593Smuzhiyun int i;
2238*4882a593Smuzhiyun ENTER();
2239*4882a593Smuzhiyun memset(ch_dfs_state, 0, sizeof(ch_dfs_state));
2240*4882a593Smuzhiyun n_chan = woal_uap_get_dfs_chan(channel, bandwidth, &ch_dfs_state[0]);
2241*4882a593Smuzhiyun if (IS_UAP_CFG80211(cfg80211_wext)) {
2242*4882a593Smuzhiyun for (i = 0; i < n_chan; i++) {
2243*4882a593Smuzhiyun woal_update_channel_dfs_state(ch_dfs_state[i].channel,
2244*4882a593Smuzhiyun dfs_state);
2245*4882a593Smuzhiyun }
2246*4882a593Smuzhiyun }
2247*4882a593Smuzhiyun LEAVE();
2248*4882a593Smuzhiyun return;
2249*4882a593Smuzhiyun }
2250*4882a593Smuzhiyun #endif
2251*4882a593Smuzhiyun #endif
2252*4882a593Smuzhiyun
2253*4882a593Smuzhiyun /**
2254*4882a593Smuzhiyun * @brief skip cac on specific channel
2255*4882a593Smuzhiyun * @and Wext
2256*4882a593Smuzhiyun *
2257*4882a593Smuzhiyun * @param dev A pointer to net_device structure
2258*4882a593Smuzhiyun * @param req A pointer to ifreq structure
2259*4882a593Smuzhiyun *
2260*4882a593Smuzhiyun * @return 0 --success, otherwise fail
2261*4882a593Smuzhiyun */
woal_uap_skip_cac(struct net_device * dev,struct ifreq * req)2262*4882a593Smuzhiyun static int woal_uap_skip_cac(struct net_device *dev, struct ifreq *req)
2263*4882a593Smuzhiyun {
2264*4882a593Smuzhiyun int ret = 0;
2265*4882a593Smuzhiyun skip_cac_para param;
2266*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
2267*4882a593Smuzhiyun #ifdef UAP_CFG80211
2268*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2269*4882a593Smuzhiyun int cfg80211_wext = priv->phandle->params.cfg80211_wext;
2270*4882a593Smuzhiyun #endif
2271*4882a593Smuzhiyun #endif
2272*4882a593Smuzhiyun dfs_state_t dfs_state;
2273*4882a593Smuzhiyun mlan_ds_11h_chan_dfs_state ch_dfs_state[4];
2274*4882a593Smuzhiyun t_u8 n_chan;
2275*4882a593Smuzhiyun int i = 0;
2276*4882a593Smuzhiyun ENTER();
2277*4882a593Smuzhiyun
2278*4882a593Smuzhiyun /* Sanity check */
2279*4882a593Smuzhiyun if (req->ifr_data == NULL) {
2280*4882a593Smuzhiyun PRINTM(MERROR, "skip_dfs_cac() corrupt data\n");
2281*4882a593Smuzhiyun ret = -EFAULT;
2282*4882a593Smuzhiyun goto done;
2283*4882a593Smuzhiyun }
2284*4882a593Smuzhiyun memset(¶m, 0, sizeof(skip_cac_para));
2285*4882a593Smuzhiyun /* Get user data */
2286*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(skip_cac_para))) {
2287*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
2288*4882a593Smuzhiyun ret = -EFAULT;
2289*4882a593Smuzhiyun goto done;
2290*4882a593Smuzhiyun }
2291*4882a593Smuzhiyun if (param.skip_cac)
2292*4882a593Smuzhiyun dfs_state = DFS_AVAILABLE;
2293*4882a593Smuzhiyun else
2294*4882a593Smuzhiyun dfs_state = DFS_USABLE;
2295*4882a593Smuzhiyun memset(&ch_dfs_state, 0, sizeof(ch_dfs_state));
2296*4882a593Smuzhiyun n_chan = woal_uap_get_dfs_chan(param.channel, param.bw,
2297*4882a593Smuzhiyun &ch_dfs_state[0]);
2298*4882a593Smuzhiyun for (i = 0; i < n_chan; i++) {
2299*4882a593Smuzhiyun if (woal_11h_chan_dfs_state(priv, MLAN_ACT_GET,
2300*4882a593Smuzhiyun &ch_dfs_state[i]))
2301*4882a593Smuzhiyun PRINTM(MERROR, "Get DFS state for chan:%d failed\n",
2302*4882a593Smuzhiyun ch_dfs_state[i].channel);
2303*4882a593Smuzhiyun }
2304*4882a593Smuzhiyun for (i = 0; i < n_chan; i++) {
2305*4882a593Smuzhiyun if (param.skip_cac && ch_dfs_state[i].dfs_state == DFS_USABLE)
2306*4882a593Smuzhiyun PRINTM(MMSG,
2307*4882a593Smuzhiyun "DFS: Requst skip cac on the channel %d which hasn't do CAC before!\n",
2308*4882a593Smuzhiyun ch_dfs_state[i].channel);
2309*4882a593Smuzhiyun ch_dfs_state[i].dfs_state = dfs_state;
2310*4882a593Smuzhiyun if (woal_11h_chan_dfs_state(priv, MLAN_ACT_SET,
2311*4882a593Smuzhiyun &ch_dfs_state[i]))
2312*4882a593Smuzhiyun PRINTM(MERROR, "Set DFS state for chan:%d failed\n",
2313*4882a593Smuzhiyun ch_dfs_state[i].channel);
2314*4882a593Smuzhiyun else
2315*4882a593Smuzhiyun PRINTM(MCMND, "DFS: Skip CAC on chan %d %d\n",
2316*4882a593Smuzhiyun ch_dfs_state[i].channel, param.skip_cac);
2317*4882a593Smuzhiyun }
2318*4882a593Smuzhiyun #ifdef UAP_CFG80211
2319*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2320*4882a593Smuzhiyun if (IS_UAP_CFG80211(cfg80211_wext)) {
2321*4882a593Smuzhiyun for (i = 0; i < n_chan; i++) {
2322*4882a593Smuzhiyun if (param.skip_cac)
2323*4882a593Smuzhiyun woal_update_channel_dfs_state(
2324*4882a593Smuzhiyun ch_dfs_state[i].channel, DFS_AVAILABLE);
2325*4882a593Smuzhiyun else
2326*4882a593Smuzhiyun woal_update_channel_dfs_state(
2327*4882a593Smuzhiyun ch_dfs_state[i].channel, DFS_USABLE);
2328*4882a593Smuzhiyun }
2329*4882a593Smuzhiyun }
2330*4882a593Smuzhiyun #endif
2331*4882a593Smuzhiyun #endif
2332*4882a593Smuzhiyun done:
2333*4882a593Smuzhiyun LEAVE();
2334*4882a593Smuzhiyun return ret;
2335*4882a593Smuzhiyun }
2336*4882a593Smuzhiyun
2337*4882a593Smuzhiyun /**
2338*4882a593Smuzhiyun * @brief Get DFS_REPEATER mode
2339*4882a593Smuzhiyun *
2340*4882a593Smuzhiyun * @param dev A pointer to net_device structure
2341*4882a593Smuzhiyun * @param req A pointer to ifreq structure
2342*4882a593Smuzhiyun *
2343*4882a593Smuzhiyun * @return 0 --success, otherwise fail
2344*4882a593Smuzhiyun */
woal_uap_cac_timer_status(struct net_device * dev,struct ifreq * req)2345*4882a593Smuzhiyun static int woal_uap_cac_timer_status(struct net_device *dev, struct ifreq *req)
2346*4882a593Smuzhiyun {
2347*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
2348*4882a593Smuzhiyun int ret = 0;
2349*4882a593Smuzhiyun cac_timer_status param;
2350*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
2351*4882a593Smuzhiyun
2352*4882a593Smuzhiyun ENTER();
2353*4882a593Smuzhiyun
2354*4882a593Smuzhiyun /* Sanity check */
2355*4882a593Smuzhiyun if (req->ifr_data == NULL) {
2356*4882a593Smuzhiyun PRINTM(MERROR, "uap_antenna_cfg() corrupt data\n");
2357*4882a593Smuzhiyun ret = -EFAULT;
2358*4882a593Smuzhiyun goto done;
2359*4882a593Smuzhiyun }
2360*4882a593Smuzhiyun
2361*4882a593Smuzhiyun memset(¶m, 0, sizeof(cac_timer_status));
2362*4882a593Smuzhiyun
2363*4882a593Smuzhiyun /* Get user data */
2364*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(cac_timer_status))) {
2365*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
2366*4882a593Smuzhiyun ret = -EFAULT;
2367*4882a593Smuzhiyun goto done;
2368*4882a593Smuzhiyun }
2369*4882a593Smuzhiyun
2370*4882a593Smuzhiyun /* Currently default action is get */
2371*4882a593Smuzhiyun param.mode = 0;
2372*4882a593Smuzhiyun
2373*4882a593Smuzhiyun if (priv->phandle->cac_period == MTRUE) {
2374*4882a593Smuzhiyun long cac_left_jiffies;
2375*4882a593Smuzhiyun
2376*4882a593Smuzhiyun cac_left_jiffies =
2377*4882a593Smuzhiyun MEAS_REPORT_TIME -
2378*4882a593Smuzhiyun (jiffies - priv->phandle->meas_start_jiffies);
2379*4882a593Smuzhiyun
2380*4882a593Smuzhiyun /* cac_left_jiffies would be negative if timer has already
2381*4882a593Smuzhiyun * elapsed. positive if timer is still yet to lapsed
2382*4882a593Smuzhiyun */
2383*4882a593Smuzhiyun if (cac_left_jiffies > 0)
2384*4882a593Smuzhiyun param.mode = (t_u32)cac_left_jiffies / HZ;
2385*4882a593Smuzhiyun }
2386*4882a593Smuzhiyun
2387*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, ¶m, sizeof(cac_timer_status))) {
2388*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed\n");
2389*4882a593Smuzhiyun ret = -EFAULT;
2390*4882a593Smuzhiyun }
2391*4882a593Smuzhiyun done:
2392*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
2393*4882a593Smuzhiyun LEAVE();
2394*4882a593Smuzhiyun return ret;
2395*4882a593Smuzhiyun }
2396*4882a593Smuzhiyun
2397*4882a593Smuzhiyun /**
2398*4882a593Smuzhiyun * @brief set/get uap operation control
2399*4882a593Smuzhiyun *
2400*4882a593Smuzhiyun * @param dev A pointer to net_device structure
2401*4882a593Smuzhiyun * @param req A pointer to ifreq structure
2402*4882a593Smuzhiyun *
2403*4882a593Smuzhiyun * @return 0 --success, otherwise fail
2404*4882a593Smuzhiyun */
woal_uap_operation_ctrl(struct net_device * dev,struct ifreq * req)2405*4882a593Smuzhiyun static int woal_uap_operation_ctrl(struct net_device *dev, struct ifreq *req)
2406*4882a593Smuzhiyun {
2407*4882a593Smuzhiyun int ret = 0;
2408*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
2409*4882a593Smuzhiyun mlan_uap_oper_ctrl uap_oper;
2410*4882a593Smuzhiyun uap_oper_para_hdr param;
2411*4882a593Smuzhiyun mlan_ds_bss *bss = NULL;
2412*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
2413*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
2414*4882a593Smuzhiyun
2415*4882a593Smuzhiyun ENTER();
2416*4882a593Smuzhiyun
2417*4882a593Smuzhiyun memset(¶m, 0, sizeof(uap_oper_para_hdr));
2418*4882a593Smuzhiyun memset(&uap_oper, 0, sizeof(mlan_uap_oper_ctrl));
2419*4882a593Smuzhiyun
2420*4882a593Smuzhiyun /* Sanity check */
2421*4882a593Smuzhiyun if (req->ifr_data == NULL) {
2422*4882a593Smuzhiyun PRINTM(MERROR, "woal_uap_operation_ctrl corrupt data\n");
2423*4882a593Smuzhiyun ret = -EFAULT;
2424*4882a593Smuzhiyun goto done;
2425*4882a593Smuzhiyun }
2426*4882a593Smuzhiyun if (copy_from_user(¶m, req->ifr_data, sizeof(uap_oper_para_hdr))) {
2427*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
2428*4882a593Smuzhiyun ret = -EFAULT;
2429*4882a593Smuzhiyun goto done;
2430*4882a593Smuzhiyun }
2431*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
2432*4882a593Smuzhiyun if (ioctl_req == NULL) {
2433*4882a593Smuzhiyun ret = MLAN_STATUS_FAILURE;
2434*4882a593Smuzhiyun goto done;
2435*4882a593Smuzhiyun }
2436*4882a593Smuzhiyun
2437*4882a593Smuzhiyun bss = (mlan_ds_bss *)ioctl_req->pbuf;
2438*4882a593Smuzhiyun bss->sub_command = MLAN_OID_UAP_OPER_CTRL;
2439*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_BSS;
2440*4882a593Smuzhiyun if (copy_from_user(&uap_oper, req->ifr_data + sizeof(uap_oper_para_hdr),
2441*4882a593Smuzhiyun sizeof(mlan_uap_oper_ctrl))) {
2442*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
2443*4882a593Smuzhiyun ret = -EFAULT;
2444*4882a593Smuzhiyun goto done;
2445*4882a593Smuzhiyun }
2446*4882a593Smuzhiyun if (!param.action) {
2447*4882a593Smuzhiyun /* Get uap operation control parameters from FW */
2448*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_GET;
2449*4882a593Smuzhiyun } else {
2450*4882a593Smuzhiyun /* Set uap operation control configurations */
2451*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
2452*4882a593Smuzhiyun bss->param.ap_oper_ctrl.ctrl_value = uap_oper.ctrl_value;
2453*4882a593Smuzhiyun if (uap_oper.ctrl_value == 2)
2454*4882a593Smuzhiyun bss->param.ap_oper_ctrl.chan_opt = uap_oper.chan_opt;
2455*4882a593Smuzhiyun if (uap_oper.chan_opt == 3) {
2456*4882a593Smuzhiyun bss->param.ap_oper_ctrl.band_cfg = uap_oper.band_cfg;
2457*4882a593Smuzhiyun bss->param.ap_oper_ctrl.channel = uap_oper.channel;
2458*4882a593Smuzhiyun }
2459*4882a593Smuzhiyun }
2460*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2461*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
2462*4882a593Smuzhiyun ret = -EFAULT;
2463*4882a593Smuzhiyun goto done;
2464*4882a593Smuzhiyun }
2465*4882a593Smuzhiyun
2466*4882a593Smuzhiyun /* Copy to user */
2467*4882a593Smuzhiyun if (copy_to_user(req->ifr_data + sizeof(uap_oper_para_hdr),
2468*4882a593Smuzhiyun &bss->param.ap_oper_ctrl,
2469*4882a593Smuzhiyun sizeof(mlan_uap_oper_ctrl))) {
2470*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
2471*4882a593Smuzhiyun ret = -EFAULT;
2472*4882a593Smuzhiyun goto done;
2473*4882a593Smuzhiyun }
2474*4882a593Smuzhiyun done:
2475*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
2476*4882a593Smuzhiyun kfree(ioctl_req);
2477*4882a593Smuzhiyun LEAVE();
2478*4882a593Smuzhiyun return ret;
2479*4882a593Smuzhiyun }
2480*4882a593Smuzhiyun
2481*4882a593Smuzhiyun /**
2482*4882a593Smuzhiyun * @brief uap ioctl handler
2483*4882a593Smuzhiyun *
2484*4882a593Smuzhiyun * @param dev A pointer to net_device structure
2485*4882a593Smuzhiyun * @param req A pointer to ifreq structure
2486*4882a593Smuzhiyun * @return 0 --success, otherwise fail
2487*4882a593Smuzhiyun */
woal_uap_ioctl(struct net_device * dev,struct ifreq * req)2488*4882a593Smuzhiyun static int woal_uap_ioctl(struct net_device *dev, struct ifreq *req)
2489*4882a593Smuzhiyun {
2490*4882a593Smuzhiyun int ret = 0;
2491*4882a593Smuzhiyun t_u32 subcmd = 0;
2492*4882a593Smuzhiyun ENTER();
2493*4882a593Smuzhiyun /* Sanity check */
2494*4882a593Smuzhiyun if (req->ifr_data == NULL) {
2495*4882a593Smuzhiyun PRINTM(MERROR, "uap_ioctl() corrupt data\n");
2496*4882a593Smuzhiyun ret = -EFAULT;
2497*4882a593Smuzhiyun goto done;
2498*4882a593Smuzhiyun }
2499*4882a593Smuzhiyun if (copy_from_user(&subcmd, req->ifr_data, sizeof(subcmd))) {
2500*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
2501*4882a593Smuzhiyun ret = -EFAULT;
2502*4882a593Smuzhiyun goto done;
2503*4882a593Smuzhiyun }
2504*4882a593Smuzhiyun
2505*4882a593Smuzhiyun PRINTM(MIOCTL, "ioctl subcmd=%d\n", (int)subcmd);
2506*4882a593Smuzhiyun switch (subcmd) {
2507*4882a593Smuzhiyun case UAP_ADDBA_PARA:
2508*4882a593Smuzhiyun ret = woal_uap_addba_param(dev, req);
2509*4882a593Smuzhiyun break;
2510*4882a593Smuzhiyun case UAP_AGGR_PRIOTBL:
2511*4882a593Smuzhiyun ret = woal_uap_aggr_priotbl(dev, req);
2512*4882a593Smuzhiyun break;
2513*4882a593Smuzhiyun case UAP_ADDBA_REJECT:
2514*4882a593Smuzhiyun ret = woal_uap_addba_reject(dev, req);
2515*4882a593Smuzhiyun break;
2516*4882a593Smuzhiyun case UAP_FW_INFO:
2517*4882a593Smuzhiyun ret = woal_uap_get_fw_info(dev, req);
2518*4882a593Smuzhiyun break;
2519*4882a593Smuzhiyun case UAP_DEEP_SLEEP:
2520*4882a593Smuzhiyun ret = woal_uap_deep_sleep(dev, req);
2521*4882a593Smuzhiyun break;
2522*4882a593Smuzhiyun case UAP_TX_DATA_PAUSE:
2523*4882a593Smuzhiyun ret = woal_uap_txdatapause(dev, req);
2524*4882a593Smuzhiyun break;
2525*4882a593Smuzhiyun #ifdef SDIO
2526*4882a593Smuzhiyun case UAP_SDCMD52_RW:
2527*4882a593Smuzhiyun ret = woal_uap_sdcmd52_rw(dev, req);
2528*4882a593Smuzhiyun break;
2529*4882a593Smuzhiyun #endif
2530*4882a593Smuzhiyun case UAP_SNMP_MIB:
2531*4882a593Smuzhiyun ret = woal_uap_snmp_mib(dev, req);
2532*4882a593Smuzhiyun break;
2533*4882a593Smuzhiyun case UAP_DFS_TESTING:
2534*4882a593Smuzhiyun ret = woal_uap_dfs_testing(dev, req);
2535*4882a593Smuzhiyun break;
2536*4882a593Smuzhiyun case UAP_CHAN_SWITCH_COUNT_CFG:
2537*4882a593Smuzhiyun ret = woal_uap_chan_switch_count_cfg(dev, req);
2538*4882a593Smuzhiyun break;
2539*4882a593Smuzhiyun case UAP_DOMAIN_INFO:
2540*4882a593Smuzhiyun ret = woal_uap_domain_info(dev, req);
2541*4882a593Smuzhiyun break;
2542*4882a593Smuzhiyun case UAP_TX_BF_CFG:
2543*4882a593Smuzhiyun ret = woal_uap_tx_bf_cfg(dev, req);
2544*4882a593Smuzhiyun break;
2545*4882a593Smuzhiyun case UAP_HT_TX_CFG:
2546*4882a593Smuzhiyun ret = woal_uap_ht_tx_cfg(dev, req);
2547*4882a593Smuzhiyun break;
2548*4882a593Smuzhiyun case UAP_VHT_CFG:
2549*4882a593Smuzhiyun ret = woal_uap_vht_cfg(dev, req);
2550*4882a593Smuzhiyun break;
2551*4882a593Smuzhiyun case UAP_HS_CFG:
2552*4882a593Smuzhiyun ret = woal_uap_hs_cfg(dev, req, MTRUE);
2553*4882a593Smuzhiyun break;
2554*4882a593Smuzhiyun case UAP_HS_SET_PARA:
2555*4882a593Smuzhiyun ret = woal_uap_hs_set_para(dev, req);
2556*4882a593Smuzhiyun break;
2557*4882a593Smuzhiyun case UAP_MGMT_FRAME_CONTROL:
2558*4882a593Smuzhiyun ret = woal_uap_mgmt_frame_control(dev, req);
2559*4882a593Smuzhiyun break;
2560*4882a593Smuzhiyun case UAP_TX_RATE_CFG:
2561*4882a593Smuzhiyun ret = woal_uap_tx_rate_cfg(dev, req);
2562*4882a593Smuzhiyun break;
2563*4882a593Smuzhiyun case UAP_ANTENNA_CFG:
2564*4882a593Smuzhiyun ret = woal_uap_antenna_cfg(dev, req);
2565*4882a593Smuzhiyun break;
2566*4882a593Smuzhiyun case UAP_HT_STREAM_CFG:
2567*4882a593Smuzhiyun ret = woal_uap_htstream_cfg(dev, req);
2568*4882a593Smuzhiyun break;
2569*4882a593Smuzhiyun case UAP_DFS_REPEATER_MODE:
2570*4882a593Smuzhiyun ret = woal_uap_dfs_repeater(dev, req);
2571*4882a593Smuzhiyun break;
2572*4882a593Smuzhiyun case UAP_CAC_TIMER_STATUS:
2573*4882a593Smuzhiyun ret = woal_uap_cac_timer_status(dev, req);
2574*4882a593Smuzhiyun break;
2575*4882a593Smuzhiyun case UAP_SKIP_CAC:
2576*4882a593Smuzhiyun ret = woal_uap_skip_cac(dev, req);
2577*4882a593Smuzhiyun break;
2578*4882a593Smuzhiyun case UAP_OPERATION_CTRL:
2579*4882a593Smuzhiyun ret = woal_uap_operation_ctrl(dev, req);
2580*4882a593Smuzhiyun break;
2581*4882a593Smuzhiyun case UAP_BAND_STEER:
2582*4882a593Smuzhiyun ret = woal_uap_band_steer(dev, req);
2583*4882a593Smuzhiyun break;
2584*4882a593Smuzhiyun case UAP_BEACON_STUCK_DETECT:
2585*4882a593Smuzhiyun ret = woal_uap_beacon_stuck(dev, req);
2586*4882a593Smuzhiyun break;
2587*4882a593Smuzhiyun default:
2588*4882a593Smuzhiyun break;
2589*4882a593Smuzhiyun }
2590*4882a593Smuzhiyun done:
2591*4882a593Smuzhiyun LEAVE();
2592*4882a593Smuzhiyun return ret;
2593*4882a593Smuzhiyun }
2594*4882a593Smuzhiyun
2595*4882a593Smuzhiyun /**
2596*4882a593Smuzhiyun * @brief uap station deauth ioctl handler
2597*4882a593Smuzhiyun *
2598*4882a593Smuzhiyun * @param dev A pointer to net_device structure
2599*4882a593Smuzhiyun * @param req A pointer to ifreq structure
2600*4882a593Smuzhiyun * @return 0 --success, otherwise fail
2601*4882a593Smuzhiyun */
woal_uap_sta_deauth_ioctl(struct net_device * dev,struct ifreq * req)2602*4882a593Smuzhiyun static int woal_uap_sta_deauth_ioctl(struct net_device *dev, struct ifreq *req)
2603*4882a593Smuzhiyun {
2604*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
2605*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
2606*4882a593Smuzhiyun mlan_ds_bss *bss = NULL;
2607*4882a593Smuzhiyun mlan_deauth_param deauth_param;
2608*4882a593Smuzhiyun int ret = 0;
2609*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
2610*4882a593Smuzhiyun
2611*4882a593Smuzhiyun ENTER();
2612*4882a593Smuzhiyun
2613*4882a593Smuzhiyun memset(&deauth_param, 0, sizeof(mlan_deauth_param));
2614*4882a593Smuzhiyun /* Sanity check */
2615*4882a593Smuzhiyun if (req->ifr_data == NULL) {
2616*4882a593Smuzhiyun PRINTM(MERROR, "uap_sta_deauth_ioctl() corrupt data\n");
2617*4882a593Smuzhiyun ret = -EFAULT;
2618*4882a593Smuzhiyun goto done;
2619*4882a593Smuzhiyun }
2620*4882a593Smuzhiyun if (copy_from_user(&deauth_param, req->ifr_data,
2621*4882a593Smuzhiyun sizeof(mlan_deauth_param))) {
2622*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
2623*4882a593Smuzhiyun ret = -EFAULT;
2624*4882a593Smuzhiyun goto done;
2625*4882a593Smuzhiyun }
2626*4882a593Smuzhiyun
2627*4882a593Smuzhiyun PRINTM(MIOCTL, "ioctl deauth station: " MACSTR ", reason=%d\n",
2628*4882a593Smuzhiyun MAC2STR(deauth_param.mac_addr), deauth_param.reason_code);
2629*4882a593Smuzhiyun
2630*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
2631*4882a593Smuzhiyun if (ioctl_req == NULL) {
2632*4882a593Smuzhiyun ret = -ENOMEM;
2633*4882a593Smuzhiyun goto done;
2634*4882a593Smuzhiyun }
2635*4882a593Smuzhiyun bss = (mlan_ds_bss *)ioctl_req->pbuf;
2636*4882a593Smuzhiyun
2637*4882a593Smuzhiyun bss->sub_command = MLAN_OID_UAP_DEAUTH_STA;
2638*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_BSS;
2639*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
2640*4882a593Smuzhiyun
2641*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &bss->param.deauth_param, &deauth_param,
2642*4882a593Smuzhiyun sizeof(mlan_deauth_param),
2643*4882a593Smuzhiyun sizeof(bss->param.deauth_param));
2644*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2645*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
2646*4882a593Smuzhiyun ret = -EFAULT;
2647*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, &ioctl_req->status_code,
2648*4882a593Smuzhiyun sizeof(t_u32)))
2649*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
2650*4882a593Smuzhiyun goto done;
2651*4882a593Smuzhiyun }
2652*4882a593Smuzhiyun
2653*4882a593Smuzhiyun done:
2654*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
2655*4882a593Smuzhiyun kfree(ioctl_req);
2656*4882a593Smuzhiyun LEAVE();
2657*4882a593Smuzhiyun return ret;
2658*4882a593Smuzhiyun }
2659*4882a593Smuzhiyun
2660*4882a593Smuzhiyun /**
2661*4882a593Smuzhiyun * @brief Set/Get radio
2662*4882a593Smuzhiyun *
2663*4882a593Smuzhiyun * @param dev A pointer to net_device structure
2664*4882a593Smuzhiyun * @param req A pointer to ifreq structure
2665*4882a593Smuzhiyun *
2666*4882a593Smuzhiyun * @return 0 --success, otherwise fail
2667*4882a593Smuzhiyun */
woal_uap_radio_ctl(struct net_device * dev,struct ifreq * req)2668*4882a593Smuzhiyun static int woal_uap_radio_ctl(struct net_device *dev, struct ifreq *req)
2669*4882a593Smuzhiyun {
2670*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
2671*4882a593Smuzhiyun int ret = 0;
2672*4882a593Smuzhiyun mlan_ds_radio_cfg *radio = NULL;
2673*4882a593Smuzhiyun mlan_ioctl_req *mreq = NULL;
2674*4882a593Smuzhiyun int data[2] = {0, 0};
2675*4882a593Smuzhiyun mlan_bss_info bss_info;
2676*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
2677*4882a593Smuzhiyun
2678*4882a593Smuzhiyun ENTER();
2679*4882a593Smuzhiyun
2680*4882a593Smuzhiyun /* Sanity check */
2681*4882a593Smuzhiyun if (req->ifr_data == NULL) {
2682*4882a593Smuzhiyun PRINTM(MERROR, "uap_radio_ctl() corrupt data\n");
2683*4882a593Smuzhiyun ret = -EFAULT;
2684*4882a593Smuzhiyun goto done;
2685*4882a593Smuzhiyun }
2686*4882a593Smuzhiyun
2687*4882a593Smuzhiyun /* Get user data */
2688*4882a593Smuzhiyun if (copy_from_user(&data, req->ifr_data, sizeof(data))) {
2689*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
2690*4882a593Smuzhiyun ret = -EFAULT;
2691*4882a593Smuzhiyun goto done;
2692*4882a593Smuzhiyun }
2693*4882a593Smuzhiyun
2694*4882a593Smuzhiyun if (data[0]) {
2695*4882a593Smuzhiyun mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
2696*4882a593Smuzhiyun if (mreq == NULL) {
2697*4882a593Smuzhiyun ret = -ENOMEM;
2698*4882a593Smuzhiyun goto done;
2699*4882a593Smuzhiyun }
2700*4882a593Smuzhiyun radio = (mlan_ds_radio_cfg *)mreq->pbuf;
2701*4882a593Smuzhiyun radio->sub_command = MLAN_OID_RADIO_CTRL;
2702*4882a593Smuzhiyun mreq->req_id = MLAN_IOCTL_RADIO_CFG;
2703*4882a593Smuzhiyun mreq->action = MLAN_ACT_SET;
2704*4882a593Smuzhiyun radio->param.radio_on_off = (t_u32)data[1];
2705*4882a593Smuzhiyun status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
2706*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS)
2707*4882a593Smuzhiyun ret = -EFAULT;
2708*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
2709*4882a593Smuzhiyun kfree(mreq);
2710*4882a593Smuzhiyun } else {
2711*4882a593Smuzhiyun /* Get radio status */
2712*4882a593Smuzhiyun memset(&bss_info, 0, sizeof(bss_info));
2713*4882a593Smuzhiyun woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
2714*4882a593Smuzhiyun
2715*4882a593Smuzhiyun data[1] = bss_info.radio_on;
2716*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, data, sizeof(data))) {
2717*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed\n");
2718*4882a593Smuzhiyun ret = -EFAULT;
2719*4882a593Smuzhiyun }
2720*4882a593Smuzhiyun }
2721*4882a593Smuzhiyun done:
2722*4882a593Smuzhiyun LEAVE();
2723*4882a593Smuzhiyun return ret;
2724*4882a593Smuzhiyun }
2725*4882a593Smuzhiyun
2726*4882a593Smuzhiyun /**
2727*4882a593Smuzhiyun * @brief uap bss control ioctl handler
2728*4882a593Smuzhiyun *
2729*4882a593Smuzhiyun * @param dev A pointer to net_device structure
2730*4882a593Smuzhiyun * @param req A pointer to ifreq structure
2731*4882a593Smuzhiyun * @return 0 --success, otherwise fail
2732*4882a593Smuzhiyun */
woal_uap_bss_ctrl_ioctl(struct net_device * dev,struct ifreq * req)2733*4882a593Smuzhiyun static int woal_uap_bss_ctrl_ioctl(struct net_device *dev, struct ifreq *req)
2734*4882a593Smuzhiyun {
2735*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
2736*4882a593Smuzhiyun int ret = 0, data = 0;
2737*4882a593Smuzhiyun
2738*4882a593Smuzhiyun ENTER();
2739*4882a593Smuzhiyun
2740*4882a593Smuzhiyun /* Sanity check */
2741*4882a593Smuzhiyun if (req->ifr_data == NULL) {
2742*4882a593Smuzhiyun PRINTM(MERROR, "uap_bss_ctrl() corrupt data\n");
2743*4882a593Smuzhiyun ret = -EFAULT;
2744*4882a593Smuzhiyun goto done;
2745*4882a593Smuzhiyun }
2746*4882a593Smuzhiyun if (copy_from_user(&data, req->ifr_data, sizeof(data))) {
2747*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
2748*4882a593Smuzhiyun ret = -EFAULT;
2749*4882a593Smuzhiyun goto done;
2750*4882a593Smuzhiyun }
2751*4882a593Smuzhiyun
2752*4882a593Smuzhiyun ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, data);
2753*4882a593Smuzhiyun
2754*4882a593Smuzhiyun done:
2755*4882a593Smuzhiyun LEAVE();
2756*4882a593Smuzhiyun return ret;
2757*4882a593Smuzhiyun }
2758*4882a593Smuzhiyun
2759*4882a593Smuzhiyun /**
2760*4882a593Smuzhiyun * @brief uap report mic error ioctl handler
2761*4882a593Smuzhiyun *
2762*4882a593Smuzhiyun * @param dev A pointer to net_device structure
2763*4882a593Smuzhiyun * @param req A pointer to ifreq structure
2764*4882a593Smuzhiyun * @return 0 --success, otherwise fail
2765*4882a593Smuzhiyun */
woal_uap_report_mic_ioctl(struct net_device * dev,struct ifreq * req)2766*4882a593Smuzhiyun static int woal_uap_report_mic_ioctl(struct net_device *dev, struct ifreq *req)
2767*4882a593Smuzhiyun {
2768*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
2769*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
2770*4882a593Smuzhiyun mlan_ds_sec_cfg *sec = NULL;
2771*4882a593Smuzhiyun t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
2772*4882a593Smuzhiyun int ret = 0;
2773*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
2774*4882a593Smuzhiyun
2775*4882a593Smuzhiyun ENTER();
2776*4882a593Smuzhiyun
2777*4882a593Smuzhiyun memset(mac_addr, 0, MLAN_MAC_ADDR_LENGTH);
2778*4882a593Smuzhiyun /* Sanity check */
2779*4882a593Smuzhiyun if (req->ifr_data == NULL) {
2780*4882a593Smuzhiyun PRINTM(MERROR, "uap_report_mic_ioctl() corrupt data\n");
2781*4882a593Smuzhiyun ret = -EFAULT;
2782*4882a593Smuzhiyun goto done;
2783*4882a593Smuzhiyun }
2784*4882a593Smuzhiyun if (copy_from_user(mac_addr, req->ifr_data, MLAN_MAC_ADDR_LENGTH)) {
2785*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
2786*4882a593Smuzhiyun ret = -EFAULT;
2787*4882a593Smuzhiyun goto done;
2788*4882a593Smuzhiyun }
2789*4882a593Smuzhiyun
2790*4882a593Smuzhiyun PRINTM(MINFO, "ioctl report mic err station: " MACSTR "\n",
2791*4882a593Smuzhiyun MAC2STR(mac_addr));
2792*4882a593Smuzhiyun
2793*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
2794*4882a593Smuzhiyun if (ioctl_req == NULL) {
2795*4882a593Smuzhiyun ret = -ENOMEM;
2796*4882a593Smuzhiyun goto done;
2797*4882a593Smuzhiyun }
2798*4882a593Smuzhiyun
2799*4882a593Smuzhiyun sec = (mlan_ds_sec_cfg *)ioctl_req->pbuf;
2800*4882a593Smuzhiyun sec->sub_command = MLAN_OID_SEC_CFG_REPORT_MIC_ERR;
2801*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_SEC_CFG;
2802*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
2803*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, sec->param.sta_mac, mac_addr,
2804*4882a593Smuzhiyun MLAN_MAC_ADDR_LENGTH, sizeof(sec->param.sta_mac));
2805*4882a593Smuzhiyun
2806*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2807*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
2808*4882a593Smuzhiyun ret = -EFAULT;
2809*4882a593Smuzhiyun goto done;
2810*4882a593Smuzhiyun }
2811*4882a593Smuzhiyun
2812*4882a593Smuzhiyun done:
2813*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
2814*4882a593Smuzhiyun kfree(ioctl_req);
2815*4882a593Smuzhiyun LEAVE();
2816*4882a593Smuzhiyun return ret;
2817*4882a593Smuzhiyun }
2818*4882a593Smuzhiyun
2819*4882a593Smuzhiyun /**
2820*4882a593Smuzhiyun * @brief uap set key ioctl handler
2821*4882a593Smuzhiyun *
2822*4882a593Smuzhiyun * @param dev A pointer to net_device structure
2823*4882a593Smuzhiyun * @param req A pointer to ifreq structure
2824*4882a593Smuzhiyun * @return 0 --success, otherwise fail
2825*4882a593Smuzhiyun */
woal_uap_set_key_ioctl(struct net_device * dev,struct ifreq * req)2826*4882a593Smuzhiyun static int woal_uap_set_key_ioctl(struct net_device *dev, struct ifreq *req)
2827*4882a593Smuzhiyun {
2828*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
2829*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
2830*4882a593Smuzhiyun mlan_ds_sec_cfg *sec = NULL;
2831*4882a593Smuzhiyun encrypt_key key;
2832*4882a593Smuzhiyun int ret = 0;
2833*4882a593Smuzhiyun t_u8 bcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2834*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
2835*4882a593Smuzhiyun
2836*4882a593Smuzhiyun ENTER();
2837*4882a593Smuzhiyun
2838*4882a593Smuzhiyun memset(&key, 0, sizeof(encrypt_key));
2839*4882a593Smuzhiyun /* Sanity check */
2840*4882a593Smuzhiyun if (req->ifr_data == NULL) {
2841*4882a593Smuzhiyun PRINTM(MERROR, "uap_set_key_ioctl() corrupt data\n");
2842*4882a593Smuzhiyun ret = -EFAULT;
2843*4882a593Smuzhiyun goto done;
2844*4882a593Smuzhiyun }
2845*4882a593Smuzhiyun if (copy_from_user(&key, req->ifr_data, sizeof(encrypt_key))) {
2846*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
2847*4882a593Smuzhiyun ret = -EFAULT;
2848*4882a593Smuzhiyun goto done;
2849*4882a593Smuzhiyun }
2850*4882a593Smuzhiyun
2851*4882a593Smuzhiyun PRINTM(MIOCTL,
2852*4882a593Smuzhiyun "ioctl report set key: " MACSTR " key_index=%d, key_len=%d \n",
2853*4882a593Smuzhiyun MAC2STR(key.mac_addr), (int)key.key_index, (int)key.key_len);
2854*4882a593Smuzhiyun
2855*4882a593Smuzhiyun if ((key.key_len > MLAN_MAX_KEY_LENGTH) || (key.key_index > 3)) {
2856*4882a593Smuzhiyun ret = -EINVAL;
2857*4882a593Smuzhiyun goto done;
2858*4882a593Smuzhiyun }
2859*4882a593Smuzhiyun
2860*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
2861*4882a593Smuzhiyun if (ioctl_req == NULL) {
2862*4882a593Smuzhiyun ret = -ENOMEM;
2863*4882a593Smuzhiyun goto done;
2864*4882a593Smuzhiyun }
2865*4882a593Smuzhiyun
2866*4882a593Smuzhiyun sec = (mlan_ds_sec_cfg *)ioctl_req->pbuf;
2867*4882a593Smuzhiyun sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY,
2868*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_SEC_CFG;
2869*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
2870*4882a593Smuzhiyun
2871*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, sec->param.encrypt_key.mac_addr,
2872*4882a593Smuzhiyun key.mac_addr, MLAN_MAC_ADDR_LENGTH,
2873*4882a593Smuzhiyun sizeof(sec->param.encrypt_key.mac_addr));
2874*4882a593Smuzhiyun sec->param.encrypt_key.key_index = key.key_index;
2875*4882a593Smuzhiyun sec->param.encrypt_key.key_len = key.key_len;
2876*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, sec->param.encrypt_key.key_material,
2877*4882a593Smuzhiyun key.key_material, key.key_len,
2878*4882a593Smuzhiyun sizeof(sec->param.encrypt_key.key_material));
2879*4882a593Smuzhiyun if (0 == memcmp(sec->param.encrypt_key.mac_addr, bcast_addr, ETH_ALEN))
2880*4882a593Smuzhiyun sec->param.encrypt_key.key_flags = KEY_FLAG_GROUP_KEY;
2881*4882a593Smuzhiyun else
2882*4882a593Smuzhiyun sec->param.encrypt_key.key_flags = KEY_FLAG_SET_TX_KEY;
2883*4882a593Smuzhiyun
2884*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2885*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
2886*4882a593Smuzhiyun ret = -EFAULT;
2887*4882a593Smuzhiyun goto done;
2888*4882a593Smuzhiyun }
2889*4882a593Smuzhiyun done:
2890*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
2891*4882a593Smuzhiyun kfree(ioctl_req);
2892*4882a593Smuzhiyun LEAVE();
2893*4882a593Smuzhiyun return ret;
2894*4882a593Smuzhiyun }
2895*4882a593Smuzhiyun
2896*4882a593Smuzhiyun /**
2897*4882a593Smuzhiyun * @brief Set/Get uap power mode
2898*4882a593Smuzhiyun *
2899*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
2900*4882a593Smuzhiyun * @param action Action set or get
2901*4882a593Smuzhiyun * @param ps_mgmt A pointer to mlan_ds_ps_mgmt structure
2902*4882a593Smuzhiyun *
2903*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
2904*4882a593Smuzhiyun */
woal_set_get_uap_power_mode(moal_private * priv,t_u32 action,mlan_ds_ps_mgmt * ps_mgmt)2905*4882a593Smuzhiyun mlan_status woal_set_get_uap_power_mode(moal_private *priv, t_u32 action,
2906*4882a593Smuzhiyun mlan_ds_ps_mgmt *ps_mgmt)
2907*4882a593Smuzhiyun {
2908*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
2909*4882a593Smuzhiyun mlan_ds_pm_cfg *pm_cfg = NULL;
2910*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
2911*4882a593Smuzhiyun
2912*4882a593Smuzhiyun ENTER();
2913*4882a593Smuzhiyun if (!ps_mgmt) {
2914*4882a593Smuzhiyun LEAVE();
2915*4882a593Smuzhiyun return MLAN_STATUS_FAILURE;
2916*4882a593Smuzhiyun }
2917*4882a593Smuzhiyun
2918*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
2919*4882a593Smuzhiyun if (ioctl_req == NULL) {
2920*4882a593Smuzhiyun LEAVE();
2921*4882a593Smuzhiyun return MLAN_STATUS_FAILURE;
2922*4882a593Smuzhiyun }
2923*4882a593Smuzhiyun pm_cfg = (mlan_ds_pm_cfg *)ioctl_req->pbuf;
2924*4882a593Smuzhiyun pm_cfg->sub_command = MLAN_OID_PM_CFG_PS_MODE;
2925*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_PM_CFG;
2926*4882a593Smuzhiyun ioctl_req->action = action;
2927*4882a593Smuzhiyun if (action == MLAN_ACT_SET)
2928*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &pm_cfg->param.ps_mgmt, ps_mgmt,
2929*4882a593Smuzhiyun sizeof(mlan_ds_ps_mgmt),
2930*4882a593Smuzhiyun sizeof(pm_cfg->param.ps_mgmt));
2931*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2932*4882a593Smuzhiyun if (status == MLAN_STATUS_SUCCESS) {
2933*4882a593Smuzhiyun if (action == MLAN_ACT_GET)
2934*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, ps_mgmt,
2935*4882a593Smuzhiyun &pm_cfg->param.ps_mgmt,
2936*4882a593Smuzhiyun sizeof(mlan_ds_ps_mgmt),
2937*4882a593Smuzhiyun sizeof(mlan_ds_ps_mgmt));
2938*4882a593Smuzhiyun }
2939*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
2940*4882a593Smuzhiyun kfree(ioctl_req);
2941*4882a593Smuzhiyun LEAVE();
2942*4882a593Smuzhiyun return status;
2943*4882a593Smuzhiyun }
2944*4882a593Smuzhiyun
2945*4882a593Smuzhiyun /**
2946*4882a593Smuzhiyun * @brief uap power mode ioctl handler
2947*4882a593Smuzhiyun *
2948*4882a593Smuzhiyun * @param dev A pointer to net_device structure
2949*4882a593Smuzhiyun * @param req A pointer to ifreq structure
2950*4882a593Smuzhiyun * @return 0 --success, otherwise fail
2951*4882a593Smuzhiyun */
woal_uap_power_mode_ioctl(struct net_device * dev,struct ifreq * req)2952*4882a593Smuzhiyun static int woal_uap_power_mode_ioctl(struct net_device *dev, struct ifreq *req)
2953*4882a593Smuzhiyun {
2954*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
2955*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
2956*4882a593Smuzhiyun mlan_ds_pm_cfg *pm_cfg = NULL;
2957*4882a593Smuzhiyun mlan_ds_ps_mgmt ps_mgmt;
2958*4882a593Smuzhiyun int ret = 0;
2959*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
2960*4882a593Smuzhiyun
2961*4882a593Smuzhiyun ENTER();
2962*4882a593Smuzhiyun
2963*4882a593Smuzhiyun memset(&ps_mgmt, 0, sizeof(mlan_ds_ps_mgmt));
2964*4882a593Smuzhiyun
2965*4882a593Smuzhiyun /* Sanity check */
2966*4882a593Smuzhiyun if (req->ifr_data == NULL) {
2967*4882a593Smuzhiyun PRINTM(MERROR, "uap_power_mode_ioctl() corrupt data\n");
2968*4882a593Smuzhiyun ret = -EFAULT;
2969*4882a593Smuzhiyun goto done;
2970*4882a593Smuzhiyun }
2971*4882a593Smuzhiyun if (copy_from_user(&ps_mgmt, req->ifr_data, sizeof(mlan_ds_ps_mgmt))) {
2972*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
2973*4882a593Smuzhiyun ret = -EFAULT;
2974*4882a593Smuzhiyun goto done;
2975*4882a593Smuzhiyun }
2976*4882a593Smuzhiyun if (priv->bss_type != MLAN_BSS_TYPE_UAP) {
2977*4882a593Smuzhiyun PRINTM(MERROR, "Invlaid BSS_TYPE for UAP power mode command\n");
2978*4882a593Smuzhiyun ret = -EFAULT;
2979*4882a593Smuzhiyun goto done;
2980*4882a593Smuzhiyun }
2981*4882a593Smuzhiyun PRINTM(MIOCTL,
2982*4882a593Smuzhiyun "ioctl power: flag=0x%x ps_mode=%d ctrl_bitmap=%d min_sleep=%d max_sleep=%d "
2983*4882a593Smuzhiyun "inact_to=%d min_awake=%d max_awake=%d\n",
2984*4882a593Smuzhiyun ps_mgmt.flags, (int)ps_mgmt.ps_mode,
2985*4882a593Smuzhiyun (int)ps_mgmt.sleep_param.ctrl_bitmap,
2986*4882a593Smuzhiyun (int)ps_mgmt.sleep_param.min_sleep,
2987*4882a593Smuzhiyun (int)ps_mgmt.sleep_param.max_sleep,
2988*4882a593Smuzhiyun (int)ps_mgmt.inact_param.inactivity_to,
2989*4882a593Smuzhiyun (int)ps_mgmt.inact_param.min_awake,
2990*4882a593Smuzhiyun (int)ps_mgmt.inact_param.max_awake);
2991*4882a593Smuzhiyun
2992*4882a593Smuzhiyun if (ps_mgmt.flags & ~(PS_FLAG_PS_MODE | PS_FLAG_SLEEP_PARAM |
2993*4882a593Smuzhiyun PS_FLAG_INACT_SLEEP_PARAM)) {
2994*4882a593Smuzhiyun PRINTM(MERROR, "Invalid parameter: flags = 0x%x\n",
2995*4882a593Smuzhiyun ps_mgmt.flags);
2996*4882a593Smuzhiyun ret = -EINVAL;
2997*4882a593Smuzhiyun goto done;
2998*4882a593Smuzhiyun }
2999*4882a593Smuzhiyun
3000*4882a593Smuzhiyun if (ps_mgmt.ps_mode > PS_MODE_INACTIVITY) {
3001*4882a593Smuzhiyun PRINTM(MERROR, "Invalid parameter: ps_mode = %d\n",
3002*4882a593Smuzhiyun (int)ps_mgmt.flags);
3003*4882a593Smuzhiyun ret = -EINVAL;
3004*4882a593Smuzhiyun goto done;
3005*4882a593Smuzhiyun }
3006*4882a593Smuzhiyun
3007*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
3008*4882a593Smuzhiyun if (ioctl_req == NULL) {
3009*4882a593Smuzhiyun ret = -ENOMEM;
3010*4882a593Smuzhiyun goto done;
3011*4882a593Smuzhiyun }
3012*4882a593Smuzhiyun pm_cfg = (mlan_ds_pm_cfg *)ioctl_req->pbuf;
3013*4882a593Smuzhiyun pm_cfg->sub_command = MLAN_OID_PM_CFG_PS_MODE;
3014*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_PM_CFG;
3015*4882a593Smuzhiyun if (ps_mgmt.flags) {
3016*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
3017*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &pm_cfg->param.ps_mgmt, &ps_mgmt,
3018*4882a593Smuzhiyun sizeof(mlan_ds_ps_mgmt),
3019*4882a593Smuzhiyun sizeof(pm_cfg->param.ps_mgmt));
3020*4882a593Smuzhiyun } else {
3021*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_GET;
3022*4882a593Smuzhiyun }
3023*4882a593Smuzhiyun
3024*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
3025*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
3026*4882a593Smuzhiyun ret = -EFAULT;
3027*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, &ioctl_req->status_code,
3028*4882a593Smuzhiyun sizeof(t_u32)))
3029*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
3030*4882a593Smuzhiyun goto done;
3031*4882a593Smuzhiyun }
3032*4882a593Smuzhiyun if (!ps_mgmt.flags) {
3033*4882a593Smuzhiyun /* Copy to user */
3034*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, &pm_cfg->param.ps_mgmt,
3035*4882a593Smuzhiyun sizeof(mlan_ds_ps_mgmt))) {
3036*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
3037*4882a593Smuzhiyun ret = -EFAULT;
3038*4882a593Smuzhiyun goto done;
3039*4882a593Smuzhiyun }
3040*4882a593Smuzhiyun }
3041*4882a593Smuzhiyun done:
3042*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
3043*4882a593Smuzhiyun kfree(ioctl_req);
3044*4882a593Smuzhiyun LEAVE();
3045*4882a593Smuzhiyun return ret;
3046*4882a593Smuzhiyun }
3047*4882a593Smuzhiyun
3048*4882a593Smuzhiyun /**
3049*4882a593Smuzhiyun * @brief uap BSS config ioctl handler
3050*4882a593Smuzhiyun *
3051*4882a593Smuzhiyun * @param dev A pointer to net_device structure
3052*4882a593Smuzhiyun * @param req A pointer to ifreq structure
3053*4882a593Smuzhiyun * @return 0 --success, otherwise fail
3054*4882a593Smuzhiyun */
woal_uap_bss_cfg_ioctl(struct net_device * dev,struct ifreq * req)3055*4882a593Smuzhiyun static int woal_uap_bss_cfg_ioctl(struct net_device *dev, struct ifreq *req)
3056*4882a593Smuzhiyun {
3057*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
3058*4882a593Smuzhiyun int ret = 0;
3059*4882a593Smuzhiyun mlan_ds_bss *bss = NULL;
3060*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
3061*4882a593Smuzhiyun int offset = 0;
3062*4882a593Smuzhiyun t_u32 action = 0;
3063*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
3064*4882a593Smuzhiyun
3065*4882a593Smuzhiyun ENTER();
3066*4882a593Smuzhiyun
3067*4882a593Smuzhiyun /* Sanity check */
3068*4882a593Smuzhiyun if (req->ifr_data == NULL) {
3069*4882a593Smuzhiyun PRINTM(MERROR, "uap_bss_cfg_ioctl() corrupt data\n");
3070*4882a593Smuzhiyun ret = -EFAULT;
3071*4882a593Smuzhiyun goto done;
3072*4882a593Smuzhiyun }
3073*4882a593Smuzhiyun
3074*4882a593Smuzhiyun /* Get action */
3075*4882a593Smuzhiyun if (copy_from_user(&action, req->ifr_data + offset, sizeof(action))) {
3076*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
3077*4882a593Smuzhiyun ret = -EFAULT;
3078*4882a593Smuzhiyun goto done;
3079*4882a593Smuzhiyun }
3080*4882a593Smuzhiyun offset += sizeof(action);
3081*4882a593Smuzhiyun
3082*4882a593Smuzhiyun /* Allocate an IOCTL request buffer */
3083*4882a593Smuzhiyun ioctl_req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(
3084*4882a593Smuzhiyun sizeof(mlan_ds_bss));
3085*4882a593Smuzhiyun if (ioctl_req == NULL) {
3086*4882a593Smuzhiyun ret = -ENOMEM;
3087*4882a593Smuzhiyun goto done;
3088*4882a593Smuzhiyun }
3089*4882a593Smuzhiyun
3090*4882a593Smuzhiyun bss = (mlan_ds_bss *)ioctl_req->pbuf;
3091*4882a593Smuzhiyun bss->sub_command = MLAN_OID_UAP_BSS_CONFIG;
3092*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_BSS;
3093*4882a593Smuzhiyun if (action == 1)
3094*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
3095*4882a593Smuzhiyun else
3096*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_GET;
3097*4882a593Smuzhiyun
3098*4882a593Smuzhiyun if (ioctl_req->action == MLAN_ACT_SET) {
3099*4882a593Smuzhiyun /* Get the BSS config from user */
3100*4882a593Smuzhiyun if (copy_from_user(&bss->param.bss_config,
3101*4882a593Smuzhiyun req->ifr_data + offset,
3102*4882a593Smuzhiyun sizeof(mlan_uap_bss_param))) {
3103*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
3104*4882a593Smuzhiyun ret = -EFAULT;
3105*4882a593Smuzhiyun goto done;
3106*4882a593Smuzhiyun }
3107*4882a593Smuzhiyun }
3108*4882a593Smuzhiyun
3109*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
3110*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
3111*4882a593Smuzhiyun ret = -EFAULT;
3112*4882a593Smuzhiyun goto done;
3113*4882a593Smuzhiyun }
3114*4882a593Smuzhiyun
3115*4882a593Smuzhiyun if (ioctl_req->action == MLAN_ACT_GET) {
3116*4882a593Smuzhiyun offset = sizeof(action);
3117*4882a593Smuzhiyun
3118*4882a593Smuzhiyun /* Copy to user : BSS config */
3119*4882a593Smuzhiyun if (copy_to_user(req->ifr_data + offset, &bss->param.bss_config,
3120*4882a593Smuzhiyun sizeof(mlan_uap_bss_param))) {
3121*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
3122*4882a593Smuzhiyun ret = -EFAULT;
3123*4882a593Smuzhiyun goto done;
3124*4882a593Smuzhiyun }
3125*4882a593Smuzhiyun }
3126*4882a593Smuzhiyun done:
3127*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
3128*4882a593Smuzhiyun kfree(ioctl_req);
3129*4882a593Smuzhiyun LEAVE();
3130*4882a593Smuzhiyun return ret;
3131*4882a593Smuzhiyun }
3132*4882a593Smuzhiyun
3133*4882a593Smuzhiyun /**
3134*4882a593Smuzhiyun * @brief uap get station list handler
3135*4882a593Smuzhiyun *
3136*4882a593Smuzhiyun * @param dev A pointer to net_device structure
3137*4882a593Smuzhiyun * @param req A pointer to ifreq structure
3138*4882a593Smuzhiyun * @return 0 --success, otherwise fail
3139*4882a593Smuzhiyun */
woal_uap_get_sta_list_ioctl(struct net_device * dev,struct ifreq * req)3140*4882a593Smuzhiyun static int woal_uap_get_sta_list_ioctl(struct net_device *dev,
3141*4882a593Smuzhiyun struct ifreq *req)
3142*4882a593Smuzhiyun {
3143*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
3144*4882a593Smuzhiyun int ret = 0;
3145*4882a593Smuzhiyun mlan_ds_get_info *info = NULL;
3146*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
3147*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
3148*4882a593Smuzhiyun
3149*4882a593Smuzhiyun ENTER();
3150*4882a593Smuzhiyun
3151*4882a593Smuzhiyun /* Sanity check */
3152*4882a593Smuzhiyun if (req->ifr_data == NULL) {
3153*4882a593Smuzhiyun PRINTM(MERROR, "uap_get_sta_list_ioctl() corrupt data\n");
3154*4882a593Smuzhiyun ret = -EFAULT;
3155*4882a593Smuzhiyun goto done;
3156*4882a593Smuzhiyun }
3157*4882a593Smuzhiyun
3158*4882a593Smuzhiyun /* Allocate an IOCTL request buffer */
3159*4882a593Smuzhiyun ioctl_req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(
3160*4882a593Smuzhiyun sizeof(mlan_ds_get_info));
3161*4882a593Smuzhiyun if (ioctl_req == NULL) {
3162*4882a593Smuzhiyun ret = -ENOMEM;
3163*4882a593Smuzhiyun goto done;
3164*4882a593Smuzhiyun }
3165*4882a593Smuzhiyun
3166*4882a593Smuzhiyun info = (mlan_ds_get_info *)ioctl_req->pbuf;
3167*4882a593Smuzhiyun info->sub_command = MLAN_OID_UAP_STA_LIST;
3168*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_GET_INFO;
3169*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_GET;
3170*4882a593Smuzhiyun
3171*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
3172*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
3173*4882a593Smuzhiyun ret = -EFAULT;
3174*4882a593Smuzhiyun goto done;
3175*4882a593Smuzhiyun }
3176*4882a593Smuzhiyun
3177*4882a593Smuzhiyun if (ioctl_req->action == MLAN_ACT_GET) {
3178*4882a593Smuzhiyun /* Copy to user : sta_list */
3179*4882a593Smuzhiyun if (copy_to_user(req->ifr_data, &info->param.sta_list,
3180*4882a593Smuzhiyun ioctl_req->data_read_written)) {
3181*4882a593Smuzhiyun PRINTM(MERROR, "Copy to user failed!\n");
3182*4882a593Smuzhiyun ret = -EFAULT;
3183*4882a593Smuzhiyun goto done;
3184*4882a593Smuzhiyun }
3185*4882a593Smuzhiyun }
3186*4882a593Smuzhiyun done:
3187*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
3188*4882a593Smuzhiyun kfree(ioctl_req);
3189*4882a593Smuzhiyun LEAVE();
3190*4882a593Smuzhiyun return ret;
3191*4882a593Smuzhiyun }
3192*4882a593Smuzhiyun
3193*4882a593Smuzhiyun /**
3194*4882a593Smuzhiyun * @brief uAP set WAPI key ioctl
3195*4882a593Smuzhiyun *
3196*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
3197*4882a593Smuzhiyun * @param msg A pointer to wapi_msg structure
3198*4882a593Smuzhiyun *
3199*4882a593Smuzhiyun * @return 0 --success, otherwise fail
3200*4882a593Smuzhiyun */
woal_uap_set_wapi_key_ioctl(moal_private * priv,wapi_msg * msg)3201*4882a593Smuzhiyun static int woal_uap_set_wapi_key_ioctl(moal_private *priv, wapi_msg *msg)
3202*4882a593Smuzhiyun {
3203*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
3204*4882a593Smuzhiyun mlan_ds_sec_cfg *sec = NULL;
3205*4882a593Smuzhiyun int ret = 0;
3206*4882a593Smuzhiyun wapi_key_msg *key_msg = NULL;
3207*4882a593Smuzhiyun t_u8 bcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
3208*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
3209*4882a593Smuzhiyun
3210*4882a593Smuzhiyun ENTER();
3211*4882a593Smuzhiyun if (msg->msg_len != sizeof(wapi_key_msg)) {
3212*4882a593Smuzhiyun ret = -EINVAL;
3213*4882a593Smuzhiyun goto done;
3214*4882a593Smuzhiyun }
3215*4882a593Smuzhiyun key_msg = (wapi_key_msg *)msg->msg;
3216*4882a593Smuzhiyun
3217*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
3218*4882a593Smuzhiyun if (req == NULL) {
3219*4882a593Smuzhiyun ret = -ENOMEM;
3220*4882a593Smuzhiyun goto done;
3221*4882a593Smuzhiyun }
3222*4882a593Smuzhiyun sec = (mlan_ds_sec_cfg *)req->pbuf;
3223*4882a593Smuzhiyun sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
3224*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_SEC_CFG;
3225*4882a593Smuzhiyun req->action = MLAN_ACT_SET;
3226*4882a593Smuzhiyun
3227*4882a593Smuzhiyun sec->param.encrypt_key.is_wapi_key = MTRUE;
3228*4882a593Smuzhiyun sec->param.encrypt_key.key_len = MLAN_MAX_KEY_LENGTH;
3229*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, sec->param.encrypt_key.mac_addr,
3230*4882a593Smuzhiyun key_msg->mac_addr, ETH_ALEN,
3231*4882a593Smuzhiyun sizeof(sec->param.encrypt_key.mac_addr));
3232*4882a593Smuzhiyun sec->param.encrypt_key.key_index = key_msg->key_id;
3233*4882a593Smuzhiyun if (0 == memcmp(key_msg->mac_addr, bcast_addr, ETH_ALEN))
3234*4882a593Smuzhiyun sec->param.encrypt_key.key_flags = KEY_FLAG_GROUP_KEY;
3235*4882a593Smuzhiyun else
3236*4882a593Smuzhiyun sec->param.encrypt_key.key_flags = KEY_FLAG_SET_TX_KEY;
3237*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, sec->param.encrypt_key.key_material,
3238*4882a593Smuzhiyun key_msg->key, sec->param.encrypt_key.key_len,
3239*4882a593Smuzhiyun sizeof(sec->param.encrypt_key.key_material));
3240*4882a593Smuzhiyun
3241*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3242*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS)
3243*4882a593Smuzhiyun ret = -EFAULT;
3244*4882a593Smuzhiyun done:
3245*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
3246*4882a593Smuzhiyun kfree(req);
3247*4882a593Smuzhiyun LEAVE();
3248*4882a593Smuzhiyun return ret;
3249*4882a593Smuzhiyun }
3250*4882a593Smuzhiyun
3251*4882a593Smuzhiyun /**
3252*4882a593Smuzhiyun * @brief Enable/Disable wapi in firmware
3253*4882a593Smuzhiyun *
3254*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
3255*4882a593Smuzhiyun * @param enable MTRUE/MFALSE
3256*4882a593Smuzhiyun *
3257*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
3258*4882a593Smuzhiyun * otherwise fail
3259*4882a593Smuzhiyun */
woal_enable_wapi(moal_private * priv,t_u8 enable)3260*4882a593Smuzhiyun static mlan_status woal_enable_wapi(moal_private *priv, t_u8 enable)
3261*4882a593Smuzhiyun {
3262*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
3263*4882a593Smuzhiyun mlan_ds_bss *bss = NULL;
3264*4882a593Smuzhiyun mlan_status status;
3265*4882a593Smuzhiyun
3266*4882a593Smuzhiyun ENTER();
3267*4882a593Smuzhiyun
3268*4882a593Smuzhiyun /* Allocate an IOCTL request buffer */
3269*4882a593Smuzhiyun req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
3270*4882a593Smuzhiyun if (req == NULL) {
3271*4882a593Smuzhiyun status = MLAN_STATUS_FAILURE;
3272*4882a593Smuzhiyun goto done;
3273*4882a593Smuzhiyun }
3274*4882a593Smuzhiyun
3275*4882a593Smuzhiyun /* Fill request buffer */
3276*4882a593Smuzhiyun bss = (mlan_ds_bss *)req->pbuf;
3277*4882a593Smuzhiyun bss->sub_command = MLAN_OID_UAP_BSS_CONFIG;
3278*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_BSS;
3279*4882a593Smuzhiyun req->action = MLAN_ACT_GET;
3280*4882a593Smuzhiyun
3281*4882a593Smuzhiyun /* Send IOCTL request to MLAN */
3282*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3283*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
3284*4882a593Smuzhiyun PRINTM(MERROR,
3285*4882a593Smuzhiyun "Get AP setting failed! status=%d, error_code=0x%x\n",
3286*4882a593Smuzhiyun status, req->status_code);
3287*4882a593Smuzhiyun }
3288*4882a593Smuzhiyun
3289*4882a593Smuzhiyun /* Change AP default setting */
3290*4882a593Smuzhiyun req->action = MLAN_ACT_SET;
3291*4882a593Smuzhiyun if (enable == MFALSE) {
3292*4882a593Smuzhiyun bss->param.bss_config.auth_mode = MLAN_AUTH_MODE_OPEN;
3293*4882a593Smuzhiyun bss->param.bss_config.protocol = PROTOCOL_NO_SECURITY;
3294*4882a593Smuzhiyun } else {
3295*4882a593Smuzhiyun bss->param.bss_config.auth_mode = MLAN_AUTH_MODE_OPEN;
3296*4882a593Smuzhiyun bss->param.bss_config.protocol = PROTOCOL_WAPI;
3297*4882a593Smuzhiyun }
3298*4882a593Smuzhiyun
3299*4882a593Smuzhiyun /* Send IOCTL request to MLAN */
3300*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3301*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
3302*4882a593Smuzhiyun PRINTM(MERROR,
3303*4882a593Smuzhiyun "Set AP setting failed! status=%d, error_code=0x%x\n",
3304*4882a593Smuzhiyun status, req->status_code);
3305*4882a593Smuzhiyun }
3306*4882a593Smuzhiyun if (enable) {
3307*4882a593Smuzhiyun if (woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START))
3308*4882a593Smuzhiyun PRINTM(MERROR, "%s: uap bss start failed \n", __func__);
3309*4882a593Smuzhiyun }
3310*4882a593Smuzhiyun done:
3311*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
3312*4882a593Smuzhiyun kfree(req);
3313*4882a593Smuzhiyun LEAVE();
3314*4882a593Smuzhiyun return status;
3315*4882a593Smuzhiyun }
3316*4882a593Smuzhiyun
3317*4882a593Smuzhiyun /**
3318*4882a593Smuzhiyun * @brief uAP set WAPI flag ioctl
3319*4882a593Smuzhiyun *
3320*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
3321*4882a593Smuzhiyun * @param msg A pointer to wapi_msg structure
3322*4882a593Smuzhiyun *
3323*4882a593Smuzhiyun * @return 0 --success, otherwise fail
3324*4882a593Smuzhiyun */
woal_uap_set_wapi_flag_ioctl(moal_private * priv,wapi_msg * msg)3325*4882a593Smuzhiyun static int woal_uap_set_wapi_flag_ioctl(moal_private *priv, wapi_msg *msg)
3326*4882a593Smuzhiyun {
3327*4882a593Smuzhiyun t_u8 wapi_psk_ie[] = {0x44, 0x14, 0x01, 0x00, 0x01, 0x00, 0x00, 0x14,
3328*4882a593Smuzhiyun 0x72, 0x02, 0x01, 0x00, 0x00, 0x14, 0x72, 0x01,
3329*4882a593Smuzhiyun 0x00, 0x14, 0x72, 0x01, 0x00, 0x00};
3330*4882a593Smuzhiyun t_u8 wapi_cert_ie[] = {0x44, 0x14, 0x01, 0x00, 0x01, 0x00, 0x00, 0x14,
3331*4882a593Smuzhiyun 0x72, 0x01, 0x01, 0x00, 0x00, 0x14, 0x72, 0x01,
3332*4882a593Smuzhiyun 0x00, 0x14, 0x72, 0x01, 0x00, 0x00};
3333*4882a593Smuzhiyun mlan_ds_misc_cfg *misc = NULL;
3334*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
3335*4882a593Smuzhiyun int ret = 0;
3336*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
3337*4882a593Smuzhiyun
3338*4882a593Smuzhiyun ENTER();
3339*4882a593Smuzhiyun
3340*4882a593Smuzhiyun if (woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP)) {
3341*4882a593Smuzhiyun PRINTM(MERROR, "%s: uap bss stop failed \n", __func__);
3342*4882a593Smuzhiyun ret = -EFAULT;
3343*4882a593Smuzhiyun goto done;
3344*4882a593Smuzhiyun }
3345*4882a593Smuzhiyun
3346*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3347*4882a593Smuzhiyun if (req == NULL) {
3348*4882a593Smuzhiyun ret = -ENOMEM;
3349*4882a593Smuzhiyun goto done;
3350*4882a593Smuzhiyun }
3351*4882a593Smuzhiyun misc = (mlan_ds_misc_cfg *)req->pbuf;
3352*4882a593Smuzhiyun misc->sub_command = MLAN_OID_MISC_GEN_IE;
3353*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_MISC_CFG;
3354*4882a593Smuzhiyun req->action = MLAN_ACT_SET;
3355*4882a593Smuzhiyun
3356*4882a593Smuzhiyun misc->param.gen_ie.type = MLAN_IE_TYPE_GEN_IE;
3357*4882a593Smuzhiyun misc->param.gen_ie.len = sizeof(wapi_psk_ie);
3358*4882a593Smuzhiyun if (msg->msg[0] & WAPI_MODE_PSK) {
3359*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, misc->param.gen_ie.ie_data,
3360*4882a593Smuzhiyun wapi_psk_ie, misc->param.gen_ie.len,
3361*4882a593Smuzhiyun sizeof(misc->param.gen_ie.ie_data));
3362*4882a593Smuzhiyun } else if (msg->msg[0] & WAPI_MODE_CERT) {
3363*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, misc->param.gen_ie.ie_data,
3364*4882a593Smuzhiyun wapi_cert_ie, misc->param.gen_ie.len,
3365*4882a593Smuzhiyun sizeof(misc->param.gen_ie.ie_data));
3366*4882a593Smuzhiyun } else if (msg->msg[0] == 0) {
3367*4882a593Smuzhiyun /* disable WAPI in driver */
3368*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
3369*4882a593Smuzhiyun woal_set_wapi_enable(priv, MOAL_IOCTL_WAIT, 0))
3370*4882a593Smuzhiyun ret = -EFAULT;
3371*4882a593Smuzhiyun woal_enable_wapi(priv, MFALSE);
3372*4882a593Smuzhiyun goto done;
3373*4882a593Smuzhiyun } else {
3374*4882a593Smuzhiyun ret = -EINVAL;
3375*4882a593Smuzhiyun goto done;
3376*4882a593Smuzhiyun }
3377*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3378*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
3379*4882a593Smuzhiyun ret = -EFAULT;
3380*4882a593Smuzhiyun goto done;
3381*4882a593Smuzhiyun }
3382*4882a593Smuzhiyun woal_enable_wapi(priv, MTRUE);
3383*4882a593Smuzhiyun done:
3384*4882a593Smuzhiyun if ((status != MLAN_STATUS_PENDING) && req)
3385*4882a593Smuzhiyun kfree(req);
3386*4882a593Smuzhiyun LEAVE();
3387*4882a593Smuzhiyun return ret;
3388*4882a593Smuzhiyun }
3389*4882a593Smuzhiyun
3390*4882a593Smuzhiyun /**
3391*4882a593Smuzhiyun * @brief set wapi ioctl function
3392*4882a593Smuzhiyun *
3393*4882a593Smuzhiyun * @param dev A pointer to net_device structure
3394*4882a593Smuzhiyun * @param req A pointer to ifreq structure
3395*4882a593Smuzhiyun * @return 0 --success, otherwise fail
3396*4882a593Smuzhiyun */
woal_uap_set_wapi(struct net_device * dev,struct ifreq * req)3397*4882a593Smuzhiyun static int woal_uap_set_wapi(struct net_device *dev, struct ifreq *req)
3398*4882a593Smuzhiyun {
3399*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
3400*4882a593Smuzhiyun wapi_msg msg;
3401*4882a593Smuzhiyun int ret = 0;
3402*4882a593Smuzhiyun
3403*4882a593Smuzhiyun ENTER();
3404*4882a593Smuzhiyun
3405*4882a593Smuzhiyun /* Sanity check */
3406*4882a593Smuzhiyun if (req->ifr_data == NULL) {
3407*4882a593Smuzhiyun PRINTM(MERROR, "uap_set_wapi() corrupt data\n");
3408*4882a593Smuzhiyun ret = -EFAULT;
3409*4882a593Smuzhiyun goto done;
3410*4882a593Smuzhiyun }
3411*4882a593Smuzhiyun
3412*4882a593Smuzhiyun memset(&msg, 0, sizeof(msg));
3413*4882a593Smuzhiyun
3414*4882a593Smuzhiyun if (copy_from_user(&msg, req->ifr_data, sizeof(msg))) {
3415*4882a593Smuzhiyun PRINTM(MERROR, "Copy from user failed\n");
3416*4882a593Smuzhiyun ret = -EFAULT;
3417*4882a593Smuzhiyun goto done;
3418*4882a593Smuzhiyun }
3419*4882a593Smuzhiyun
3420*4882a593Smuzhiyun PRINTM(MIOCTL, "set wapi msg_type = %d, msg_len=%d\n", msg.msg_type,
3421*4882a593Smuzhiyun msg.msg_len);
3422*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "wapi msg", msg.msg,
3423*4882a593Smuzhiyun MIN(msg.msg_len, sizeof(msg.msg)));
3424*4882a593Smuzhiyun
3425*4882a593Smuzhiyun switch (msg.msg_type) {
3426*4882a593Smuzhiyun case P80211_PACKET_WAPIFLAG:
3427*4882a593Smuzhiyun ret = woal_uap_set_wapi_flag_ioctl(priv, &msg);
3428*4882a593Smuzhiyun break;
3429*4882a593Smuzhiyun case P80211_PACKET_SETKEY:
3430*4882a593Smuzhiyun ret = woal_uap_set_wapi_key_ioctl(priv, &msg);
3431*4882a593Smuzhiyun break;
3432*4882a593Smuzhiyun default:
3433*4882a593Smuzhiyun ret = -EOPNOTSUPP;
3434*4882a593Smuzhiyun break;
3435*4882a593Smuzhiyun }
3436*4882a593Smuzhiyun done:
3437*4882a593Smuzhiyun LEAVE();
3438*4882a593Smuzhiyun return ret;
3439*4882a593Smuzhiyun }
3440*4882a593Smuzhiyun
3441*4882a593Smuzhiyun /********************************************************
3442*4882a593Smuzhiyun Global Functions
3443*4882a593Smuzhiyun ********************************************************/
3444*4882a593Smuzhiyun /**
3445*4882a593Smuzhiyun * @brief Initialize the members of mlan_uap_bss_param
3446*4882a593Smuzhiyun * which are uploaded from firmware
3447*4882a593Smuzhiyun *
3448*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
3449*4882a593Smuzhiyun * @param sys_cfg A pointer to mlan_uap_bss_param structure
3450*4882a593Smuzhiyun * @param wait_option Wait option
3451*4882a593Smuzhiyun *
3452*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3453*4882a593Smuzhiyun */
woal_uap_get_bss_param(moal_private * priv,mlan_uap_bss_param * sys_cfg,t_u8 wait_option)3454*4882a593Smuzhiyun static mlan_status woal_uap_get_bss_param(moal_private *priv,
3455*4882a593Smuzhiyun mlan_uap_bss_param *sys_cfg,
3456*4882a593Smuzhiyun t_u8 wait_option)
3457*4882a593Smuzhiyun {
3458*4882a593Smuzhiyun mlan_ds_bss *info = NULL;
3459*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
3460*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
3461*4882a593Smuzhiyun
3462*4882a593Smuzhiyun ENTER();
3463*4882a593Smuzhiyun
3464*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
3465*4882a593Smuzhiyun if (req == NULL) {
3466*4882a593Smuzhiyun LEAVE();
3467*4882a593Smuzhiyun return MLAN_STATUS_FAILURE;
3468*4882a593Smuzhiyun }
3469*4882a593Smuzhiyun
3470*4882a593Smuzhiyun info = (mlan_ds_bss *)req->pbuf;
3471*4882a593Smuzhiyun info->sub_command = MLAN_OID_UAP_BSS_CONFIG;
3472*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_BSS;
3473*4882a593Smuzhiyun req->action = MLAN_ACT_GET;
3474*4882a593Smuzhiyun
3475*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, wait_option);
3476*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
3477*4882a593Smuzhiyun PRINTM(MERROR, "Get bss info failed!\n");
3478*4882a593Smuzhiyun status = MLAN_STATUS_FAILURE;
3479*4882a593Smuzhiyun goto done;
3480*4882a593Smuzhiyun }
3481*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, sys_cfg, &info->param.bss_config,
3482*4882a593Smuzhiyun sizeof(mlan_uap_bss_param), sizeof(mlan_uap_bss_param));
3483*4882a593Smuzhiyun
3484*4882a593Smuzhiyun done:
3485*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
3486*4882a593Smuzhiyun kfree(req);
3487*4882a593Smuzhiyun LEAVE();
3488*4882a593Smuzhiyun return status;
3489*4882a593Smuzhiyun }
3490*4882a593Smuzhiyun
3491*4882a593Smuzhiyun /**
3492*4882a593Smuzhiyun * @brief Set uap httxcfg
3493*4882a593Smuzhiyun *
3494*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
3495*4882a593Smuzhiyun * @param band_cfg Band cfg
3496*4882a593Smuzhiyun * @param en Enabled/Disabled
3497*4882a593Smuzhiyun *
3498*4882a593Smuzhiyun * @return 0 --success, otherwise fail
3499*4882a593Smuzhiyun */
woal_set_uap_ht_tx_cfg(moal_private * priv,Band_Config_t bandcfg,t_u16 ht_cap,t_u8 en)3500*4882a593Smuzhiyun int woal_set_uap_ht_tx_cfg(moal_private *priv, Band_Config_t bandcfg,
3501*4882a593Smuzhiyun t_u16 ht_cap, t_u8 en)
3502*4882a593Smuzhiyun {
3503*4882a593Smuzhiyun int ret = 0;
3504*4882a593Smuzhiyun mlan_ds_11n_cfg *cfg_11n = NULL;
3505*4882a593Smuzhiyun mlan_ioctl_req *ioctl_req = NULL;
3506*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
3507*4882a593Smuzhiyun
3508*4882a593Smuzhiyun ENTER();
3509*4882a593Smuzhiyun
3510*4882a593Smuzhiyun ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
3511*4882a593Smuzhiyun if (ioctl_req == NULL) {
3512*4882a593Smuzhiyun ret = -ENOMEM;
3513*4882a593Smuzhiyun goto done;
3514*4882a593Smuzhiyun }
3515*4882a593Smuzhiyun cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
3516*4882a593Smuzhiyun cfg_11n->sub_command = MLAN_OID_11N_CFG_TX;
3517*4882a593Smuzhiyun ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
3518*4882a593Smuzhiyun
3519*4882a593Smuzhiyun /* Set HT Tx configurations */
3520*4882a593Smuzhiyun if (bandcfg.chanBand == BAND_2GHZ) {
3521*4882a593Smuzhiyun if (en)
3522*4882a593Smuzhiyun cfg_11n->param.tx_cfg.httxcap = ht_cap;
3523*4882a593Smuzhiyun else
3524*4882a593Smuzhiyun cfg_11n->param.tx_cfg.httxcap = 0;
3525*4882a593Smuzhiyun cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_BG;
3526*4882a593Smuzhiyun } else if (bandcfg.chanBand == BAND_5GHZ) {
3527*4882a593Smuzhiyun if (en)
3528*4882a593Smuzhiyun cfg_11n->param.tx_cfg.httxcap = ht_cap;
3529*4882a593Smuzhiyun else
3530*4882a593Smuzhiyun cfg_11n->param.tx_cfg.httxcap = 0;
3531*4882a593Smuzhiyun cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_A;
3532*4882a593Smuzhiyun }
3533*4882a593Smuzhiyun PRINTM(MCMND, "SET: httxcap=0x%x band:0x%x\n",
3534*4882a593Smuzhiyun cfg_11n->param.tx_cfg.httxcap, cfg_11n->param.tx_cfg.misc_cfg);
3535*4882a593Smuzhiyun /* Update 11n tx parameters in MLAN */
3536*4882a593Smuzhiyun ioctl_req->action = MLAN_ACT_SET;
3537*4882a593Smuzhiyun status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
3538*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
3539*4882a593Smuzhiyun ret = -EFAULT;
3540*4882a593Smuzhiyun goto done;
3541*4882a593Smuzhiyun }
3542*4882a593Smuzhiyun done:
3543*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
3544*4882a593Smuzhiyun kfree(ioctl_req);
3545*4882a593Smuzhiyun LEAVE();
3546*4882a593Smuzhiyun return ret;
3547*4882a593Smuzhiyun }
3548*4882a593Smuzhiyun
3549*4882a593Smuzhiyun /**
3550*4882a593Smuzhiyun * @brief Set 11n status based on the configured security mode
3551*4882a593Smuzhiyun *
3552*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
3553*4882a593Smuzhiyun * @param sys_cfg A pointer to mlan_uap_bss_param structure
3554*4882a593Smuzhiyun * @param action MLAN_ACT_DISABLE or MLAN_ACT_ENABLE
3555*4882a593Smuzhiyun *
3556*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3557*4882a593Smuzhiyun */
woal_uap_set_11n_status(moal_private * priv,mlan_uap_bss_param * sys_cfg,t_u8 action)3558*4882a593Smuzhiyun mlan_status woal_uap_set_11n_status(moal_private *priv,
3559*4882a593Smuzhiyun mlan_uap_bss_param *sys_cfg, t_u8 action)
3560*4882a593Smuzhiyun {
3561*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
3562*4882a593Smuzhiyun mlan_fw_info fw_info;
3563*4882a593Smuzhiyun
3564*4882a593Smuzhiyun ENTER();
3565*4882a593Smuzhiyun memset(&fw_info, 0, sizeof(mlan_fw_info));
3566*4882a593Smuzhiyun if (action == MLAN_ACT_DISABLE) {
3567*4882a593Smuzhiyun if ((sys_cfg->supported_mcs_set[0] == 0) &&
3568*4882a593Smuzhiyun (sys_cfg->supported_mcs_set[4] == 0) &&
3569*4882a593Smuzhiyun (sys_cfg->supported_mcs_set[1] == 0)) {
3570*4882a593Smuzhiyun goto done;
3571*4882a593Smuzhiyun } else {
3572*4882a593Smuzhiyun sys_cfg->supported_mcs_set[0] = 0;
3573*4882a593Smuzhiyun sys_cfg->supported_mcs_set[4] = 0;
3574*4882a593Smuzhiyun sys_cfg->supported_mcs_set[1] = 0;
3575*4882a593Smuzhiyun }
3576*4882a593Smuzhiyun }
3577*4882a593Smuzhiyun
3578*4882a593Smuzhiyun if (action == MLAN_ACT_ENABLE) {
3579*4882a593Smuzhiyun woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
3580*4882a593Smuzhiyun sys_cfg->supported_mcs_set[0] = 0xFF;
3581*4882a593Smuzhiyun if (sys_cfg->bandcfg.chan2Offset)
3582*4882a593Smuzhiyun sys_cfg->supported_mcs_set[4] = 0x01;
3583*4882a593Smuzhiyun else
3584*4882a593Smuzhiyun sys_cfg->supported_mcs_set[4] = 0x0;
3585*4882a593Smuzhiyun if (fw_info.usr_dev_mcs_support == HT_STREAM_MODE_2X2)
3586*4882a593Smuzhiyun sys_cfg->supported_mcs_set[1] = 0xFF;
3587*4882a593Smuzhiyun else
3588*4882a593Smuzhiyun sys_cfg->supported_mcs_set[1] = 0;
3589*4882a593Smuzhiyun }
3590*4882a593Smuzhiyun
3591*4882a593Smuzhiyun done:
3592*4882a593Smuzhiyun LEAVE();
3593*4882a593Smuzhiyun return status;
3594*4882a593Smuzhiyun }
3595*4882a593Smuzhiyun
3596*4882a593Smuzhiyun #define VHT_CAP_11AC_MASK 0x007fffff
3597*4882a593Smuzhiyun
3598*4882a593Smuzhiyun /**
3599*4882a593Smuzhiyun * @brief enable/disable 11AC
3600*4882a593Smuzhiyun *
3601*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
3602*4882a593Smuzhiyun * @param action MLAN_ACT_DISABLE or MLAN_ACT_ENABLE
3603*4882a593Smuzhiyun * @param vht20_40 Enable VHT 20 MHz or 40 MHz band
3604*4882a593Smuzhiyun * @param vhtcap_ie A pointer to vht capability IE
3605*4882a593Smuzhiyun *
3606*4882a593Smuzhiyun * @return 0--success, otherwise failure
3607*4882a593Smuzhiyun */
woal_uap_set_11ac_status(moal_private * priv,t_u8 action,t_u8 vht20_40,IEEEtypes_VHTCap_t * vhtcap_ie)3608*4882a593Smuzhiyun int woal_uap_set_11ac_status(moal_private *priv, t_u8 action, t_u8 vht20_40,
3609*4882a593Smuzhiyun IEEEtypes_VHTCap_t *vhtcap_ie)
3610*4882a593Smuzhiyun {
3611*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
3612*4882a593Smuzhiyun mlan_ds_11ac_cfg *cfg_11ac = NULL;
3613*4882a593Smuzhiyun mlan_fw_info fw_info;
3614*4882a593Smuzhiyun int ret = 0;
3615*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
3616*4882a593Smuzhiyun
3617*4882a593Smuzhiyun ENTER();
3618*4882a593Smuzhiyun
3619*4882a593Smuzhiyun memset(&fw_info, 0, sizeof(mlan_fw_info));
3620*4882a593Smuzhiyun woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
3621*4882a593Smuzhiyun
3622*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11ac_cfg));
3623*4882a593Smuzhiyun if (req == NULL) {
3624*4882a593Smuzhiyun ret = -ENOMEM;
3625*4882a593Smuzhiyun goto done;
3626*4882a593Smuzhiyun }
3627*4882a593Smuzhiyun
3628*4882a593Smuzhiyun cfg_11ac = (mlan_ds_11ac_cfg *)req->pbuf;
3629*4882a593Smuzhiyun cfg_11ac->sub_command = MLAN_OID_11AC_VHT_CFG;
3630*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_11AC_CFG;
3631*4882a593Smuzhiyun req->action = MLAN_ACT_SET;
3632*4882a593Smuzhiyun
3633*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.band = BAND_SELECT_A;
3634*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.txrx = MLAN_RADIO_TXRX;
3635*4882a593Smuzhiyun
3636*4882a593Smuzhiyun /*
3637*4882a593Smuzhiyun * p2p GO (negotiation or auto GO) cases, wpa_supplicant will download
3638*4882a593Smuzhiyun * invalid vht capability with value 0 in beacon parameters, so for p2p
3639*4882a593Smuzhiyun * GO case (vht_cap_info = 0), driver will use hardware 11ac vht
3640*4882a593Smuzhiyun * capability value instead of up layer value.
3641*4882a593Smuzhiyun */
3642*4882a593Smuzhiyun if (vhtcap_ie && vhtcap_ie->vht_cap.vht_cap_info != 0) {
3643*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.vht_cap_info =
3644*4882a593Smuzhiyun woal_le32_to_cpu(vhtcap_ie->vht_cap.vht_cap_info);
3645*4882a593Smuzhiyun /** todo mcs configuration */
3646*4882a593Smuzhiyun } else {
3647*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.vht_cap_info =
3648*4882a593Smuzhiyun fw_info.usr_dot_11ac_dev_cap_a;
3649*4882a593Smuzhiyun }
3650*4882a593Smuzhiyun if (action == MLAN_ACT_DISABLE) {
3651*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.bwcfg = MFALSE;
3652*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.vht_cap_info &= ~VHT_CAP_11AC_MASK;
3653*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.vht_rx_mcs =
3654*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.vht_tx_mcs = 0xffff;
3655*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.skip_usr_11ac_mcs_cfg = MTRUE;
3656*4882a593Smuzhiyun } else {
3657*4882a593Smuzhiyun if (vht20_40)
3658*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.bwcfg = MFALSE;
3659*4882a593Smuzhiyun else
3660*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.bwcfg = MTRUE;
3661*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.vht_cap_info &=
3662*4882a593Smuzhiyun ~DEFALUT_11AC_CAP_BEAMFORMING_RESET_MASK;
3663*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.vht_tx_mcs =
3664*4882a593Smuzhiyun fw_info.usr_dot_11ac_mcs_support >> 16;
3665*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.vht_rx_mcs =
3666*4882a593Smuzhiyun fw_info.usr_dot_11ac_mcs_support & 0xffff;
3667*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.skip_usr_11ac_mcs_cfg = MTRUE;
3668*4882a593Smuzhiyun }
3669*4882a593Smuzhiyun PRINTM(MCMND,
3670*4882a593Smuzhiyun "Uap:11ac=%d vht_cap_info=0x%x, vht_tx_mcs=0x%x, vht_rx_mcs=0x%x\n",
3671*4882a593Smuzhiyun action, cfg_11ac->param.vht_cfg.vht_cap_info,
3672*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.vht_tx_mcs,
3673*4882a593Smuzhiyun cfg_11ac->param.vht_cfg.vht_rx_mcs);
3674*4882a593Smuzhiyun
3675*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3676*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
3677*4882a593Smuzhiyun ret = -EFAULT;
3678*4882a593Smuzhiyun goto done;
3679*4882a593Smuzhiyun }
3680*4882a593Smuzhiyun done:
3681*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
3682*4882a593Smuzhiyun kfree(req);
3683*4882a593Smuzhiyun LEAVE();
3684*4882a593Smuzhiyun return ret;
3685*4882a593Smuzhiyun }
3686*4882a593Smuzhiyun
3687*4882a593Smuzhiyun /**
3688*4882a593Smuzhiyun * @brief Get/Set 11ax cfg
3689*4882a593Smuzhiyun *
3690*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
3691*4882a593Smuzhiyun * @param action MLAN_ACT_SET or MLAN_ACT_GET
3692*4882a593Smuzhiyun * @param he_cfg a pointer to mlan_ds_11ax_he_cfg
3693*4882a593Smuzhiyun *
3694*4882a593Smuzhiyun * @return 0--success, otherwise failure
3695*4882a593Smuzhiyun */
woal_11ax_cfg(moal_private * priv,t_u8 action,mlan_ds_11ax_he_cfg * he_cfg)3696*4882a593Smuzhiyun int woal_11ax_cfg(moal_private *priv, t_u8 action, mlan_ds_11ax_he_cfg *he_cfg)
3697*4882a593Smuzhiyun {
3698*4882a593Smuzhiyun int ret = 0;
3699*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
3700*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
3701*4882a593Smuzhiyun mlan_ds_11ax_cfg *cfg_11ax = NULL;
3702*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11ax_cfg));
3703*4882a593Smuzhiyun if (req == NULL) {
3704*4882a593Smuzhiyun ret = -ENOMEM;
3705*4882a593Smuzhiyun goto done;
3706*4882a593Smuzhiyun }
3707*4882a593Smuzhiyun cfg_11ax = (mlan_ds_11ax_cfg *)req->pbuf;
3708*4882a593Smuzhiyun cfg_11ax->sub_command = MLAN_OID_11AX_HE_CFG;
3709*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_11AX_CFG;
3710*4882a593Smuzhiyun req->action = action;
3711*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &cfg_11ax->param.he_cfg, he_cfg,
3712*4882a593Smuzhiyun sizeof(mlan_ds_11ax_he_cfg),
3713*4882a593Smuzhiyun sizeof(mlan_ds_11ax_he_cfg));
3714*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3715*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
3716*4882a593Smuzhiyun ret = -EFAULT;
3717*4882a593Smuzhiyun goto done;
3718*4882a593Smuzhiyun }
3719*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, he_cfg, &cfg_11ax->param.he_cfg,
3720*4882a593Smuzhiyun sizeof(mlan_ds_11ax_he_cfg),
3721*4882a593Smuzhiyun sizeof(mlan_ds_11ax_he_cfg));
3722*4882a593Smuzhiyun done:
3723*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
3724*4882a593Smuzhiyun kfree(req);
3725*4882a593Smuzhiyun LEAVE();
3726*4882a593Smuzhiyun return ret;
3727*4882a593Smuzhiyun }
3728*4882a593Smuzhiyun
3729*4882a593Smuzhiyun /**
3730*4882a593Smuzhiyun * @brief enable/disable 11AX
3731*4882a593Smuzhiyun *
3732*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
3733*4882a593Smuzhiyun * @param action MLAN_ACT_DISABLE or MLAN_ACT_ENABLE
3734*4882a593Smuzhiyun * @param band band config
3735*4882a593Smuzhiyun * @param hecap_ie
3736*4882a593Smuzhiyun *
3737*4882a593Smuzhiyun * @return 0--success, otherwise failure
3738*4882a593Smuzhiyun */
woal_uap_set_11ax_status(moal_private * priv,t_u8 action,t_u8 band,IEEEtypes_HECap_t * hecap_ie)3739*4882a593Smuzhiyun int woal_uap_set_11ax_status(moal_private *priv, t_u8 action, t_u8 band,
3740*4882a593Smuzhiyun IEEEtypes_HECap_t *hecap_ie)
3741*4882a593Smuzhiyun {
3742*4882a593Smuzhiyun mlan_fw_info fw_info;
3743*4882a593Smuzhiyun int ret = 0;
3744*4882a593Smuzhiyun mlan_ds_11ax_he_cfg he_cfg;
3745*4882a593Smuzhiyun ENTER();
3746*4882a593Smuzhiyun
3747*4882a593Smuzhiyun memset(&fw_info, 0, sizeof(mlan_fw_info));
3748*4882a593Smuzhiyun woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
3749*4882a593Smuzhiyun if ((band == BAND_5GHZ && !(fw_info.fw_bands & BAND_AAX)) ||
3750*4882a593Smuzhiyun (band == BAND_2GHZ && !(fw_info.fw_bands & BAND_GAX))) {
3751*4882a593Smuzhiyun PRINTM(MERROR, "fw doesn't support 11ax\n");
3752*4882a593Smuzhiyun ret = -EFAULT;
3753*4882a593Smuzhiyun goto done;
3754*4882a593Smuzhiyun }
3755*4882a593Smuzhiyun memset(&he_cfg, 0, sizeof(he_cfg));
3756*4882a593Smuzhiyun if (band == BAND_5GHZ)
3757*4882a593Smuzhiyun he_cfg.band = MBIT(1);
3758*4882a593Smuzhiyun else if (band == BAND_2GHZ)
3759*4882a593Smuzhiyun he_cfg.band = MBIT(0);
3760*4882a593Smuzhiyun else {
3761*4882a593Smuzhiyun PRINTM(MERROR, "Invalid band!\n");
3762*4882a593Smuzhiyun ret = -EFAULT;
3763*4882a593Smuzhiyun goto done;
3764*4882a593Smuzhiyun }
3765*4882a593Smuzhiyun if (woal_11ax_cfg(priv, MLAN_ACT_GET, &he_cfg)) {
3766*4882a593Smuzhiyun PRINTM(MERROR, "Fail to get 11ax cfg!\n");
3767*4882a593Smuzhiyun ret = -EFAULT;
3768*4882a593Smuzhiyun goto done;
3769*4882a593Smuzhiyun }
3770*4882a593Smuzhiyun if (hecap_ie) {
3771*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "hecap_ie", (t_u8 *)hecap_ie,
3772*4882a593Smuzhiyun hecap_ie->ieee_hdr.len +
3773*4882a593Smuzhiyun sizeof(IEEEtypes_Header_t));
3774*4882a593Smuzhiyun he_cfg.he_cap.id = hecap_ie->ieee_hdr.element_id;
3775*4882a593Smuzhiyun he_cfg.he_cap.len = hecap_ie->ieee_hdr.len;
3776*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &he_cfg.he_cap.ext_id,
3777*4882a593Smuzhiyun &hecap_ie->ext_id, he_cfg.he_cap.len,
3778*4882a593Smuzhiyun he_cfg.he_cap.len);
3779*4882a593Smuzhiyun }
3780*4882a593Smuzhiyun #define HE_MAC_CAP_TWT_REQ_SUPPORT MBIT(1)
3781*4882a593Smuzhiyun /* uap mode clear TWT request bit */
3782*4882a593Smuzhiyun he_cfg.he_cap.he_mac_cap[0] &= ~HE_MAC_CAP_TWT_REQ_SUPPORT;
3783*4882a593Smuzhiyun
3784*4882a593Smuzhiyun if (action == MLAN_ACT_DISABLE) {
3785*4882a593Smuzhiyun if (he_cfg.he_cap.len &&
3786*4882a593Smuzhiyun (he_cfg.he_cap.ext_id == HE_CAPABILITY)) {
3787*4882a593Smuzhiyun memset(he_cfg.he_cap.he_txrx_mcs_support, 0xff,
3788*4882a593Smuzhiyun sizeof(he_cfg.he_cap.he_txrx_mcs_support));
3789*4882a593Smuzhiyun } else {
3790*4882a593Smuzhiyun PRINTM(MCMND, "11ax already disabled\n");
3791*4882a593Smuzhiyun goto done;
3792*4882a593Smuzhiyun }
3793*4882a593Smuzhiyun }
3794*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "HE_CFG ", (t_u8 *)&he_cfg, sizeof(he_cfg));
3795*4882a593Smuzhiyun ret = woal_11ax_cfg(priv, MLAN_ACT_SET, &he_cfg);
3796*4882a593Smuzhiyun done:
3797*4882a593Smuzhiyun LEAVE();
3798*4882a593Smuzhiyun return ret;
3799*4882a593Smuzhiyun }
3800*4882a593Smuzhiyun
3801*4882a593Smuzhiyun /**
3802*4882a593Smuzhiyun * @brief Parse AP configuration from ASCII string
3803*4882a593Smuzhiyun *
3804*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
3805*4882a593Smuzhiyun * @param ap_cfg A pointer to mlan_uap_bss_param structure
3806*4882a593Smuzhiyun * @param buf A pointer to user data
3807*4882a593Smuzhiyun *
3808*4882a593Smuzhiyun * @return 0 --success, otherwise fail
3809*4882a593Smuzhiyun */
woal_uap_ap_cfg_parse_data(moal_private * priv,mlan_uap_bss_param * ap_cfg,char * buf)3810*4882a593Smuzhiyun static int woal_uap_ap_cfg_parse_data(moal_private *priv,
3811*4882a593Smuzhiyun mlan_uap_bss_param *ap_cfg, char *buf)
3812*4882a593Smuzhiyun {
3813*4882a593Smuzhiyun int ret = 0, atoi_ret;
3814*4882a593Smuzhiyun int set_sec = 0, set_key = 0, set_chan = 0;
3815*4882a593Smuzhiyun int set_preamble = 0, set_scb = 0, set_ssid = 0;
3816*4882a593Smuzhiyun char *begin = buf, *value = NULL, *opt = NULL;
3817*4882a593Smuzhiyun
3818*4882a593Smuzhiyun ENTER();
3819*4882a593Smuzhiyun
3820*4882a593Smuzhiyun while (begin) {
3821*4882a593Smuzhiyun value = woal_strsep(&begin, ',', '/');
3822*4882a593Smuzhiyun opt = woal_strsep(&value, '=', '/');
3823*4882a593Smuzhiyun if (opt && !strncmp(opt, "END", strlen("END"))) {
3824*4882a593Smuzhiyun if (!ap_cfg->ssid.ssid_len) {
3825*4882a593Smuzhiyun PRINTM(MERROR,
3826*4882a593Smuzhiyun "Minimum option required is SSID\n");
3827*4882a593Smuzhiyun ret = -EINVAL;
3828*4882a593Smuzhiyun goto done;
3829*4882a593Smuzhiyun }
3830*4882a593Smuzhiyun PRINTM(MINFO, "Parsing terminated by string END\n");
3831*4882a593Smuzhiyun break;
3832*4882a593Smuzhiyun }
3833*4882a593Smuzhiyun if (!opt || !value || !value[0]) {
3834*4882a593Smuzhiyun PRINTM(MERROR, "Invalid option\n");
3835*4882a593Smuzhiyun ret = -EINVAL;
3836*4882a593Smuzhiyun goto done;
3837*4882a593Smuzhiyun } else if (!strncmp(opt, "ASCII_CMD", strlen("ASCII_CMD"))) {
3838*4882a593Smuzhiyun if (strncmp(value, "AP_CFG", strlen("AP_CFG"))) {
3839*4882a593Smuzhiyun PRINTM(MERROR,
3840*4882a593Smuzhiyun "ASCII_CMD: %s not matched with AP_CFG\n",
3841*4882a593Smuzhiyun value);
3842*4882a593Smuzhiyun ret = -EFAULT;
3843*4882a593Smuzhiyun goto done;
3844*4882a593Smuzhiyun }
3845*4882a593Smuzhiyun value = woal_strsep(&begin, ',', '/');
3846*4882a593Smuzhiyun opt = woal_strsep(&value, '=', '/');
3847*4882a593Smuzhiyun if (!opt || !value || !value[0]) {
3848*4882a593Smuzhiyun PRINTM(MERROR,
3849*4882a593Smuzhiyun "Minimum option required is SSID\n");
3850*4882a593Smuzhiyun ret = -EINVAL;
3851*4882a593Smuzhiyun goto done;
3852*4882a593Smuzhiyun } else if (!strncmp(opt, "SSID", strlen("SSID"))) {
3853*4882a593Smuzhiyun if (set_ssid) {
3854*4882a593Smuzhiyun PRINTM(MWARN,
3855*4882a593Smuzhiyun "Skipping SSID, found again!\n");
3856*4882a593Smuzhiyun continue;
3857*4882a593Smuzhiyun }
3858*4882a593Smuzhiyun if (strlen(value) >= MLAN_MAX_SSID_LENGTH) {
3859*4882a593Smuzhiyun PRINTM(MERROR,
3860*4882a593Smuzhiyun "SSID length exceeds max length\n");
3861*4882a593Smuzhiyun ret = -EFAULT;
3862*4882a593Smuzhiyun goto done;
3863*4882a593Smuzhiyun }
3864*4882a593Smuzhiyun ap_cfg->ssid.ssid_len = strlen(value);
3865*4882a593Smuzhiyun strncpy((char *)ap_cfg->ssid.ssid, value,
3866*4882a593Smuzhiyun MIN(MLAN_MAX_SSID_LENGTH - 1,
3867*4882a593Smuzhiyun strlen(value)));
3868*4882a593Smuzhiyun PRINTM(MINFO, "ssid=%s, len=%d\n",
3869*4882a593Smuzhiyun ap_cfg->ssid.ssid,
3870*4882a593Smuzhiyun (int)ap_cfg->ssid.ssid_len);
3871*4882a593Smuzhiyun set_ssid = 1;
3872*4882a593Smuzhiyun } else {
3873*4882a593Smuzhiyun PRINTM(MERROR,
3874*4882a593Smuzhiyun "AP_CFG: Invalid option %s, expect SSID\n",
3875*4882a593Smuzhiyun opt);
3876*4882a593Smuzhiyun ret = -EINVAL;
3877*4882a593Smuzhiyun goto done;
3878*4882a593Smuzhiyun }
3879*4882a593Smuzhiyun } else if (!strncmp(opt, "SEC", strlen("SEC"))) {
3880*4882a593Smuzhiyun if (set_sec) {
3881*4882a593Smuzhiyun PRINTM(MWARN, "Skipping SEC, found again!\n");
3882*4882a593Smuzhiyun continue;
3883*4882a593Smuzhiyun }
3884*4882a593Smuzhiyun if (!strnicmp(value, "open", strlen("open"))) {
3885*4882a593Smuzhiyun ap_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
3886*4882a593Smuzhiyun if (set_key)
3887*4882a593Smuzhiyun ap_cfg->wpa_cfg.length = 0;
3888*4882a593Smuzhiyun ap_cfg->key_mgmt = KEY_MGMT_NONE;
3889*4882a593Smuzhiyun ap_cfg->protocol = PROTOCOL_NO_SECURITY;
3890*4882a593Smuzhiyun } else if (!strnicmp(value, "wpa2-psk",
3891*4882a593Smuzhiyun strlen("wpa2-psk"))) {
3892*4882a593Smuzhiyun ap_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
3893*4882a593Smuzhiyun ap_cfg->protocol = PROTOCOL_WPA2;
3894*4882a593Smuzhiyun ap_cfg->key_mgmt = KEY_MGMT_PSK;
3895*4882a593Smuzhiyun ap_cfg->wpa_cfg.pairwise_cipher_wpa =
3896*4882a593Smuzhiyun CIPHER_AES_CCMP;
3897*4882a593Smuzhiyun ap_cfg->wpa_cfg.pairwise_cipher_wpa2 =
3898*4882a593Smuzhiyun CIPHER_AES_CCMP;
3899*4882a593Smuzhiyun ap_cfg->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
3900*4882a593Smuzhiyun } else if (!strnicmp(value, "wpa-psk",
3901*4882a593Smuzhiyun strlen("wpa-psk"))) {
3902*4882a593Smuzhiyun ap_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
3903*4882a593Smuzhiyun ap_cfg->protocol = PROTOCOL_WPA;
3904*4882a593Smuzhiyun ap_cfg->key_mgmt = KEY_MGMT_PSK;
3905*4882a593Smuzhiyun ap_cfg->wpa_cfg.pairwise_cipher_wpa =
3906*4882a593Smuzhiyun CIPHER_TKIP;
3907*4882a593Smuzhiyun ap_cfg->wpa_cfg.group_cipher = CIPHER_TKIP;
3908*4882a593Smuzhiyun } else if (!strnicmp(value, "wep128",
3909*4882a593Smuzhiyun strlen("wep128"))) {
3910*4882a593Smuzhiyun ap_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
3911*4882a593Smuzhiyun if (set_key)
3912*4882a593Smuzhiyun ap_cfg->wpa_cfg.length = 0;
3913*4882a593Smuzhiyun ap_cfg->key_mgmt = KEY_MGMT_NONE;
3914*4882a593Smuzhiyun ap_cfg->protocol = PROTOCOL_STATIC_WEP;
3915*4882a593Smuzhiyun } else {
3916*4882a593Smuzhiyun PRINTM(MERROR,
3917*4882a593Smuzhiyun "AP_CFG: Invalid value=%s for %s\n",
3918*4882a593Smuzhiyun value, opt);
3919*4882a593Smuzhiyun ret = -EFAULT;
3920*4882a593Smuzhiyun goto done;
3921*4882a593Smuzhiyun }
3922*4882a593Smuzhiyun set_sec = 1;
3923*4882a593Smuzhiyun } else if (!strncmp(opt, "KEY", strlen("KEY"))) {
3924*4882a593Smuzhiyun if (set_key) {
3925*4882a593Smuzhiyun PRINTM(MWARN, "Skipping KEY, found again!\n");
3926*4882a593Smuzhiyun continue;
3927*4882a593Smuzhiyun }
3928*4882a593Smuzhiyun if (set_sec &&
3929*4882a593Smuzhiyun ap_cfg->protocol == PROTOCOL_STATIC_WEP) {
3930*4882a593Smuzhiyun if (strlen(value) != MAX_WEP_KEY_SIZE) {
3931*4882a593Smuzhiyun PRINTM(MERROR,
3932*4882a593Smuzhiyun "Invalid WEP KEY length\n");
3933*4882a593Smuzhiyun ret = -EFAULT;
3934*4882a593Smuzhiyun goto done;
3935*4882a593Smuzhiyun }
3936*4882a593Smuzhiyun ap_cfg->wep_cfg.key0.key_index = 0;
3937*4882a593Smuzhiyun ap_cfg->wep_cfg.key0.is_default = 1;
3938*4882a593Smuzhiyun ap_cfg->wep_cfg.key0.length = strlen(value);
3939*4882a593Smuzhiyun moal_memcpy_ext(
3940*4882a593Smuzhiyun priv->phandle, ap_cfg->wep_cfg.key0.key,
3941*4882a593Smuzhiyun value, strlen(value),
3942*4882a593Smuzhiyun sizeof(ap_cfg->wep_cfg.key0.key));
3943*4882a593Smuzhiyun set_key = 1;
3944*4882a593Smuzhiyun continue;
3945*4882a593Smuzhiyun }
3946*4882a593Smuzhiyun if (set_sec && ap_cfg->protocol != PROTOCOL_WPA2 &&
3947*4882a593Smuzhiyun ap_cfg->protocol != PROTOCOL_WPA) {
3948*4882a593Smuzhiyun PRINTM(MWARN,
3949*4882a593Smuzhiyun "Warning! No KEY for open mode\n");
3950*4882a593Smuzhiyun set_key = 1;
3951*4882a593Smuzhiyun continue;
3952*4882a593Smuzhiyun }
3953*4882a593Smuzhiyun if (strlen(value) < MLAN_MIN_PASSPHRASE_LENGTH ||
3954*4882a593Smuzhiyun strlen(value) > MLAN_PMK_HEXSTR_LENGTH) {
3955*4882a593Smuzhiyun PRINTM(MERROR, "Invalid PSK/PMK length\n");
3956*4882a593Smuzhiyun ret = -EINVAL;
3957*4882a593Smuzhiyun goto done;
3958*4882a593Smuzhiyun }
3959*4882a593Smuzhiyun ap_cfg->wpa_cfg.length = strlen(value);
3960*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle,
3961*4882a593Smuzhiyun ap_cfg->wpa_cfg.passphrase, value,
3962*4882a593Smuzhiyun strlen(value),
3963*4882a593Smuzhiyun sizeof(ap_cfg->wpa_cfg.passphrase));
3964*4882a593Smuzhiyun set_key = 1;
3965*4882a593Smuzhiyun } else if (!strncmp(opt, "CHANNEL", strlen("CHANNEL"))) {
3966*4882a593Smuzhiyun if (set_chan) {
3967*4882a593Smuzhiyun PRINTM(MWARN,
3968*4882a593Smuzhiyun "Skipping CHANNEL, found again!\n");
3969*4882a593Smuzhiyun continue;
3970*4882a593Smuzhiyun }
3971*4882a593Smuzhiyun if (woal_atoi(&atoi_ret, value)) {
3972*4882a593Smuzhiyun ret = -EINVAL;
3973*4882a593Smuzhiyun goto done;
3974*4882a593Smuzhiyun }
3975*4882a593Smuzhiyun if (atoi_ret < 1 || atoi_ret > MLAN_MAX_CHANNEL) {
3976*4882a593Smuzhiyun PRINTM(MERROR,
3977*4882a593Smuzhiyun "AP_CFG: Channel must be between 1 and %d"
3978*4882a593Smuzhiyun "(both included)\n",
3979*4882a593Smuzhiyun MLAN_MAX_CHANNEL);
3980*4882a593Smuzhiyun ret = -EINVAL;
3981*4882a593Smuzhiyun goto done;
3982*4882a593Smuzhiyun }
3983*4882a593Smuzhiyun ap_cfg->channel = atoi_ret;
3984*4882a593Smuzhiyun set_chan = 1;
3985*4882a593Smuzhiyun } else if (!strncmp(opt, "PREAMBLE", strlen("PREAMBLE"))) {
3986*4882a593Smuzhiyun if (set_preamble) {
3987*4882a593Smuzhiyun PRINTM(MWARN,
3988*4882a593Smuzhiyun "Skipping PREAMBLE, found again!\n");
3989*4882a593Smuzhiyun continue;
3990*4882a593Smuzhiyun }
3991*4882a593Smuzhiyun if (woal_atoi(&atoi_ret, value)) {
3992*4882a593Smuzhiyun ret = -EINVAL;
3993*4882a593Smuzhiyun goto done;
3994*4882a593Smuzhiyun }
3995*4882a593Smuzhiyun /* This is a READ only value from FW, so we
3996*4882a593Smuzhiyun * can not set this and pass it successfully */
3997*4882a593Smuzhiyun set_preamble = 1;
3998*4882a593Smuzhiyun } else if (!strncmp(opt, "MAX_SCB", strlen("MAX_SCB"))) {
3999*4882a593Smuzhiyun if (set_scb) {
4000*4882a593Smuzhiyun PRINTM(MWARN,
4001*4882a593Smuzhiyun "Skipping MAX_SCB, found again!\n");
4002*4882a593Smuzhiyun continue;
4003*4882a593Smuzhiyun }
4004*4882a593Smuzhiyun if (woal_atoi(&atoi_ret, value)) {
4005*4882a593Smuzhiyun ret = -EINVAL;
4006*4882a593Smuzhiyun goto done;
4007*4882a593Smuzhiyun }
4008*4882a593Smuzhiyun if (atoi_ret < 1 || atoi_ret > MAX_STA_COUNT) {
4009*4882a593Smuzhiyun PRINTM(MERROR,
4010*4882a593Smuzhiyun "AP_CFG: MAX_SCB must be between 1 to %d "
4011*4882a593Smuzhiyun "(both included)\n",
4012*4882a593Smuzhiyun MAX_STA_COUNT);
4013*4882a593Smuzhiyun ret = -EINVAL;
4014*4882a593Smuzhiyun goto done;
4015*4882a593Smuzhiyun }
4016*4882a593Smuzhiyun ap_cfg->max_sta_count = (t_u16)atoi_ret;
4017*4882a593Smuzhiyun set_scb = 1;
4018*4882a593Smuzhiyun } else {
4019*4882a593Smuzhiyun PRINTM(MERROR, "Invalid option %s\n", opt);
4020*4882a593Smuzhiyun ret = -EINVAL;
4021*4882a593Smuzhiyun goto done;
4022*4882a593Smuzhiyun }
4023*4882a593Smuzhiyun }
4024*4882a593Smuzhiyun
4025*4882a593Smuzhiyun done:
4026*4882a593Smuzhiyun LEAVE();
4027*4882a593Smuzhiyun return ret;
4028*4882a593Smuzhiyun }
4029*4882a593Smuzhiyun
4030*4882a593Smuzhiyun /**
4031*4882a593Smuzhiyun * @brief Set AP configuration
4032*4882a593Smuzhiyun *
4033*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
4034*4882a593Smuzhiyun * @param data A pointer to user data
4035*4882a593Smuzhiyun * @param len Length of buf
4036*4882a593Smuzhiyun *
4037*4882a593Smuzhiyun * @return 0 --success, otherwise fail
4038*4882a593Smuzhiyun */
woal_uap_set_ap_cfg(moal_private * priv,t_u8 * data,int len)4039*4882a593Smuzhiyun int woal_uap_set_ap_cfg(moal_private *priv, t_u8 *data, int len)
4040*4882a593Smuzhiyun {
4041*4882a593Smuzhiyun int ret = 0;
4042*4882a593Smuzhiyun static char buf[MAX_BUF_LEN];
4043*4882a593Smuzhiyun mlan_uap_bss_param *sys_config = NULL;
4044*4882a593Smuzhiyun int restart = 0;
4045*4882a593Smuzhiyun
4046*4882a593Smuzhiyun ENTER();
4047*4882a593Smuzhiyun
4048*4882a593Smuzhiyun #define MIN_AP_CFG_CMD_LEN 16 /* strlen("ASCII_CMD=AP_CFG") */
4049*4882a593Smuzhiyun if ((len - 1) <= MIN_AP_CFG_CMD_LEN) {
4050*4882a593Smuzhiyun PRINTM(MERROR, "Invalid length of command\n");
4051*4882a593Smuzhiyun ret = -EINVAL;
4052*4882a593Smuzhiyun goto done;
4053*4882a593Smuzhiyun }
4054*4882a593Smuzhiyun sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
4055*4882a593Smuzhiyun if (!sys_config) {
4056*4882a593Smuzhiyun PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
4057*4882a593Smuzhiyun ret = -EFAULT;
4058*4882a593Smuzhiyun goto done;
4059*4882a593Smuzhiyun }
4060*4882a593Smuzhiyun memset(buf, 0, MAX_BUF_LEN);
4061*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, buf, data, len, sizeof(buf) - 1);
4062*4882a593Smuzhiyun
4063*4882a593Smuzhiyun /* Initialize the uap bss values which are uploaded from firmware */
4064*4882a593Smuzhiyun woal_uap_get_bss_param(priv, sys_config, MOAL_IOCTL_WAIT);
4065*4882a593Smuzhiyun
4066*4882a593Smuzhiyun /* Setting the default values */
4067*4882a593Smuzhiyun sys_config->channel = 6;
4068*4882a593Smuzhiyun sys_config->preamble_type = 0;
4069*4882a593Smuzhiyun
4070*4882a593Smuzhiyun ret = woal_uap_ap_cfg_parse_data(priv, sys_config, buf);
4071*4882a593Smuzhiyun if (ret)
4072*4882a593Smuzhiyun goto done;
4073*4882a593Smuzhiyun
4074*4882a593Smuzhiyun /* If BSS already started stop it first and restart
4075*4882a593Smuzhiyun * after changing the setting */
4076*4882a593Smuzhiyun if (priv->bss_started == MTRUE) {
4077*4882a593Smuzhiyun ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP);
4078*4882a593Smuzhiyun if (ret)
4079*4882a593Smuzhiyun goto done;
4080*4882a593Smuzhiyun restart = 1;
4081*4882a593Smuzhiyun }
4082*4882a593Smuzhiyun
4083*4882a593Smuzhiyun /* If the security mode is configured as WEP or WPA-PSK,
4084*4882a593Smuzhiyun * it will disable 11n automatically, and if configured as
4085*4882a593Smuzhiyun * open(off) or wpa2-psk, it will automatically enable 11n */
4086*4882a593Smuzhiyun if ((sys_config->protocol == PROTOCOL_STATIC_WEP) ||
4087*4882a593Smuzhiyun (sys_config->protocol == PROTOCOL_WPA)) {
4088*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
4089*4882a593Smuzhiyun woal_uap_set_11n_status(priv, sys_config,
4090*4882a593Smuzhiyun MLAN_ACT_DISABLE)) {
4091*4882a593Smuzhiyun ret = -EFAULT;
4092*4882a593Smuzhiyun goto done;
4093*4882a593Smuzhiyun }
4094*4882a593Smuzhiyun } else {
4095*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
4096*4882a593Smuzhiyun woal_uap_set_11n_status(priv, sys_config,
4097*4882a593Smuzhiyun MLAN_ACT_ENABLE)) {
4098*4882a593Smuzhiyun ret = -EFAULT;
4099*4882a593Smuzhiyun goto done;
4100*4882a593Smuzhiyun }
4101*4882a593Smuzhiyun }
4102*4882a593Smuzhiyun
4103*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET,
4104*4882a593Smuzhiyun MOAL_IOCTL_WAIT,
4105*4882a593Smuzhiyun sys_config)) {
4106*4882a593Smuzhiyun ret = -EFAULT;
4107*4882a593Smuzhiyun goto done;
4108*4882a593Smuzhiyun }
4109*4882a593Smuzhiyun
4110*4882a593Smuzhiyun /* Start the BSS after successful configuration */
4111*4882a593Smuzhiyun if (restart)
4112*4882a593Smuzhiyun ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START);
4113*4882a593Smuzhiyun
4114*4882a593Smuzhiyun done:
4115*4882a593Smuzhiyun kfree(sys_config);
4116*4882a593Smuzhiyun LEAVE();
4117*4882a593Smuzhiyun return ret;
4118*4882a593Smuzhiyun }
4119*4882a593Smuzhiyun
4120*4882a593Smuzhiyun /**
4121*4882a593Smuzhiyun * @brief Set/Get ap scan channel list
4122*4882a593Smuzhiyun *
4123*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
4124*4882a593Smuzhiyun * @param action MLAN_ACT_SET or MLAN_ACT_GET
4125*4882a593Smuzhiyun * @param scan_channels A pointer to mlan_uap_scan_channels structure
4126*4882a593Smuzhiyun *
4127*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4128*4882a593Smuzhiyun */
4129*4882a593Smuzhiyun static mlan_status
woal_set_get_ap_scan_channels(moal_private * priv,t_u16 action,mlan_uap_scan_channels * scan_channels)4130*4882a593Smuzhiyun woal_set_get_ap_scan_channels(moal_private *priv, t_u16 action,
4131*4882a593Smuzhiyun mlan_uap_scan_channels *scan_channels)
4132*4882a593Smuzhiyun {
4133*4882a593Smuzhiyun mlan_status ret = MLAN_STATUS_SUCCESS;
4134*4882a593Smuzhiyun mlan_ds_bss *bss = NULL;
4135*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
4136*4882a593Smuzhiyun
4137*4882a593Smuzhiyun ENTER();
4138*4882a593Smuzhiyun
4139*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4140*4882a593Smuzhiyun if (req == NULL) {
4141*4882a593Smuzhiyun ret = MLAN_STATUS_FAILURE;
4142*4882a593Smuzhiyun goto done;
4143*4882a593Smuzhiyun }
4144*4882a593Smuzhiyun
4145*4882a593Smuzhiyun bss = (mlan_ds_bss *)req->pbuf;
4146*4882a593Smuzhiyun bss->sub_command = MLAN_OID_UAP_SCAN_CHANNELS;
4147*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_BSS;
4148*4882a593Smuzhiyun req->action = action;
4149*4882a593Smuzhiyun
4150*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &bss->param.ap_scan_channels,
4151*4882a593Smuzhiyun scan_channels, sizeof(mlan_uap_scan_channels),
4152*4882a593Smuzhiyun sizeof(bss->param.ap_scan_channels));
4153*4882a593Smuzhiyun
4154*4882a593Smuzhiyun ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4155*4882a593Smuzhiyun if (ret != MLAN_STATUS_SUCCESS)
4156*4882a593Smuzhiyun goto done;
4157*4882a593Smuzhiyun if (action == MLAN_ACT_GET)
4158*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, scan_channels,
4159*4882a593Smuzhiyun &bss->param.ap_scan_channels,
4160*4882a593Smuzhiyun sizeof(mlan_uap_scan_channels),
4161*4882a593Smuzhiyun sizeof(mlan_uap_scan_channels));
4162*4882a593Smuzhiyun
4163*4882a593Smuzhiyun done:
4164*4882a593Smuzhiyun if (ret != MLAN_STATUS_PENDING)
4165*4882a593Smuzhiyun kfree(req);
4166*4882a593Smuzhiyun LEAVE();
4167*4882a593Smuzhiyun return ret;
4168*4882a593Smuzhiyun }
4169*4882a593Smuzhiyun
4170*4882a593Smuzhiyun /**
4171*4882a593Smuzhiyun * @brief Set/Get uap channel
4172*4882a593Smuzhiyun *
4173*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
4174*4882a593Smuzhiyun * @param action MLAN_ACT_SET or MLAN_ACT_GET
4175*4882a593Smuzhiyun * @param wait_option wait option
4176*4882a593Smuzhiyun * @param uap_channel A pointer to mlan_uap_channel structure
4177*4882a593Smuzhiyun *
4178*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4179*4882a593Smuzhiyun */
woal_set_get_ap_channel(moal_private * priv,t_u16 action,t_u8 wait_option,chan_band_info * uap_channel)4180*4882a593Smuzhiyun mlan_status woal_set_get_ap_channel(moal_private *priv, t_u16 action,
4181*4882a593Smuzhiyun t_u8 wait_option,
4182*4882a593Smuzhiyun chan_band_info *uap_channel)
4183*4882a593Smuzhiyun {
4184*4882a593Smuzhiyun mlan_status ret = MLAN_STATUS_SUCCESS;
4185*4882a593Smuzhiyun mlan_ds_bss *bss = NULL;
4186*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
4187*4882a593Smuzhiyun
4188*4882a593Smuzhiyun ENTER();
4189*4882a593Smuzhiyun
4190*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4191*4882a593Smuzhiyun if (req == NULL) {
4192*4882a593Smuzhiyun ret = MLAN_STATUS_FAILURE;
4193*4882a593Smuzhiyun goto done;
4194*4882a593Smuzhiyun }
4195*4882a593Smuzhiyun
4196*4882a593Smuzhiyun bss = (mlan_ds_bss *)req->pbuf;
4197*4882a593Smuzhiyun bss->sub_command = MLAN_OID_UAP_CHANNEL;
4198*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_BSS;
4199*4882a593Smuzhiyun req->action = action;
4200*4882a593Smuzhiyun
4201*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &bss->param.ap_channel, uap_channel,
4202*4882a593Smuzhiyun sizeof(chan_band_info), sizeof(bss->param.ap_channel));
4203*4882a593Smuzhiyun ret = woal_request_ioctl(priv, req, wait_option);
4204*4882a593Smuzhiyun if (ret != MLAN_STATUS_SUCCESS)
4205*4882a593Smuzhiyun goto done;
4206*4882a593Smuzhiyun if (action == MLAN_ACT_GET)
4207*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, uap_channel,
4208*4882a593Smuzhiyun &bss->param.ap_channel, sizeof(chan_band_info),
4209*4882a593Smuzhiyun sizeof(chan_band_info));
4210*4882a593Smuzhiyun
4211*4882a593Smuzhiyun done:
4212*4882a593Smuzhiyun if (ret != MLAN_STATUS_PENDING)
4213*4882a593Smuzhiyun kfree(req);
4214*4882a593Smuzhiyun LEAVE();
4215*4882a593Smuzhiyun return ret;
4216*4882a593Smuzhiyun }
4217*4882a593Smuzhiyun
4218*4882a593Smuzhiyun /**
4219*4882a593Smuzhiyun * @brief start ACS scan
4220*4882a593Smuzhiyun *
4221*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
4222*4882a593Smuzhiyun * @param action MLAN_ACT_SET or MLAN_ACT_GET
4223*4882a593Smuzhiyun *
4224*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4225*4882a593Smuzhiyun */
woal_start_acs_scan(moal_private * priv)4226*4882a593Smuzhiyun static mlan_status woal_start_acs_scan(moal_private *priv)
4227*4882a593Smuzhiyun {
4228*4882a593Smuzhiyun mlan_status ret = MLAN_STATUS_SUCCESS;
4229*4882a593Smuzhiyun mlan_ds_bss *bss = NULL;
4230*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
4231*4882a593Smuzhiyun
4232*4882a593Smuzhiyun ENTER();
4233*4882a593Smuzhiyun
4234*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4235*4882a593Smuzhiyun if (req == NULL) {
4236*4882a593Smuzhiyun ret = MLAN_STATUS_FAILURE;
4237*4882a593Smuzhiyun goto done;
4238*4882a593Smuzhiyun }
4239*4882a593Smuzhiyun
4240*4882a593Smuzhiyun bss = (mlan_ds_bss *)req->pbuf;
4241*4882a593Smuzhiyun bss->sub_command = MLAN_OID_UAP_ACS_SCAN;
4242*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_BSS;
4243*4882a593Smuzhiyun req->action = MLAN_ACT_SET;
4244*4882a593Smuzhiyun
4245*4882a593Smuzhiyun ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4246*4882a593Smuzhiyun if (ret != MLAN_STATUS_SUCCESS)
4247*4882a593Smuzhiyun goto done;
4248*4882a593Smuzhiyun PRINTM(MIOCTL,
4249*4882a593Smuzhiyun "ACS scan done: bandcfg:[chanBand=0x%x chanWidth=0x%x chan2Offset=0x%x scanMode=0x%x], channel=%d\n",
4250*4882a593Smuzhiyun bss->param.ap_acs_scan.bandcfg.chanBand,
4251*4882a593Smuzhiyun bss->param.ap_acs_scan.bandcfg.chanWidth,
4252*4882a593Smuzhiyun bss->param.ap_acs_scan.bandcfg.chan2Offset,
4253*4882a593Smuzhiyun bss->param.ap_acs_scan.bandcfg.scanMode,
4254*4882a593Smuzhiyun bss->param.ap_acs_scan.chan);
4255*4882a593Smuzhiyun done:
4256*4882a593Smuzhiyun if (ret != MLAN_STATUS_PENDING)
4257*4882a593Smuzhiyun kfree(req);
4258*4882a593Smuzhiyun LEAVE();
4259*4882a593Smuzhiyun return ret;
4260*4882a593Smuzhiyun }
4261*4882a593Smuzhiyun
4262*4882a593Smuzhiyun /**
4263*4882a593Smuzhiyun * @brie check if we need do ACS scan
4264*4882a593Smuzhiyun *
4265*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
4266*4882a593Smuzhiyun *
4267*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4268*4882a593Smuzhiyun */
woal_do_acs_check(moal_private * priv)4269*4882a593Smuzhiyun static mlan_status woal_do_acs_check(moal_private *priv)
4270*4882a593Smuzhiyun {
4271*4882a593Smuzhiyun mlan_status ret = MLAN_STATUS_SUCCESS;
4272*4882a593Smuzhiyun mlan_uap_bss_param *sys_config = NULL;
4273*4882a593Smuzhiyun mlan_uap_scan_channels *scan_channels = NULL;
4274*4882a593Smuzhiyun chan_band_info uap_channel;
4275*4882a593Smuzhiyun ENTER();
4276*4882a593Smuzhiyun
4277*4882a593Smuzhiyun sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
4278*4882a593Smuzhiyun if (!sys_config) {
4279*4882a593Smuzhiyun PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
4280*4882a593Smuzhiyun LEAVE();
4281*4882a593Smuzhiyun return MLAN_STATUS_FAILURE;
4282*4882a593Smuzhiyun }
4283*4882a593Smuzhiyun
4284*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET,
4285*4882a593Smuzhiyun MOAL_IOCTL_WAIT,
4286*4882a593Smuzhiyun sys_config)) {
4287*4882a593Smuzhiyun PRINTM(MERROR, "Fail to get sys config data\n");
4288*4882a593Smuzhiyun kfree(sys_config);
4289*4882a593Smuzhiyun LEAVE();
4290*4882a593Smuzhiyun return MLAN_STATUS_FAILURE;
4291*4882a593Smuzhiyun }
4292*4882a593Smuzhiyun if (!(sys_config->bandcfg.scanMode == SCAN_MODE_ACS)) {
4293*4882a593Smuzhiyun kfree(sys_config);
4294*4882a593Smuzhiyun LEAVE();
4295*4882a593Smuzhiyun return ret;
4296*4882a593Smuzhiyun }
4297*4882a593Smuzhiyun scan_channels = kzalloc(sizeof(mlan_uap_scan_channels), GFP_ATOMIC);
4298*4882a593Smuzhiyun if (scan_channels == NULL) {
4299*4882a593Smuzhiyun PRINTM(MERROR, "Fail to alloc scan channels buffer\n");
4300*4882a593Smuzhiyun kfree(sys_config);
4301*4882a593Smuzhiyun LEAVE();
4302*4882a593Smuzhiyun return MLAN_STATUS_FAILURE;
4303*4882a593Smuzhiyun }
4304*4882a593Smuzhiyun scan_channels->remove_nop_channel = MTRUE;
4305*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
4306*4882a593Smuzhiyun woal_set_get_ap_scan_channels(priv, MLAN_ACT_GET, scan_channels)) {
4307*4882a593Smuzhiyun PRINTM(MERROR, "Fail to get scan channels\n");
4308*4882a593Smuzhiyun goto done;
4309*4882a593Smuzhiyun }
4310*4882a593Smuzhiyun
4311*4882a593Smuzhiyun if (scan_channels->num_remvoed_channel && scan_channels->num_of_chan) {
4312*4882a593Smuzhiyun scan_channels->remove_nop_channel = 0;
4313*4882a593Smuzhiyun /** set back new channel list after remove nop channels */
4314*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
4315*4882a593Smuzhiyun woal_set_get_ap_scan_channels(priv, MLAN_ACT_SET,
4316*4882a593Smuzhiyun scan_channels)) {
4317*4882a593Smuzhiyun PRINTM(MERROR, "Fail to get scan channels\n");
4318*4882a593Smuzhiyun goto done;
4319*4882a593Smuzhiyun }
4320*4882a593Smuzhiyun }
4321*4882a593Smuzhiyun if (scan_channels->num_of_chan)
4322*4882a593Smuzhiyun ret = woal_start_acs_scan(priv);
4323*4882a593Smuzhiyun else
4324*4882a593Smuzhiyun ret = MLAN_STATUS_FAILURE;
4325*4882a593Smuzhiyun /** set to default channel 6 when 5G ACS is configured */
4326*4882a593Smuzhiyun if ((ret != MLAN_STATUS_SUCCESS) &&
4327*4882a593Smuzhiyun (sys_config->bandcfg.chanBand == BAND_5GHZ)) {
4328*4882a593Smuzhiyun memset(&uap_channel, 0, sizeof(uap_channel));
4329*4882a593Smuzhiyun uap_channel.bandcfg.chanBand = DEFAULT_UAP_BAND;
4330*4882a593Smuzhiyun uap_channel.channel = DEFAULT_UAP_CHANNEL;
4331*4882a593Smuzhiyun ret = woal_set_get_ap_channel(priv, MLAN_ACT_SET,
4332*4882a593Smuzhiyun MOAL_IOCTL_WAIT, &uap_channel);
4333*4882a593Smuzhiyun }
4334*4882a593Smuzhiyun done:
4335*4882a593Smuzhiyun kfree(scan_channels);
4336*4882a593Smuzhiyun kfree(sys_config);
4337*4882a593Smuzhiyun LEAVE();
4338*4882a593Smuzhiyun return ret;
4339*4882a593Smuzhiyun }
4340*4882a593Smuzhiyun
4341*4882a593Smuzhiyun /**
4342*4882a593Smuzhiyun * @brief uap BSS control ioctl handler
4343*4882a593Smuzhiyun *
4344*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
4345*4882a593Smuzhiyun * @param wait_option Wait option
4346*4882a593Smuzhiyun * @param data BSS control type
4347*4882a593Smuzhiyun * @return 0 --success, otherwise fail
4348*4882a593Smuzhiyun */
woal_uap_bss_ctrl(moal_private * priv,t_u8 wait_option,int data)4349*4882a593Smuzhiyun int woal_uap_bss_ctrl(moal_private *priv, t_u8 wait_option, int data)
4350*4882a593Smuzhiyun {
4351*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
4352*4882a593Smuzhiyun mlan_ds_bss *bss = NULL;
4353*4882a593Smuzhiyun int ret = 0;
4354*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
4355*4882a593Smuzhiyun
4356*4882a593Smuzhiyun ENTER();
4357*4882a593Smuzhiyun
4358*4882a593Smuzhiyun PRINTM(MIOCTL, "ioctl bss ctrl=%d\n", data);
4359*4882a593Smuzhiyun
4360*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4361*4882a593Smuzhiyun if (req == NULL) {
4362*4882a593Smuzhiyun ret = -ENOMEM;
4363*4882a593Smuzhiyun goto done;
4364*4882a593Smuzhiyun }
4365*4882a593Smuzhiyun bss = (mlan_ds_bss *)req->pbuf;
4366*4882a593Smuzhiyun switch (data) {
4367*4882a593Smuzhiyun case UAP_BSS_START:
4368*4882a593Smuzhiyun if (priv->bss_started == MTRUE) {
4369*4882a593Smuzhiyun PRINTM(MWARN, "Warning: BSS already started!\n");
4370*4882a593Smuzhiyun /* goto done; */
4371*4882a593Smuzhiyun } else if (!priv->uap_host_based
4372*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
4373*4882a593Smuzhiyun || moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD)
4374*4882a593Smuzhiyun #endif
4375*4882a593Smuzhiyun ) {
4376*4882a593Smuzhiyun status = woal_do_acs_check(priv);
4377*4882a593Smuzhiyun if (status)
4378*4882a593Smuzhiyun PRINTM(MMSG, "woal_do_acs_check fails\n");
4379*4882a593Smuzhiyun /* about to start bss: issue channel check */
4380*4882a593Smuzhiyun status = woal_11h_channel_check_ioctl(priv,
4381*4882a593Smuzhiyun MOAL_IOCTL_WAIT);
4382*4882a593Smuzhiyun if (status) {
4383*4882a593Smuzhiyun PRINTM(MMSG, "11h channel check fails\n");
4384*4882a593Smuzhiyun status = MLAN_STATUS_FAILURE;
4385*4882a593Smuzhiyun ret = -1;
4386*4882a593Smuzhiyun goto done;
4387*4882a593Smuzhiyun }
4388*4882a593Smuzhiyun }
4389*4882a593Smuzhiyun bss->sub_command = MLAN_OID_BSS_START;
4390*4882a593Smuzhiyun if (priv->uap_host_based) {
4391*4882a593Smuzhiyun bss->param.host_based |= UAP_FLAG_HOST_BASED;
4392*4882a593Smuzhiyun #ifdef UAP_CFG80211
4393*4882a593Smuzhiyun #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
4394*4882a593Smuzhiyun if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME))
4395*4882a593Smuzhiyun bss->param.host_based |= UAP_FLAG_HOST_MLME;
4396*4882a593Smuzhiyun #endif
4397*4882a593Smuzhiyun #endif
4398*4882a593Smuzhiyun }
4399*4882a593Smuzhiyun break;
4400*4882a593Smuzhiyun case UAP_BSS_STOP:
4401*4882a593Smuzhiyun if (priv->bss_started == MFALSE) {
4402*4882a593Smuzhiyun PRINTM(MWARN, "Warning: BSS already stopped!\n");
4403*4882a593Smuzhiyun /* This is a situation where CAC it started and BSS
4404*4882a593Smuzhiyun * start is dealyed and before CAC timer expires BSS
4405*4882a593Smuzhiyun * stop is triggered.
4406*4882a593Smuzhiyun *
4407*4882a593Smuzhiyun * Do not skip sending the BSS_STOP command since there
4408*4882a593Smuzhiyun * are many routines triggered on BSS_STOP command
4409*4882a593Smuzhiyun * response.
4410*4882a593Smuzhiyun */
4411*4882a593Smuzhiyun woal_cancel_cac_block(priv);
4412*4882a593Smuzhiyun }
4413*4882a593Smuzhiyun bss->sub_command = MLAN_OID_BSS_STOP;
4414*4882a593Smuzhiyun break;
4415*4882a593Smuzhiyun case UAP_BSS_RESET:
4416*4882a593Smuzhiyun bss->sub_command = MLAN_OID_UAP_BSS_RESET;
4417*4882a593Smuzhiyun woal_cancel_cac_block(priv);
4418*4882a593Smuzhiyun break;
4419*4882a593Smuzhiyun default:
4420*4882a593Smuzhiyun PRINTM(MMSG, "We don't support this uap_bss_ctrl cmd %d\n",
4421*4882a593Smuzhiyun data);
4422*4882a593Smuzhiyun ret = -EFAULT;
4423*4882a593Smuzhiyun goto done;
4424*4882a593Smuzhiyun }
4425*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_BSS;
4426*4882a593Smuzhiyun req->action = MLAN_ACT_SET;
4427*4882a593Smuzhiyun
4428*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, wait_option);
4429*4882a593Smuzhiyun if (status == MLAN_STATUS_FAILURE) {
4430*4882a593Smuzhiyun ret = -EFAULT;
4431*4882a593Smuzhiyun goto done;
4432*4882a593Smuzhiyun }
4433*4882a593Smuzhiyun if (data == UAP_BSS_STOP || data == UAP_BSS_RESET) {
4434*4882a593Smuzhiyun priv->bss_started = MFALSE;
4435*4882a593Smuzhiyun woal_stop_queue(priv->netdev);
4436*4882a593Smuzhiyun if (netif_carrier_ok(priv->netdev))
4437*4882a593Smuzhiyun netif_carrier_off(priv->netdev);
4438*4882a593Smuzhiyun if (data == UAP_BSS_RESET) {
4439*4882a593Smuzhiyun if (MLAN_STATUS_FAILURE ==
4440*4882a593Smuzhiyun woal_request_set_mac_address(priv, wait_option))
4441*4882a593Smuzhiyun PRINTM(MERROR,
4442*4882a593Smuzhiyun "Fail to set mac address after UAP_BSS_RESET\n");
4443*4882a593Smuzhiyun }
4444*4882a593Smuzhiyun woal_flush_tcp_sess_queue(priv);
4445*4882a593Smuzhiyun }
4446*4882a593Smuzhiyun done:
4447*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
4448*4882a593Smuzhiyun kfree(req);
4449*4882a593Smuzhiyun LEAVE();
4450*4882a593Smuzhiyun return ret;
4451*4882a593Smuzhiyun }
4452*4882a593Smuzhiyun
4453*4882a593Smuzhiyun /**
4454*4882a593Smuzhiyun * @brief This function sets multicast addresses to firmware
4455*4882a593Smuzhiyun *
4456*4882a593Smuzhiyun * @param dev A pointer to net_device structure
4457*4882a593Smuzhiyun * @return N/A
4458*4882a593Smuzhiyun */
woal_uap_set_multicast_list(struct net_device * dev)4459*4882a593Smuzhiyun void woal_uap_set_multicast_list(struct net_device *dev)
4460*4882a593Smuzhiyun {
4461*4882a593Smuzhiyun ENTER();
4462*4882a593Smuzhiyun
4463*4882a593Smuzhiyun LEAVE();
4464*4882a593Smuzhiyun }
4465*4882a593Smuzhiyun
4466*4882a593Smuzhiyun /**
4467*4882a593Smuzhiyun * @brief ioctl function - entry point
4468*4882a593Smuzhiyun *
4469*4882a593Smuzhiyun * @param dev A pointer to net_device structure
4470*4882a593Smuzhiyun * @param req A pointer to ifreq structure
4471*4882a593Smuzhiyun * @param cmd Command
4472*4882a593Smuzhiyun *
4473*4882a593Smuzhiyun * @return 0 --success, otherwise fail
4474*4882a593Smuzhiyun */
4475*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
woal_uap_do_ioctl(struct net_device * dev,struct ifreq * req,void __user * data,int cmd)4476*4882a593Smuzhiyun int woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req,
4477*4882a593Smuzhiyun void __user *data, int cmd)
4478*4882a593Smuzhiyun #else
4479*4882a593Smuzhiyun int woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
4480*4882a593Smuzhiyun #endif
4481*4882a593Smuzhiyun {
4482*4882a593Smuzhiyun int ret = 0;
4483*4882a593Smuzhiyun ENTER();
4484*4882a593Smuzhiyun
4485*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
4486*4882a593Smuzhiyun if (in_compat_syscall()) /* not implemented yet */
4487*4882a593Smuzhiyun return -EOPNOTSUPP;
4488*4882a593Smuzhiyun #endif
4489*4882a593Smuzhiyun
4490*4882a593Smuzhiyun switch (cmd) {
4491*4882a593Smuzhiyun case WOAL_ANDROID_DEF_CMD:
4492*4882a593Smuzhiyun /** android default ioctl ID is SIOCDEVPRIVATE + 1 */
4493*4882a593Smuzhiyun ret = woal_android_priv_cmd(dev, req);
4494*4882a593Smuzhiyun break;
4495*4882a593Smuzhiyun case UAP_IOCTL_CMD:
4496*4882a593Smuzhiyun ret = woal_uap_ioctl(dev, req);
4497*4882a593Smuzhiyun break;
4498*4882a593Smuzhiyun case UAP_POWER_MODE:
4499*4882a593Smuzhiyun ret = woal_uap_power_mode_ioctl(dev, req);
4500*4882a593Smuzhiyun break;
4501*4882a593Smuzhiyun case UAP_BSS_CTRL:
4502*4882a593Smuzhiyun ret = woal_uap_bss_ctrl_ioctl(dev, req);
4503*4882a593Smuzhiyun break;
4504*4882a593Smuzhiyun case UAP_WAPI_MSG:
4505*4882a593Smuzhiyun ret = woal_uap_set_wapi(dev, req);
4506*4882a593Smuzhiyun break;
4507*4882a593Smuzhiyun case UAP_BSS_CONFIG:
4508*4882a593Smuzhiyun ret = woal_uap_bss_cfg_ioctl(dev, req);
4509*4882a593Smuzhiyun break;
4510*4882a593Smuzhiyun case UAP_STA_DEAUTH:
4511*4882a593Smuzhiyun ret = woal_uap_sta_deauth_ioctl(dev, req);
4512*4882a593Smuzhiyun break;
4513*4882a593Smuzhiyun case UAP_RADIO_CTL:
4514*4882a593Smuzhiyun ret = woal_uap_radio_ctl(dev, req);
4515*4882a593Smuzhiyun break;
4516*4882a593Smuzhiyun case UAP_REPORT_MIC_ERR:
4517*4882a593Smuzhiyun ret = woal_uap_report_mic_ioctl(dev, req);
4518*4882a593Smuzhiyun break;
4519*4882a593Smuzhiyun case UAP_SET_KEY:
4520*4882a593Smuzhiyun ret = woal_uap_set_key_ioctl(dev, req);
4521*4882a593Smuzhiyun break;
4522*4882a593Smuzhiyun case UAPHOSTPKTINJECT:
4523*4882a593Smuzhiyun ret = woal_send_host_packet(dev, req);
4524*4882a593Smuzhiyun break;
4525*4882a593Smuzhiyun case UAP_GET_STA_LIST:
4526*4882a593Smuzhiyun ret = woal_uap_get_sta_list_ioctl(dev, req);
4527*4882a593Smuzhiyun break;
4528*4882a593Smuzhiyun case UAP_CUSTOM_IE:
4529*4882a593Smuzhiyun ret = woal_custom_ie_ioctl(dev, req);
4530*4882a593Smuzhiyun break;
4531*4882a593Smuzhiyun case UAP_GET_BSS_TYPE:
4532*4882a593Smuzhiyun ret = woal_get_bss_type(dev, req);
4533*4882a593Smuzhiyun break;
4534*4882a593Smuzhiyun case WOAL_ANDROID_PRIV_CMD:
4535*4882a593Smuzhiyun ret = woal_android_priv_cmd(dev, req);
4536*4882a593Smuzhiyun break;
4537*4882a593Smuzhiyun default:
4538*4882a593Smuzhiyun #ifdef UAP_WEXT
4539*4882a593Smuzhiyun ret = woal_uap_do_priv_ioctl(dev, req, cmd);
4540*4882a593Smuzhiyun #else
4541*4882a593Smuzhiyun ret = -EOPNOTSUPP;
4542*4882a593Smuzhiyun #endif
4543*4882a593Smuzhiyun break;
4544*4882a593Smuzhiyun }
4545*4882a593Smuzhiyun
4546*4882a593Smuzhiyun LEAVE();
4547*4882a593Smuzhiyun return ret;
4548*4882a593Smuzhiyun }
4549*4882a593Smuzhiyun
4550*4882a593Smuzhiyun #ifdef CONFIG_PROC_FS
4551*4882a593Smuzhiyun /**
4552*4882a593Smuzhiyun * @brief Get version
4553*4882a593Smuzhiyun *
4554*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
4555*4882a593Smuzhiyun * @param version A pointer to version buffer
4556*4882a593Smuzhiyun * @param max_len max length of version buffer
4557*4882a593Smuzhiyun *
4558*4882a593Smuzhiyun * @return N/A
4559*4882a593Smuzhiyun */
woal_uap_get_version(moal_private * priv,char * version,int max_len)4560*4882a593Smuzhiyun void woal_uap_get_version(moal_private *priv, char *version, int max_len)
4561*4882a593Smuzhiyun {
4562*4882a593Smuzhiyun mlan_ds_get_info *info = NULL;
4563*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
4564*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
4565*4882a593Smuzhiyun
4566*4882a593Smuzhiyun ENTER();
4567*4882a593Smuzhiyun
4568*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
4569*4882a593Smuzhiyun if (req == NULL) {
4570*4882a593Smuzhiyun LEAVE();
4571*4882a593Smuzhiyun return;
4572*4882a593Smuzhiyun }
4573*4882a593Smuzhiyun
4574*4882a593Smuzhiyun info = (mlan_ds_get_info *)req->pbuf;
4575*4882a593Smuzhiyun info->sub_command = MLAN_OID_GET_VER_EXT;
4576*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_GET_INFO;
4577*4882a593Smuzhiyun req->action = MLAN_ACT_GET;
4578*4882a593Smuzhiyun
4579*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4580*4882a593Smuzhiyun if (status == MLAN_STATUS_SUCCESS) {
4581*4882a593Smuzhiyun PRINTM(MINFO, "MOAL UAP VERSION: %s\n",
4582*4882a593Smuzhiyun info->param.ver_ext.version_str);
4583*4882a593Smuzhiyun snprintf(version, max_len, priv->phandle->driver_version,
4584*4882a593Smuzhiyun info->param.ver_ext.version_str);
4585*4882a593Smuzhiyun }
4586*4882a593Smuzhiyun
4587*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
4588*4882a593Smuzhiyun kfree(req);
4589*4882a593Smuzhiyun LEAVE();
4590*4882a593Smuzhiyun return;
4591*4882a593Smuzhiyun }
4592*4882a593Smuzhiyun #endif
4593*4882a593Smuzhiyun
4594*4882a593Smuzhiyun /**
4595*4882a593Smuzhiyun * @brief Get uap statistics
4596*4882a593Smuzhiyun *
4597*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
4598*4882a593Smuzhiyun * @param wait_option Wait option
4599*4882a593Smuzhiyun * @param ustats A pointer to mlan_ds_uap_stats structure
4600*4882a593Smuzhiyun *
4601*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
4602*4882a593Smuzhiyun * success, otherwise fail
4603*4882a593Smuzhiyun */
woal_uap_get_stats(moal_private * priv,t_u8 wait_option,mlan_ds_uap_stats * ustats)4604*4882a593Smuzhiyun mlan_status woal_uap_get_stats(moal_private *priv, t_u8 wait_option,
4605*4882a593Smuzhiyun mlan_ds_uap_stats *ustats)
4606*4882a593Smuzhiyun {
4607*4882a593Smuzhiyun mlan_ds_get_info *info = NULL;
4608*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
4609*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
4610*4882a593Smuzhiyun
4611*4882a593Smuzhiyun ENTER();
4612*4882a593Smuzhiyun
4613*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
4614*4882a593Smuzhiyun if (req == NULL) {
4615*4882a593Smuzhiyun LEAVE();
4616*4882a593Smuzhiyun return MLAN_STATUS_FAILURE;
4617*4882a593Smuzhiyun }
4618*4882a593Smuzhiyun
4619*4882a593Smuzhiyun info = (mlan_ds_get_info *)req->pbuf;
4620*4882a593Smuzhiyun info->sub_command = MLAN_OID_GET_STATS;
4621*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_GET_INFO;
4622*4882a593Smuzhiyun req->action = MLAN_ACT_GET;
4623*4882a593Smuzhiyun
4624*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, wait_option);
4625*4882a593Smuzhiyun if (status == MLAN_STATUS_SUCCESS) {
4626*4882a593Smuzhiyun if (ustats)
4627*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, ustats,
4628*4882a593Smuzhiyun &info->param.ustats,
4629*4882a593Smuzhiyun sizeof(mlan_ds_uap_stats),
4630*4882a593Smuzhiyun sizeof(mlan_ds_uap_stats));
4631*4882a593Smuzhiyun #ifdef UAP_WEXT
4632*4882a593Smuzhiyun priv->w_stats.discard.fragment =
4633*4882a593Smuzhiyun info->param.ustats.fcs_error_count;
4634*4882a593Smuzhiyun priv->w_stats.discard.retries = info->param.ustats.retry_count;
4635*4882a593Smuzhiyun priv->w_stats.discard.misc =
4636*4882a593Smuzhiyun info->param.ustats.ack_failure_count;
4637*4882a593Smuzhiyun #endif
4638*4882a593Smuzhiyun }
4639*4882a593Smuzhiyun
4640*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
4641*4882a593Smuzhiyun kfree(req);
4642*4882a593Smuzhiyun LEAVE();
4643*4882a593Smuzhiyun return status;
4644*4882a593Smuzhiyun }
4645*4882a593Smuzhiyun
4646*4882a593Smuzhiyun /**
4647*4882a593Smuzhiyun * @brief Set/Get system configuration parameters
4648*4882a593Smuzhiyun *
4649*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
4650*4882a593Smuzhiyun * @param action MLAN_ACT_SET or MLAN_ACT_GET
4651*4882a593Smuzhiyun * @param ap_wmm_para A pointer to wmm_parameter_t structure
4652*4882a593Smuzhiyun *
4653*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4654*4882a593Smuzhiyun */
woal_set_get_ap_wmm_para(moal_private * priv,t_u16 action,wmm_parameter_t * ap_wmm_para)4655*4882a593Smuzhiyun mlan_status woal_set_get_ap_wmm_para(moal_private *priv, t_u16 action,
4656*4882a593Smuzhiyun wmm_parameter_t *ap_wmm_para)
4657*4882a593Smuzhiyun {
4658*4882a593Smuzhiyun mlan_status ret = MLAN_STATUS_SUCCESS;
4659*4882a593Smuzhiyun mlan_ds_bss *bss = NULL;
4660*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
4661*4882a593Smuzhiyun
4662*4882a593Smuzhiyun ENTER();
4663*4882a593Smuzhiyun
4664*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4665*4882a593Smuzhiyun if (req == NULL) {
4666*4882a593Smuzhiyun ret = MLAN_STATUS_FAILURE;
4667*4882a593Smuzhiyun goto done;
4668*4882a593Smuzhiyun }
4669*4882a593Smuzhiyun
4670*4882a593Smuzhiyun bss = (mlan_ds_bss *)req->pbuf;
4671*4882a593Smuzhiyun bss->sub_command = MLAN_OID_UAP_CFG_WMM_PARAM;
4672*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_BSS;
4673*4882a593Smuzhiyun req->action = action;
4674*4882a593Smuzhiyun
4675*4882a593Smuzhiyun if (action == MLAN_ACT_SET)
4676*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &bss->param.ap_wmm_para,
4677*4882a593Smuzhiyun ap_wmm_para, sizeof(wmm_parameter_t),
4678*4882a593Smuzhiyun sizeof(bss->param.ap_wmm_para));
4679*4882a593Smuzhiyun
4680*4882a593Smuzhiyun ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4681*4882a593Smuzhiyun if (ret != MLAN_STATUS_SUCCESS)
4682*4882a593Smuzhiyun goto done;
4683*4882a593Smuzhiyun if (bss->param.ap_wmm_para.reserved != MLAN_STATUS_COMPLETE) {
4684*4882a593Smuzhiyun ret = MLAN_STATUS_FAILURE;
4685*4882a593Smuzhiyun goto done;
4686*4882a593Smuzhiyun }
4687*4882a593Smuzhiyun if (action == MLAN_ACT_GET)
4688*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, ap_wmm_para,
4689*4882a593Smuzhiyun &bss->param.ap_wmm_para,
4690*4882a593Smuzhiyun sizeof(wmm_parameter_t),
4691*4882a593Smuzhiyun sizeof(wmm_parameter_t));
4692*4882a593Smuzhiyun
4693*4882a593Smuzhiyun done:
4694*4882a593Smuzhiyun if (ret != MLAN_STATUS_PENDING)
4695*4882a593Smuzhiyun kfree(req);
4696*4882a593Smuzhiyun LEAVE();
4697*4882a593Smuzhiyun return ret;
4698*4882a593Smuzhiyun }
4699*4882a593Smuzhiyun
4700*4882a593Smuzhiyun /**
4701*4882a593Smuzhiyun * @brief Set/Get system configuration parameters
4702*4882a593Smuzhiyun *
4703*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
4704*4882a593Smuzhiyun * @param action MLAN_ACT_SET or MLAN_ACT_GET
4705*4882a593Smuzhiyun * @param wait_option Wait option
4706*4882a593Smuzhiyun * @param sys_cfg A pointer to mlan_uap_bss_param structure
4707*4882a593Smuzhiyun *
4708*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4709*4882a593Smuzhiyun */
woal_set_get_sys_config(moal_private * priv,t_u16 action,t_u8 wait_option,mlan_uap_bss_param * sys_cfg)4710*4882a593Smuzhiyun mlan_status woal_set_get_sys_config(moal_private *priv, t_u16 action,
4711*4882a593Smuzhiyun t_u8 wait_option,
4712*4882a593Smuzhiyun mlan_uap_bss_param *sys_cfg)
4713*4882a593Smuzhiyun {
4714*4882a593Smuzhiyun mlan_status ret = MLAN_STATUS_SUCCESS;
4715*4882a593Smuzhiyun mlan_ds_bss *bss = NULL;
4716*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
4717*4882a593Smuzhiyun
4718*4882a593Smuzhiyun ENTER();
4719*4882a593Smuzhiyun
4720*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4721*4882a593Smuzhiyun if (req == NULL) {
4722*4882a593Smuzhiyun ret = MLAN_STATUS_FAILURE;
4723*4882a593Smuzhiyun goto done;
4724*4882a593Smuzhiyun }
4725*4882a593Smuzhiyun
4726*4882a593Smuzhiyun bss = (mlan_ds_bss *)req->pbuf;
4727*4882a593Smuzhiyun bss->sub_command = MLAN_OID_UAP_BSS_CONFIG;
4728*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_BSS;
4729*4882a593Smuzhiyun req->action = action;
4730*4882a593Smuzhiyun
4731*4882a593Smuzhiyun if (action == MLAN_ACT_SET)
4732*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &bss->param.bss_config, sys_cfg,
4733*4882a593Smuzhiyun sizeof(mlan_uap_bss_param),
4734*4882a593Smuzhiyun sizeof(bss->param.bss_config));
4735*4882a593Smuzhiyun
4736*4882a593Smuzhiyun ret = woal_request_ioctl(priv, req, wait_option);
4737*4882a593Smuzhiyun if (ret != MLAN_STATUS_SUCCESS)
4738*4882a593Smuzhiyun goto done;
4739*4882a593Smuzhiyun
4740*4882a593Smuzhiyun if (action == MLAN_ACT_GET)
4741*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, sys_cfg, &bss->param.bss_config,
4742*4882a593Smuzhiyun sizeof(mlan_uap_bss_param),
4743*4882a593Smuzhiyun sizeof(mlan_uap_bss_param));
4744*4882a593Smuzhiyun
4745*4882a593Smuzhiyun done:
4746*4882a593Smuzhiyun if (ret != MLAN_STATUS_PENDING)
4747*4882a593Smuzhiyun kfree(req);
4748*4882a593Smuzhiyun LEAVE();
4749*4882a593Smuzhiyun return ret;
4750*4882a593Smuzhiyun }
4751*4882a593Smuzhiyun
4752*4882a593Smuzhiyun /**
4753*4882a593Smuzhiyun * @brief Set invalid data for each member of mlan_uap_bss_param
4754*4882a593Smuzhiyun * structure
4755*4882a593Smuzhiyun *
4756*4882a593Smuzhiyun * @param config A pointer to mlan_uap_bss_param structure
4757*4882a593Smuzhiyun *
4758*4882a593Smuzhiyun * @return N/A
4759*4882a593Smuzhiyun */
woal_set_sys_config_invalid_data(mlan_uap_bss_param * config)4760*4882a593Smuzhiyun void woal_set_sys_config_invalid_data(mlan_uap_bss_param *config)
4761*4882a593Smuzhiyun {
4762*4882a593Smuzhiyun ENTER();
4763*4882a593Smuzhiyun
4764*4882a593Smuzhiyun memset(config, 0, sizeof(mlan_uap_bss_param));
4765*4882a593Smuzhiyun config->bcast_ssid_ctl = 0x7F;
4766*4882a593Smuzhiyun config->radio_ctl = 0x7F;
4767*4882a593Smuzhiyun config->dtim_period = 0x7F;
4768*4882a593Smuzhiyun config->beacon_period = 0x7FFF;
4769*4882a593Smuzhiyun config->tx_data_rate = 0x7FFF;
4770*4882a593Smuzhiyun config->mcbc_data_rate = 0x7FFF;
4771*4882a593Smuzhiyun config->tx_power_level = 0x7F;
4772*4882a593Smuzhiyun config->tx_antenna = 0x7F;
4773*4882a593Smuzhiyun config->rx_antenna = 0x7F;
4774*4882a593Smuzhiyun config->pkt_forward_ctl = 0x7F;
4775*4882a593Smuzhiyun config->max_sta_count = 0x7FFF;
4776*4882a593Smuzhiyun config->auth_mode = 0x7F;
4777*4882a593Smuzhiyun config->sta_ageout_timer = 0x7FFFFFFF;
4778*4882a593Smuzhiyun config->pairwise_update_timeout = 0x7FFFFFFF;
4779*4882a593Smuzhiyun config->pwk_retries = 0x7FFFFFFF;
4780*4882a593Smuzhiyun config->groupwise_update_timeout = 0x7FFFFFFF;
4781*4882a593Smuzhiyun config->gwk_retries = 0x7FFFFFFF;
4782*4882a593Smuzhiyun config->mgmt_ie_passthru_mask = 0x7FFFFFFF;
4783*4882a593Smuzhiyun config->ps_sta_ageout_timer = 0x7FFFFFFF;
4784*4882a593Smuzhiyun config->rts_threshold = 0x7FFF;
4785*4882a593Smuzhiyun config->frag_threshold = 0x7FFF;
4786*4882a593Smuzhiyun config->retry_limit = 0x7FFF;
4787*4882a593Smuzhiyun config->filter.filter_mode = 0x7FFF;
4788*4882a593Smuzhiyun config->filter.mac_count = 0x7FFF;
4789*4882a593Smuzhiyun config->wpa_cfg.rsn_protection = 0x7F;
4790*4882a593Smuzhiyun config->wpa_cfg.gk_rekey_time = 0x7FFFFFFF;
4791*4882a593Smuzhiyun config->enable_2040coex = 0x7F;
4792*4882a593Smuzhiyun config->wmm_para.qos_info = 0x7F;
4793*4882a593Smuzhiyun
4794*4882a593Smuzhiyun LEAVE();
4795*4882a593Smuzhiyun }
4796