1 /** @file moal_ioctl.c
2 *
3 * @brief This file contains ioctl function to MLAN
4 *
5 *
6 * Copyright 2008-2022 NXP
7 *
8 * This software file (the File) is distributed by NXP
9 * under the terms of the GNU General Public License Version 2, June 1991
10 * (the License). You may use, redistribute and/or modify the File in
11 * accordance with the terms and conditions of the License, a copy of which
12 * is available by writing to the Free Software Foundation, Inc.,
13 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15 *
16 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
19 * this warranty disclaimer.
20 *
21 */
22
23 /********************************************************
24 Change log:
25 10/21/2008: initial version
26 ********************************************************/
27
28 #include "moal_main.h"
29 #include "moal_eth_ioctl.h"
30 #ifdef SDIO
31 #include "moal_sdio.h"
32 #endif
33 #ifdef USB
34 #include "moal_usb.h"
35 #endif
36 #ifdef UAP_SUPPORT
37 #include "moal_uap.h"
38 #endif
39
40 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
41 #include "moal_cfg80211.h"
42 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
43 #include "moal_cfg80211_util.h"
44 #endif
45 #endif
46
47 /********************************************************
48 Local Variables
49 ********************************************************/
50 #define MRVL_TLV_HEADER_SIZE 4
51 /* NXP Channel config TLV ID */
52 #define MRVL_CHANNELCONFIG_TLV_ID (0x0100 + 0x2a) /* 0x012a */
53
54 typedef struct _hostcmd_header {
55 /** Command Header : Command */
56 t_u16 command;
57 /** Command Header : Size */
58 t_u16 size;
59 /** Command Header : Sequence number */
60 t_u16 seq_num;
61 /** Command Header : Result */
62 t_u16 result;
63 /** Command action */
64 t_u16 action;
65 } hostcmd_header, *phostcmd_header;
66
67 /** Region code mapping */
68 typedef struct _region_code_mapping_t {
69 /** Region */
70 t_u8 region[COUNTRY_CODE_LEN];
71 /** Code */
72 t_u8 code;
73 } region_code_mapping_t;
74
75 #define EU_REGION_CODE 0x30
76
77 /** Region code mapping table */
78 static region_code_mapping_t region_code_mapping[] = {
79 {"00", 0x00}, /* World */
80 {"US", 0x10}, /* US FCC */
81 {"CA", 0x20}, /* IC Canada */
82 {"SG", 0x10}, /* Singapore */
83 {"EU", 0x30}, /* ETSI */
84 {"AU", 0x30}, /* Australia */
85 {"KR", 0x30}, /* Republic Of Korea */
86 {"JP", 0x40}, /* Japan */
87 {"CN", 0x50}, /* China */
88 {"BR", 0x09}, /* Brazil */
89 {"RU", 0x0f}, /* Russia */
90 {"IN", 0x06}, /* India */
91 {"MY", 0x06}, /* Malaysia */
92 {"MX", 0x07}, /* Mexico */
93 {"NE", 0x30}, /* New Zeland */
94 };
95
96 /** EEPROM Region code mapping table */
97 static region_code_mapping_t hw_region_code_mapping[] = {
98 {"00 ", 0x00}, /* World */
99 {"US ", 0x10}, /* US FCC */
100 {"CA ", 0x20}, /* IC Canada */
101 {"KR ", 0x30}, /* Korea */
102 {"CN ", 0x50}, /* China */
103 {"ES ", 0x31}, /* Spain */
104 {"FR ", 0x32}, /* France */
105 {"JP ", 0x40}, /* Japan */
106 {"JP ", 0x41}, /* Japan */
107 };
108
109 /** Country code for ETSI */
110 static t_u8 eu_country_code_table[][COUNTRY_CODE_LEN] = {
111 "AL", "AD", "AT", "AU", "BE", "BA", "BG", "HR", "CY", "CZ", "DK", "EE",
112 "FI", "FR", "MK", "DE", "GR", "HU", "IS", "IE", "IT", "LV", "LI", "LT",
113 "LU", "MT", "MD", "MC", "ME", "NL", "NO", "PL", "RO", "SM", "RS", "SI",
114 "SK", "ES", "SE", "CH", "TR", "UA", "UK", "GB", "NE", "NZ", "DZ", "AO",
115 "AM", "AW", "BH", "BD", "BT", "BO", "BQ", "BW", "VG", "BF", "BI", "KH",
116 "CL", "KM", "CG", "CD", "CW", "EG", "FO", "GF", "PF", "GE", "GI", "GP",
117 "HK", "IN", "ID", "IM", "IL", "JE", "KE", "XK", "KW", "LA", "LR", "MW",
118 "MV", "MQ", "MR", "YT", "MA", "MZ", "MM", "NA", "NC", "NG", "OM", "PS",
119 "PT", "QA", "RW", "RE", "BL", "MF", "VC", "SA", "SC", "ZA", "SZ", "SY",
120 "TZ", "TG", "TN", "AE", "VA", "EH", "YE", "ZM", "ZW"};
121
122 /********************************************************
123 Global Variables
124 ********************************************************/
125
126 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
127 #ifdef UAP_SUPPORT
128 /** Network device handlers for uAP */
129 extern const struct net_device_ops woal_uap_netdev_ops;
130 #endif
131 #ifdef STA_SUPPORT
132 /** Network device handlers for STA */
133 extern const struct net_device_ops woal_netdev_ops;
134 #endif
135 #endif
136
137 /********************************************************
138 Local Functions
139 ********************************************************/
140 /**
141 * @brief This function converts region string to region code
142 *
143 * @param country_code Region string
144 *
145 * @return Region code
146 */
woal_is_country_code_supported(t_u8 * country_code)147 static t_bool woal_is_country_code_supported(t_u8 *country_code)
148 {
149 t_u8 i;
150 ENTER();
151
152 for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
153 if (!memcmp(country_code, region_code_mapping[i].region,
154 COUNTRY_CODE_LEN - 1)) {
155 PRINTM(MIOCTL,
156 "found country code in region_code table\n");
157 LEAVE();
158 return MTRUE;
159 }
160 }
161
162 LEAVE();
163 return MFALSE;
164 }
165 /**
166 * @brief This function converts region string to region code
167 *
168 * @param region_string Region string
169 *
170 * @return Region code
171 */
region_string_2_region_code(char * region_string)172 static t_u8 region_string_2_region_code(char *region_string)
173 {
174 t_u8 i;
175
176 ENTER();
177 for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
178 if (!memcmp(region_string, region_code_mapping[i].region,
179 strlen(region_string))) {
180 LEAVE();
181 return region_code_mapping[i].code;
182 }
183 }
184
185 /* If still not found, look for code in EU country code table */
186 for (i = 0; i < ARRAY_SIZE(eu_country_code_table); i++) {
187 if (!memcmp(region_string, eu_country_code_table[i],
188 COUNTRY_CODE_LEN - 1)) {
189 PRINTM(MIOCTL, "found region code=%d in EU table\n",
190 EU_REGION_CODE);
191 LEAVE();
192 return EU_REGION_CODE;
193 }
194 }
195
196 /* Default is US */
197 LEAVE();
198 return region_code_mapping[0].code;
199 }
200
201 /**
202 * @brief This function converts region string to region code
203 *
204 * @param country_code Region string
205 *
206 * @return Region code
207 */
woal_is_etsi_country(t_u8 * country_code)208 t_bool woal_is_etsi_country(t_u8 *country_code)
209 {
210 t_u8 i;
211 ENTER();
212
213 for (i = 0; i < ARRAY_SIZE(eu_country_code_table); i++) {
214 if (!memcmp(country_code, eu_country_code_table[i],
215 COUNTRY_CODE_LEN - 1)) {
216 PRINTM(MIOCTL, "found region code=%d in EU table\n",
217 EU_REGION_CODE);
218 LEAVE();
219 return MTRUE;
220 }
221 }
222
223 LEAVE();
224 return MFALSE;
225 }
226
227 /**
228 * @brief This function converts region string to region code
229 *
230 * @param region_code region code
231 *
232 * @return Region string or NULL
233 */
region_code_2_string(t_u8 region_code)234 char *region_code_2_string(t_u8 region_code)
235 {
236 t_u8 i;
237
238 ENTER();
239 for (i = 0; i < ARRAY_SIZE(hw_region_code_mapping); i++) {
240 if (hw_region_code_mapping[i].code == region_code) {
241 LEAVE();
242 return hw_region_code_mapping[i].region;
243 }
244 }
245 LEAVE();
246 return NULL;
247 }
248
woal_is_valid_alpha2(char * alpha2)249 t_u8 woal_is_valid_alpha2(char *alpha2)
250 {
251 if (!alpha2 || strlen(alpha2) < 2)
252 return MFALSE;
253 if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
254 return MTRUE;
255 return MFALSE;
256 }
257
258 /**
259 * @brief Get second channel offset
260 *
261 * @param priv A pointer to moal_private structure
262 * @param chan channel num
263 * @return second channel offset
264 */
woal_get_second_channel_offset(moal_private * priv,int chan)265 t_u8 woal_get_second_channel_offset(moal_private *priv, int chan)
266 {
267 t_u8 chan2Offset = SEC_CHAN_NONE;
268 mlan_bss_info bss_info;
269
270 /* Special Case: 20Mhz-only Channel */
271 woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
272 if (bss_info.region_code != COUNTRY_CODE_US && chan == 165)
273 return chan2Offset;
274
275 switch (chan) {
276 case 36:
277 case 44:
278 case 52:
279 case 60:
280 case 100:
281 case 108:
282 case 116:
283 case 124:
284 case 132:
285 case 140:
286 case 149:
287 case 157:
288 case 165:
289 case 173:
290 chan2Offset = SEC_CHAN_ABOVE;
291 break;
292 case 40:
293 case 48:
294 case 56:
295 case 64:
296 case 104:
297 case 112:
298 case 120:
299 case 128:
300 case 136:
301 case 144:
302 case 153:
303 case 161:
304 case 169:
305 case 177:
306 chan2Offset = SEC_CHAN_BELOW;
307 break;
308 }
309 return chan2Offset;
310 }
311
312 /**
313 * @brief Copy mc address to the mlist
314 *
315 * @param mlist A pointer to mlan_multicast_list structure
316 * @param mac mc address
317 *
318 * @return N/A
319 */
woal_copy_mc_addr(mlan_multicast_list * mlist,mlan_802_11_mac_addr mac)320 static inline void woal_copy_mc_addr(mlan_multicast_list *mlist,
321 mlan_802_11_mac_addr mac)
322 {
323 t_u32 i = 0;
324 for (i = 0; i < mlist->num_multicast_addr; i++) {
325 if (!memcmp(&mlist->mac_list[i], mac, ETH_ALEN))
326 return;
327 }
328 if (mlist->num_multicast_addr < MLAN_MAX_MULTICAST_LIST_SIZE)
329 moal_memcpy_ext(NULL,
330 &mlist->mac_list[mlist->num_multicast_addr],
331 mac, ETH_ALEN, sizeof(mlan_802_11_mac_addr));
332 mlist->num_multicast_addr++;
333 return;
334 }
335
336 /**
337 * @brief Copy multicast table
338 *
339 * @param mlist A pointer to mlan_multicast_list structure
340 * @param dev A pointer to net_device structure
341 *
342 * @return Number of multicast addresses
343 */
woal_copy_mcast_addr(mlan_multicast_list * mlist,struct net_device * dev)344 static inline int woal_copy_mcast_addr(mlan_multicast_list *mlist,
345 struct net_device *dev)
346 {
347 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
348 struct dev_mc_list *mcptr = dev->mc_list;
349 int i = 0;
350 #else
351 struct netdev_hw_addr *mcptr = NULL;
352 #endif /* < 2.6.35 */
353
354 ENTER();
355 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
356 for (i = 0; i < dev->mc_count && mcptr; i++) {
357 woal_copy_mc_addr(mlist, mcptr->dmi_addr);
358 mcptr = mcptr->next;
359 }
360 #else
361 netdev_for_each_mc_addr (mcptr, dev)
362 woal_copy_mc_addr(mlist, mcptr->addr);
363 #endif /* < 2.6.35 */
364 LEAVE();
365 return mlist->num_multicast_addr;
366 }
367
368 /**
369 * @brief copy mc list from all the active interface
370 *
371 * @param handle A pointer to moal_handle
372 * @param mlist A pointer to multicast list
373 *
374 * @return total_mc_count
375 */
woal_copy_all_mc_list(moal_handle * handle,mlan_multicast_list * mlist)376 static int woal_copy_all_mc_list(moal_handle *handle,
377 mlan_multicast_list *mlist)
378 {
379 int i;
380 moal_private *priv = NULL;
381 #ifdef STA_SUPPORT
382 int mc_count = 0;
383 #endif
384 ENTER();
385 for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) {
386 #ifdef STA_SUPPORT
387 if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA) {
388 if (handle->priv[i]->media_connected == MTRUE) {
389 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
390 mc_count = priv->netdev->mc_count;
391 #else
392 mc_count = netdev_mc_count(priv->netdev);
393 #endif
394 if (mc_count)
395 woal_copy_mcast_addr(mlist,
396 priv->netdev);
397 }
398 }
399 #endif
400 }
401 PRINTM(MIOCTL, "total mc_count=%d\n", mlist->num_multicast_addr);
402 LEAVE();
403 return mlist->num_multicast_addr;
404 }
405
406 /**
407 * @brief Fill in wait queue
408 *
409 * @param priv A pointer to moal_private structure
410 * @param wait A pointer to wait_queue structure
411 * @param wait_option Wait option
412 *
413 * @return N/A
414 */
woal_fill_wait_queue(moal_private * priv,wait_queue * wait,t_u8 wait_option)415 static inline void woal_fill_wait_queue(moal_private *priv, wait_queue *wait,
416 t_u8 wait_option)
417 {
418 ENTER();
419 wait->start_time = jiffies;
420 wait->condition = MFALSE;
421 wait->wait_timeout = MFALSE;
422 switch (wait_option) {
423 case MOAL_NO_WAIT:
424 break;
425 case MOAL_IOCTL_WAIT:
426 init_waitqueue_head(&wait->wait);
427 break;
428 case MOAL_IOCTL_WAIT_TIMEOUT:
429 init_waitqueue_head(&wait->wait);
430 wait->wait_timeout = MTRUE;
431 break;
432 }
433 LEAVE();
434 return;
435 }
436
437 /**
438 * @brief Wait mlan ioctl complete
439 *
440 * @param priv A pointer to moal_private structure
441 * @param req A pointer to mlan_ioctl_req structure
442 * @param wait_option Wait option
443 *
444 * @return N/A
445 */
woal_wait_ioctl_complete(moal_private * priv,mlan_ioctl_req * req,t_u8 wait_option)446 static inline mlan_status woal_wait_ioctl_complete(moal_private *priv,
447 mlan_ioctl_req *req,
448 t_u8 wait_option)
449 {
450 mlan_status status;
451 wait_queue *wait = (wait_queue *)req->reserved_1;
452 unsigned long flags;
453
454 ENTER();
455
456 priv->phandle->ioctl_timeout = MFALSE;
457
458 switch (wait_option) {
459 case MOAL_NO_WAIT:
460 break;
461 case MOAL_IOCTL_WAIT:
462 while (wait_event_interruptible_exclusive(
463 wait->wait, wait->condition) == -ERESTARTSYS &&
464 wait->retry < MAX_RETRY_CNT) {
465 wait->retry++;
466 }
467 break;
468 case MOAL_IOCTL_WAIT_TIMEOUT:
469 wait_event_timeout(wait->wait, wait->condition,
470 MOAL_IOCTL_TIMEOUT);
471 break;
472 }
473 spin_lock_irqsave(&priv->phandle->driver_lock, flags);
474 if (wait->condition == MFALSE) {
475 if (wait_option == MOAL_IOCTL_WAIT_TIMEOUT) {
476 priv->phandle->ioctl_timeout = MTRUE;
477 PRINTM(MMSG,
478 "wlan: IOCTL timeout %p id=0x%x, sub_id=0x%x, wait_option=%d, action=%d\n",
479 req, req->req_id, (*(t_u32 *)req->pbuf),
480 wait_option, (int)req->action);
481 } else {
482 PRINTM(MMSG,
483 "wlan: IOCTL by signal %p id=0x%x, sub_id=0x%x, wait_option=%d, action=%d\n",
484 req, req->req_id, (*(t_u32 *)req->pbuf),
485 wait_option, (int)req->action);
486 }
487 req->reserved_1 = 0;
488 status = MLAN_STATUS_PENDING;
489 } else {
490 status = wait->status;
491 }
492 spin_unlock_irqrestore(&priv->phandle->driver_lock, flags);
493
494 LEAVE();
495 return status;
496 }
497
498 /**
499 * @brief CAC period block cmd handler
500 *
501 * @param priv A pointer to moal_private structure
502 * @param req A pointer to mlan_ioctl_req buffer
503 *
504 * @return MTRUE/MFALSE
505 */
woal_cac_period_block_cmd(moal_private * priv,pmlan_ioctl_req req)506 static inline t_bool woal_cac_period_block_cmd(moal_private *priv,
507 pmlan_ioctl_req req)
508 {
509 mlan_status ret = MFALSE;
510 t_u32 sub_command;
511
512 ENTER();
513 if (req == NULL || req->pbuf == NULL)
514 goto done;
515
516 sub_command = *(t_u32 *)req->pbuf;
517
518 switch (req->req_id) {
519 case MLAN_IOCTL_SCAN:
520 if (sub_command == MLAN_OID_SCAN_NORMAL ||
521 sub_command == MLAN_OID_SCAN_SPECIFIC_SSID ||
522 sub_command == MLAN_OID_SCAN_USER_CONFIG)
523 ret = MTRUE;
524 break;
525 case MLAN_IOCTL_BSS:
526 if (sub_command == MLAN_OID_BSS_STOP ||
527 sub_command == MLAN_OID_BSS_CHANNEL
528 /* sub_command == MLAN_OID_BSS_ROLE */)
529 ret = MTRUE;
530 #ifdef UAP_SUPPORT
531 else if (sub_command == MLAN_OID_UAP_BSS_CONFIG) {
532 mlan_ds_bss *bss = (mlan_ds_bss *)req->pbuf;
533 if (bss->param.bss_config.channel)
534 ret = MTRUE;
535 else
536 ret = MFALSE;
537 }
538 #endif
539 break;
540 case MLAN_IOCTL_RADIO_CFG:
541 if (sub_command == MLAN_OID_BAND_CFG ||
542 sub_command == MLAN_OID_REMAIN_CHAN_CFG)
543 ret = MTRUE;
544 break;
545 case MLAN_IOCTL_SNMP_MIB:
546 if (sub_command == MLAN_OID_SNMP_MIB_DOT11D)
547 ret = MTRUE;
548 #if defined(UAP_SUPPORT)
549 if (sub_command == MLAN_OID_SNMP_MIB_DOT11H)
550 ret = MTRUE;
551 #endif
552 break;
553 case MLAN_IOCTL_11D_CFG:
554 #ifdef STA_SUPPORT
555 if (sub_command == MLAN_OID_11D_CFG_ENABLE)
556 ret = MTRUE;
557 #endif
558 #ifdef UAP_SUPPORT
559 if (sub_command == MLAN_OID_11D_DOMAIN_INFO)
560 ret = MTRUE;
561 #endif
562 if (sub_command == MLAN_OID_11D_DOMAIN_INFO_EXT)
563 ret = MTRUE;
564 break;
565 case MLAN_IOCTL_MISC_CFG:
566 if (sub_command == MLAN_OID_MISC_REGION)
567 ret = MTRUE;
568 if (sub_command == MLAN_OID_MISC_HOST_CMD) {
569 phostcmd_header phostcmd;
570 t_u8 *ptlv_buf;
571 t_u16 tag, length;
572
573 phostcmd =
574 (phostcmd_header)((pmlan_ds_misc_cfg)req->pbuf)
575 ->param.hostcmd.cmd;
576 ptlv_buf = (t_u8 *)phostcmd + sizeof(hostcmd_header);
577 if (phostcmd->action == MLAN_ACT_SET) {
578 while (ptlv_buf <
579 (t_u8 *)phostcmd + phostcmd->size) {
580 tag = *(t_u16 *)ptlv_buf;
581 length = *(t_u16 *)(ptlv_buf + 2);
582 /* Check Blocking TLV here, should add
583 * more... */
584 if (tag == MRVL_CHANNELCONFIG_TLV_ID) {
585 ret = MTRUE;
586 break;
587 }
588 ptlv_buf +=
589 (length + MRVL_TLV_HEADER_SIZE);
590 }
591 }
592 }
593 break;
594 case MLAN_IOCTL_11H_CFG:
595 /* Prevent execute more than once */
596 if (sub_command == MLAN_OID_11H_CHANNEL_CHECK)
597 ret = MTRUE;
598 break;
599 default:
600 ret = MFALSE;
601 break;
602 }
603
604 done:
605 LEAVE();
606 return ret;
607 }
608
609 /********************************************************
610 Global Functions
611 ********************************************************/
612
613 /**
614 * @brief Send ioctl request to MLAN
615 *
616 * @param priv A pointer to moal_private structure
617 * @param req A pointer to mlan_ioctl_req buffer
618 * @param wait_option Wait option (MOAL_WAIT or MOAL_NO_WAIT)
619 *
620 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
621 * -- success, otherwise fail
622 */
woal_request_ioctl(moal_private * priv,mlan_ioctl_req * req,t_u8 wait_option)623 mlan_status woal_request_ioctl(moal_private *priv, mlan_ioctl_req *req,
624 t_u8 wait_option)
625 {
626 wait_queue *wait = NULL;
627 mlan_status status;
628 unsigned long flags;
629 t_u32 sub_command = 0;
630
631 ENTER();
632
633 if (!priv || !priv->phandle || !priv->phandle->pmlan_adapter || !req) {
634 PRINTM(MINFO,
635 "priv or priv->phandle or priv->phandle->pmlan_adapter or req is null\n");
636 LEAVE();
637 return MLAN_STATUS_FAILURE;
638 }
639
640 sub_command = *(t_u32 *)req->pbuf;
641
642 if (sub_command != MLAN_OID_GET_DEBUG_INFO &&
643 sub_command != MLAN_OID_MISC_WARM_RESET) {
644 if (priv->phandle->surprise_removed == MTRUE ||
645 priv->phandle->driver_status) {
646 PRINTM(MCMND,
647 "IOCTL is not allowed while the device is not present or hang\n");
648 LEAVE();
649 return MLAN_STATUS_FAILURE;
650 }
651 if (priv->phandle->is_suspended == MTRUE) {
652 PRINTM(MCMND, "IOCTL is not allowed while suspended\n");
653 LEAVE();
654 return MLAN_STATUS_FAILURE;
655 }
656 #ifdef MFG_CMD_SUPPORT
657 if (mfg_mode && sub_command != MLAN_OID_MISC_HOST_CMD) {
658 PRINTM(MCMND, "Only HOST_CMD allowed in MFG mode\n");
659 LEAVE();
660 return MLAN_STATUS_FAILURE;
661 }
662 #endif
663 }
664 /* For MLAN_OID_MISC_HOST_CMD, action is 0, "action set" is checked
665 * later */
666 if ((req->action == MLAN_ACT_SET || req->action == 0) &&
667 priv->phandle->cac_period == MTRUE) {
668 /* CAC checking period left to complete jiffies */
669 long cac_left_jiffies;
670
671 /* cac_left_jiffies will be negative if and only if
672 * event MLAN_EVENT_ID_DRV_MEAS_REPORT recieved from FW
673 * after CAC measure period ends,
674 * usually this could be considered as a FW bug
675 */
676 cac_left_jiffies =
677 priv->phandle->cac_timer_jiffies -
678 (jiffies - priv->phandle->meas_start_jiffies);
679 if (priv->phandle->cac_period_jiffies) {
680 cac_left_jiffies =
681 priv->phandle->cac_period_jiffies -
682 (jiffies - priv->phandle->meas_start_jiffies);
683 }
684 if (priv->phandle->cac_restart)
685 cac_left_jiffies = DEF_CAC_DWELL_TIME * HZ / 1000;
686 if (cac_left_jiffies < 0) {
687 /* Avoid driver hang in FW died during CAC measure
688 * period */
689 priv->phandle->cac_period = MFALSE;
690 PRINTM(MERROR,
691 "CAC measure period spends longer than scheduled time "
692 "or meas done event never received\n");
693 status = MLAN_STATUS_FAILURE;
694 #ifdef UAP_SUPPORT
695 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
696 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
697 if (priv->uap_host_based &&
698 moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
699 woal_cfg80211_dfs_vendor_event(
700 priv, event_dfs_cac_aborted,
701 &priv->chan);
702 #endif
703 #endif
704 #endif
705
706 goto done;
707 }
708
709 /* Check BSS START first */
710 if (sub_command == MLAN_OID_BSS_START) {
711 mlan_ds_bss *bss;
712 bss = (mlan_ds_bss *)req->pbuf;
713 /*
714 * Bss delay start after channel report received,
715 * not block the driver by delay executing. This is
716 * because a BSS_START cmd is always executed right
717 * after channel check issued.
718 */
719 if (priv->phandle->delay_bss_start == MFALSE) {
720 PRINTM(MMSG,
721 "Received BSS Start command during CAC period, delay executing %ld seconds\n",
722 cac_left_jiffies / HZ);
723 priv->phandle->delay_bss_start = MTRUE;
724 moal_memcpy_ext(
725 priv->phandle,
726 &priv->phandle->delay_ssid_bssid,
727 &bss->param.ssid_bssid,
728 sizeof(mlan_ssid_bssid),
729 sizeof(mlan_ssid_bssid));
730 /* TODO: return success to allow the half below
731 * of routines of which calling BSS start to
732 * execute
733 */
734 status = MLAN_STATUS_SUCCESS;
735 goto done;
736 } else {
737 /* TODO: not blocking it, just return failure */
738 PRINTM(MMSG,
739 "Only one BSS Start command allowed for delay executing!\n");
740 status = MLAN_STATUS_FAILURE;
741 goto done;
742 }
743 }
744 if (woal_cac_period_block_cmd(priv, req)) {
745 priv->phandle->meas_wait_q_woken = MFALSE;
746 PRINTM(MMSG,
747 "CAC check is on going... Blocking Command %ld seconds\n",
748 cac_left_jiffies / HZ);
749 /* blocking timeout set to 1.5 * CAC checking period
750 * left time */
751 wait_event_interruptible_timeout(
752 priv->phandle->meas_wait_q,
753 priv->phandle->meas_wait_q_woken,
754 cac_left_jiffies * 3 / 2);
755 }
756 }
757 #ifdef UAP_CFG80211
758 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
759 else if (priv->phandle->is_cac_timer_set &&
760 (req->action == MLAN_ACT_SET || req->action == 0)) {
761 if (woal_cac_period_block_cmd(priv, req)) {
762 PRINTM(MMSG,
763 "CAC check is on going... Blocking Command\n");
764 status = MLAN_STATUS_FAILURE;
765 goto done;
766 }
767 }
768 #endif
769 #endif
770 else if (priv->phandle->cac_period) {
771 PRINTM(MINFO, "Operation during CAC check period.\n");
772 }
773 wait = (wait_queue *)req->reserved_1;
774 req->bss_index = priv->bss_index;
775 if (wait_option)
776 woal_fill_wait_queue(priv, wait, wait_option);
777 else
778 req->reserved_1 = 0;
779
780 /* Call MLAN ioctl handle */
781 atomic_inc(&priv->phandle->ioctl_pending);
782 spin_lock_irqsave(&priv->phandle->ioctl_lock, flags);
783 status = mlan_ioctl(priv->phandle->pmlan_adapter, req);
784 spin_unlock_irqrestore(&priv->phandle->ioctl_lock, flags);
785 switch (status) {
786 case MLAN_STATUS_PENDING:
787 if (wait_option == MOAL_NO_WAIT)
788 PRINTM(MIOCTL, "IOCTL MOAL_NO_WAIT: %p\n", req);
789 else
790 PRINTM(MIOCTL,
791 "IOCTL pending: %p id=0x%x, sub_id=0x%x wait_option=%d, action=%d\n",
792 req, req->req_id, (*(t_u32 *)req->pbuf),
793 wait_option, (int)req->action);
794 /* Status pending, wake up main process */
795 queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
796
797 /* Wait for completion */
798 if (wait_option)
799 status = woal_wait_ioctl_complete(priv, req,
800 wait_option);
801 break;
802 case MLAN_STATUS_SUCCESS:
803 case MLAN_STATUS_FAILURE:
804 case MLAN_STATUS_RESOURCE:
805 if (req)
806 PRINTM(MIOCTL,
807 "IOCTL: %p id=0x%x, sub_id=0x%x wait_option=%d, action=%d status=%d\n",
808 req, req->req_id, (*(t_u32 *)req->pbuf),
809 wait_option, (int)req->action, status);
810 atomic_dec(&priv->phandle->ioctl_pending);
811 break;
812 default:
813 atomic_dec(&priv->phandle->ioctl_pending);
814 break;
815 }
816
817 done:
818 LEAVE();
819 return status;
820 }
821
822 /**
823 * @brief Send set MAC address request to MLAN
824 *
825 * @param priv A pointer to moal_private structure
826 * @param wait_option wait option
827 *
828 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
829 * -- success, otherwise fail
830 */
woal_request_set_mac_address(moal_private * priv,t_u8 wait_option)831 mlan_status woal_request_set_mac_address(moal_private *priv, t_u8 wait_option)
832 {
833 mlan_ioctl_req *req = NULL;
834 mlan_ds_bss *bss = NULL;
835 mlan_status status;
836 ENTER();
837
838 /* Allocate an IOCTL request buffer */
839 req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
840 if (req == NULL) {
841 status = MLAN_STATUS_FAILURE;
842 goto done;
843 }
844
845 /* Fill request buffer */
846 bss = (mlan_ds_bss *)req->pbuf;
847 bss->sub_command = MLAN_OID_BSS_MAC_ADDR;
848 moal_memcpy_ext(priv->phandle, &bss->param.mac_addr, priv->current_addr,
849 sizeof(mlan_802_11_mac_addr),
850 sizeof(mlan_802_11_mac_addr));
851 req->req_id = MLAN_IOCTL_BSS;
852 req->action = MLAN_ACT_SET;
853
854 /* Send IOCTL request to MLAN */
855 status = woal_request_ioctl(priv, req, wait_option);
856 if (status == MLAN_STATUS_FAILURE) {
857 PRINTM(MERROR,
858 "set mac address failed! status=%d, error_code=0x%x\n",
859 status, req->status_code);
860 } else {
861 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)
862 eth_hw_addr_set(priv->netdev, priv->current_addr);
863 #else
864 moal_memcpy_ext(priv->phandle, priv->netdev->dev_addr,
865 priv->current_addr, ETH_ALEN, ETH_ALEN);
866 #endif
867 HEXDUMP("priv->MacAddr:", priv->current_addr, ETH_ALEN);
868 }
869 done:
870 if (status != MLAN_STATUS_PENDING)
871 kfree(req);
872 LEAVE();
873 return status;
874 }
875
876 /**
877 * @brief Send multicast list request to MLAN
878 *
879 * @param priv A pointer to moal_private structure
880 * @param dev A pointer to net_device structure
881 *
882 * @return N/A
883 */
woal_request_set_multicast_list(moal_private * priv,struct net_device * dev)884 void woal_request_set_multicast_list(moal_private *priv, struct net_device *dev)
885 {
886 mlan_ioctl_req *req = NULL;
887 mlan_ds_bss *bss = NULL;
888 mlan_status status;
889 int mc_count = 0;
890
891 ENTER();
892
893 /* Allocate an IOCTL request buffer */
894 req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
895 if (req == NULL) {
896 PRINTM(MERROR, "%s:Fail to allocate ioctl req buffer\n",
897 __func__);
898 goto done;
899 }
900
901 /* Fill request buffer */
902 bss = (mlan_ds_bss *)req->pbuf;
903 bss->sub_command = MLAN_OID_BSS_MULTICAST_LIST;
904 req->req_id = MLAN_IOCTL_BSS;
905 req->action = MLAN_ACT_SET;
906 if (dev->flags & IFF_PROMISC) {
907 bss->param.multicast_list.mode = MLAN_PROMISC_MODE;
908 } else if (dev->flags & IFF_ALLMULTI) {
909 bss->param.multicast_list.mode = MLAN_ALL_MULTI_MODE;
910 } else {
911 bss->param.multicast_list.mode = MLAN_MULTICAST_MODE;
912 mc_count = woal_copy_all_mc_list(priv->phandle,
913 &bss->param.multicast_list);
914 if (mc_count > MLAN_MAX_MULTICAST_LIST_SIZE)
915 bss->param.multicast_list.mode = MLAN_ALL_MULTI_MODE;
916 }
917 PRINTM(MCMND, "%s set multicast_list\n", dev->name);
918 /* Send IOCTL request to MLAN */
919 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
920 if (status != MLAN_STATUS_PENDING)
921 kfree(req);
922 done:
923 LEAVE();
924 return;
925 }
926
927 /**
928 * @brief Send deauth command to MLAN
929 *
930 * @param priv A pointer to moal_private structure
931 * @param wait_option Wait option
932 * @param mac MAC address to deauthenticate
933 * @param reason code reason code to deauthenticate
934 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
935 * otherwise fail
936 */
woal_disconnect(moal_private * priv,t_u8 wait_option,t_u8 * mac,t_u16 reason_code)937 mlan_status woal_disconnect(moal_private *priv, t_u8 wait_option, t_u8 *mac,
938 t_u16 reason_code)
939 {
940 mlan_ioctl_req *req = NULL;
941 mlan_ds_bss *bss = NULL;
942 mlan_status status;
943
944 ENTER();
945
946 /* Allocate an IOCTL request buffer */
947 req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
948 if (req == NULL) {
949 status = MLAN_STATUS_FAILURE;
950 goto done;
951 }
952
953 /* Fill request buffer */
954 bss = (mlan_ds_bss *)req->pbuf;
955 bss->sub_command = MLAN_OID_BSS_STOP;
956 if (mac)
957 moal_memcpy_ext(priv->phandle,
958 &bss->param.deauth_param.mac_addr, mac,
959 sizeof(mlan_802_11_mac_addr),
960 sizeof(bss->param.deauth_param.mac_addr));
961 bss->param.deauth_param.reason_code = reason_code;
962 req->req_id = MLAN_IOCTL_BSS;
963 req->action = MLAN_ACT_SET;
964
965 /* Send IOCTL request to MLAN */
966 status = woal_request_ioctl(priv, req, wait_option);
967
968 done:
969 if (status != MLAN_STATUS_PENDING)
970 kfree(req);
971 #ifdef REASSOCIATION
972 priv->reassoc_required = MFALSE;
973 #endif /* REASSOCIATION */
974 priv->auto_assoc_priv.drv_assoc.status = MFALSE;
975 priv->auto_assoc_priv.drv_reconnect.status = MFALSE;
976 LEAVE();
977 return status;
978 }
979
980 #if defined(UAP_SUPPORT)
981 /**
982 * @brief Get non-global oper class
983 *
984 * @param priv Pointer to moal_private structure
985 * @param bw bandwidth
986 * @param channel channel
987 * @param oper_class pointer to oper_class
988
989 * @return non-global operclass
990 */
woal_priv_get_nonglobal_operclass_by_bw_channel(moal_private * priv,t_u8 bandwidth,t_u8 channel,t_u8 * oper_class)991 int woal_priv_get_nonglobal_operclass_by_bw_channel(moal_private *priv,
992 t_u8 bandwidth,
993 t_u8 channel,
994 t_u8 *oper_class)
995 {
996 int ret = 0;
997 mlan_ioctl_req *ioctl_req = NULL;
998 mlan_ds_misc_cfg *misc = NULL;
999 mlan_status status = MLAN_STATUS_SUCCESS;
1000
1001 ENTER();
1002
1003 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1004 if (ioctl_req == NULL) {
1005 ret = -ENOMEM;
1006 goto done;
1007 }
1008
1009 misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
1010 misc->sub_command = MLAN_OID_MISC_OPER_CLASS;
1011 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
1012 ioctl_req->action = MLAN_ACT_GET;
1013 misc->param.bw_chan_oper.bandwidth = bandwidth;
1014 misc->param.bw_chan_oper.channel = channel;
1015
1016 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1017 if (status != MLAN_STATUS_SUCCESS) {
1018 ret = -EFAULT;
1019 goto done;
1020 }
1021 *oper_class = misc->param.bw_chan_oper.oper_class;
1022
1023 done:
1024 if (status != MLAN_STATUS_PENDING)
1025 kfree(ioctl_req);
1026
1027 LEAVE();
1028 return ret;
1029 }
1030 #endif
1031
1032 /**
1033 * @brief Send bss_start command to MLAN
1034 *
1035 * @param priv A pointer to moal_private structure
1036 * @param wait_option Wait option
1037 * @param ssid_bssid A point to mlan_ssid_bssid structure
1038 *
1039 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
1040 * otherwise fail
1041 */
woal_bss_start(moal_private * priv,t_u8 wait_option,mlan_ssid_bssid * ssid_bssid)1042 mlan_status woal_bss_start(moal_private *priv, t_u8 wait_option,
1043 mlan_ssid_bssid *ssid_bssid)
1044 {
1045 mlan_ioctl_req *req = NULL;
1046 mlan_ds_bss *bss = NULL;
1047 mlan_status status;
1048
1049 ENTER();
1050
1051 /* Stop the O.S. TX queue When we are roaming */
1052 woal_stop_queue(priv->netdev);
1053 if (priv->media_connected == MFALSE) {
1054 if (netif_carrier_ok(priv->netdev))
1055 netif_carrier_off(priv->netdev);
1056 }
1057
1058 /* Allocate an IOCTL request buffer */
1059 req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
1060 if (req == NULL) {
1061 status = MLAN_STATUS_FAILURE;
1062 goto done;
1063 }
1064
1065 /* Fill request buffer */
1066 bss = (mlan_ds_bss *)req->pbuf;
1067 bss->sub_command = MLAN_OID_BSS_START;
1068 if (ssid_bssid)
1069 moal_memcpy_ext(priv->phandle, &bss->param.ssid_bssid,
1070 ssid_bssid, sizeof(mlan_ssid_bssid),
1071 sizeof(mlan_ssid_bssid));
1072 req->req_id = MLAN_IOCTL_BSS;
1073 req->action = MLAN_ACT_SET;
1074
1075 /* Send IOCTL request to MLAN */
1076 status = woal_request_ioctl(priv, req, wait_option);
1077 if (ssid_bssid)
1078 moal_memcpy_ext(priv->phandle, ssid_bssid,
1079 &bss->param.ssid_bssid, sizeof(mlan_ssid_bssid),
1080 sizeof(mlan_ssid_bssid));
1081 #ifdef STA_CFG80211
1082 #ifdef STA_SUPPORT
1083 priv->assoc_status = req->status_code;
1084 #endif
1085 #endif
1086 done:
1087 if (status != MLAN_STATUS_PENDING)
1088 kfree(req);
1089 LEAVE();
1090 return status;
1091 }
1092
1093 /**
1094 * @brief Get BSS info
1095 *
1096 * @param priv A pointer to moal_private structure
1097 * @param wait_option Wait option
1098 * @param bss_info A pointer to mlan_bss_info structure
1099 *
1100 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
1101 * success, otherwise fail
1102 */
woal_get_bss_info(moal_private * priv,t_u8 wait_option,mlan_bss_info * bss_info)1103 mlan_status woal_get_bss_info(moal_private *priv, t_u8 wait_option,
1104 mlan_bss_info *bss_info)
1105 {
1106 mlan_ioctl_req *req = NULL;
1107 mlan_ds_get_info *info = NULL;
1108 mlan_status status = MLAN_STATUS_SUCCESS;
1109 ENTER();
1110
1111 /* Allocate an IOCTL request buffer */
1112 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
1113 if (req == NULL) {
1114 PRINTM(MERROR,
1115 "Fail to allocate the buffer for get bss_info\n");
1116 status = MLAN_STATUS_FAILURE;
1117 goto done;
1118 }
1119
1120 /* Fill request buffer */
1121 info = (mlan_ds_get_info *)req->pbuf;
1122 info->sub_command = MLAN_OID_GET_BSS_INFO;
1123 req->req_id = MLAN_IOCTL_GET_INFO;
1124 req->action = MLAN_ACT_GET;
1125
1126 /* Send IOCTL request to MLAN */
1127 status = woal_request_ioctl(priv, req, wait_option);
1128 if (status == MLAN_STATUS_SUCCESS) {
1129 if (bss_info)
1130 moal_memcpy_ext(priv->phandle, bss_info,
1131 &info->param.bss_info,
1132 sizeof(mlan_bss_info),
1133 sizeof(mlan_bss_info));
1134 }
1135 done:
1136 if (status != MLAN_STATUS_PENDING)
1137 kfree(req);
1138 LEAVE();
1139 return status;
1140 }
1141
1142 /**
1143 * @brief Set/Get generic IE
1144 *
1145 * @param priv A pointer to moal_private structure
1146 * @param action Action set or get
1147 * @param ie Information element
1148 * @param ie_len Length of the IE
1149 * @param wait_option wait option
1150 *
1151 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
1152 */
woal_set_get_gen_ie(moal_private * priv,t_u32 action,t_u8 * ie,int * ie_len,t_u8 wait_option)1153 mlan_status woal_set_get_gen_ie(moal_private *priv, t_u32 action, t_u8 *ie,
1154 int *ie_len, t_u8 wait_option)
1155 {
1156 mlan_status ret = MLAN_STATUS_SUCCESS;
1157 mlan_ds_misc_cfg *misc = NULL;
1158 mlan_ioctl_req *req = NULL;
1159
1160 ENTER();
1161
1162 if ((action == MLAN_ACT_GET) && (ie == NULL || ie_len == NULL)) {
1163 ret = MLAN_STATUS_FAILURE;
1164 goto done;
1165 }
1166
1167 if (action == MLAN_ACT_SET && *ie_len > MAX_IE_SIZE) {
1168 ret = MLAN_STATUS_FAILURE;
1169 goto done;
1170 }
1171
1172 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1173 if (req == NULL) {
1174 ret = MLAN_STATUS_FAILURE;
1175 goto done;
1176 }
1177
1178 misc = (mlan_ds_misc_cfg *)req->pbuf;
1179 misc->sub_command = MLAN_OID_MISC_GEN_IE;
1180 req->req_id = MLAN_IOCTL_MISC_CFG;
1181 req->action = action;
1182 misc->param.gen_ie.type = MLAN_IE_TYPE_GEN_IE;
1183
1184 if (action == MLAN_ACT_SET) {
1185 misc->param.gen_ie.len = *ie_len;
1186 if (*ie_len)
1187 moal_memcpy_ext(priv->phandle,
1188 misc->param.gen_ie.ie_data, ie, *ie_len,
1189 MAX_IE_SIZE);
1190 }
1191
1192 ret = woal_request_ioctl(priv, req, wait_option);
1193 if (ret != MLAN_STATUS_SUCCESS)
1194 goto done;
1195
1196 if (action == MLAN_ACT_GET) {
1197 *ie_len = misc->param.gen_ie.len;
1198 if (*ie_len)
1199 moal_memcpy_ext(priv->phandle, ie,
1200 misc->param.gen_ie.ie_data, *ie_len,
1201 *ie_len);
1202 }
1203
1204 done:
1205 if (ret != MLAN_STATUS_PENDING)
1206 kfree(req);
1207 LEAVE();
1208 return ret;
1209 }
1210
1211 #ifdef STA_SUPPORT
1212 /**
1213 * @brief Set/Get retry count
1214 *
1215 * @param priv A pointer to moal_private structure
1216 * @param action Action set or get
1217 * @param wait_option Wait option
1218 * @param value Retry value
1219 *
1220 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
1221 * success, otherwise fail
1222 */
woal_set_get_retry(moal_private * priv,t_u32 action,t_u8 wait_option,int * value)1223 mlan_status woal_set_get_retry(moal_private *priv, t_u32 action,
1224 t_u8 wait_option, int *value)
1225 {
1226 mlan_ioctl_req *req = NULL;
1227 mlan_ds_snmp_mib *mib = NULL;
1228 mlan_status ret = MLAN_STATUS_SUCCESS;
1229
1230 ENTER();
1231
1232 /* Allocate an IOCTL request buffer */
1233 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
1234 if (req == NULL) {
1235 ret = MLAN_STATUS_FAILURE;
1236 goto done;
1237 }
1238
1239 /* Fill request buffer */
1240 mib = (mlan_ds_snmp_mib *)req->pbuf;
1241 mib->sub_command = MLAN_OID_SNMP_MIB_RETRY_COUNT;
1242 req->req_id = MLAN_IOCTL_SNMP_MIB;
1243 req->action = action;
1244
1245 if (action == MLAN_ACT_SET) {
1246 if (*value < MLAN_TX_RETRY_MIN || *value > MLAN_TX_RETRY_MAX) {
1247 ret = MLAN_STATUS_FAILURE;
1248 goto done;
1249 }
1250 mib->param.retry_count = *value;
1251 }
1252
1253 /* Send IOCTL request to MLAN */
1254 ret = woal_request_ioctl(priv, req, wait_option);
1255 if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
1256 *value = mib->param.retry_count;
1257 #ifdef STA_CFG80211
1258 /* If set is invoked from other than iw i.e iwconfig,
1259 * wiphy retry count should be updated as well */
1260 if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext) &&
1261 priv->wdev && priv->wdev->wiphy &&
1262 (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1263 (action == MLAN_ACT_SET)) {
1264 priv->wdev->wiphy->retry_long = (t_u8)*value;
1265 priv->wdev->wiphy->retry_short = (t_u8)*value;
1266 }
1267 #endif
1268
1269 done:
1270 if (ret != MLAN_STATUS_PENDING)
1271 kfree(req);
1272 LEAVE();
1273 return ret;
1274 }
1275
1276 /**
1277 * @brief Performs pre-warm-reset
1278 *
1279 * @param priv A pointer to moal_private structure
1280 *
1281 * @return 0 if successful else negative value
1282 */
woal_pre_warmreset(moal_private * priv)1283 int woal_pre_warmreset(moal_private *priv)
1284 {
1285 moal_handle *handle = priv->phandle;
1286 int ret = 0;
1287 int intf_num;
1288 #ifdef WIFI_DIRECT_SUPPORT
1289 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
1290 #if defined(STA_WEXT) || defined(UAP_WEXT)
1291 t_u8 bss_role = MLAN_BSS_ROLE_STA;
1292 #endif
1293 #endif
1294 #endif /* WIFI_DIRECT_SUPPORT */
1295
1296 ENTER();
1297 #ifdef USB
1298 #ifdef CONFIG_USB_SUSPEND
1299 if (IS_USB(handle->card_type) && handle->is_suspended &&
1300 woal_exit_usb_suspend(handle)) {
1301 PRINTM(MERROR, "Failed to resume the suspended device\n");
1302 LEAVE();
1303 return -EFAULT;
1304 }
1305 #endif /* CONFIG_USB_SUSPEND */
1306 #endif
1307 woal_cancel_cac_block(priv);
1308 /* Reset all interfaces */
1309 woal_reset_intf(priv, MOAL_IOCTL_WAIT, MTRUE);
1310 /* Initialize private structures */
1311 for (intf_num = 0; intf_num < handle->priv_num; intf_num++) {
1312 woal_init_priv(handle->priv[intf_num], MOAL_IOCTL_WAIT);
1313 #ifdef WIFI_DIRECT_SUPPORT
1314 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
1315 #if defined(STA_WEXT) || defined(UAP_WEXT)
1316 if ((handle->priv[intf_num]->bss_type ==
1317 MLAN_BSS_TYPE_WIFIDIRECT) &&
1318 (GET_BSS_ROLE(handle->priv[intf_num]) ==
1319 MLAN_BSS_ROLE_UAP)) {
1320 if (MLAN_STATUS_SUCCESS !=
1321 woal_bss_role_cfg(handle->priv[intf_num],
1322 MLAN_ACT_SET, MOAL_IOCTL_WAIT,
1323 &bss_role)) {
1324 ret = -EFAULT;
1325 goto done;
1326 }
1327 }
1328 #endif /* STA_WEXT || UAP_WEXT */
1329 #endif /* STA_SUPPORT && UAP_SUPPORT */
1330 #endif /* WIFI_DIRECT_SUPPORT */
1331 }
1332 woal_shutdown_fw(priv, MOAL_IOCTL_WAIT);
1333 #ifdef WIFI_DIRECT_SUPPORT
1334 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
1335 #if defined(STA_WEXT) || defined(UAP_WEXT)
1336 done:
1337 #endif /* STA_WEXT || UAP_WEXT */
1338 #endif /* STA_SUPPORT && UAP_SUPPORT */
1339 #endif /* WIFI_DIRECT_SUPPORT */
1340 LEAVE();
1341 return ret;
1342 }
1343
1344 /**
1345 * @brief warm reset
1346 *
1347 * @param priv A pointer to moal_private structure
1348 *
1349 * @return 0 success, otherwise failure
1350 */
woal_warmreset(moal_private * priv)1351 int woal_warmreset(moal_private *priv)
1352 {
1353 moal_handle *handle = priv->phandle;
1354 mlan_ioctl_req *req = NULL;
1355 mlan_ds_misc_cfg *misc = NULL;
1356 mlan_status status = MLAN_STATUS_SUCCESS;
1357 int ret = 0;
1358 int intf_num;
1359
1360 /* Restart the firmware */
1361 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1362 if (req) {
1363 misc = (mlan_ds_misc_cfg *)req->pbuf;
1364 misc->sub_command = MLAN_OID_MISC_WARM_RESET;
1365 misc->param.fw_reload = MTRUE;
1366 req->req_id = MLAN_IOCTL_MISC_CFG;
1367 req->action = MLAN_ACT_SET;
1368 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1369 if (status != MLAN_STATUS_SUCCESS) {
1370 PRINTM(MERROR, "warm reset failure!\n");
1371 ret = -EFAULT;
1372 if (status != MLAN_STATUS_PENDING)
1373 kfree(req);
1374 goto done;
1375 }
1376 kfree(req);
1377 }
1378 #ifdef USB
1379 if (IS_USB(handle->card_type) && handle->params.usb_aggr == 1) {
1380 /* Enable USB aggregation in FW */
1381 if (woal_usb_aggr_init(handle)) {
1382 PRINTM(MERROR, "usb aggr init fail\n");
1383 ret = -EFAULT;
1384 goto done;
1385 }
1386 }
1387 #endif
1388
1389 if (moal_extflg_isset(handle, EXT_AGGR_CTRL)) {
1390 /* Enable aggregation in FW */
1391 if (woal_init_aggr_ctrl(handle, MOAL_IOCTL_WAIT)) {
1392 PRINTM(MERROR, "Fail to init aggr ctrl\n");
1393 ret = -EFAULT;
1394 goto done;
1395 }
1396 }
1397
1398 /* Enable interfaces */
1399 for (intf_num = 0; intf_num < handle->priv_num; intf_num++) {
1400 netif_device_attach(handle->priv[intf_num]->netdev);
1401 woal_start_queue(handle->priv[intf_num]->netdev);
1402 }
1403 done:
1404 LEAVE();
1405 return ret;
1406 }
1407
1408 /**
1409 * @brief Set/Get RTS threshold
1410 *
1411 * @param priv A pointer to moal_private structure
1412 * @param action Action set or get
1413 * @param wait_option Wait option
1414 * @param value RTS threshold value
1415 *
1416 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
1417 * success, otherwise fail
1418 */
woal_set_get_rts(moal_private * priv,t_u32 action,t_u8 wait_option,int * value)1419 mlan_status woal_set_get_rts(moal_private *priv, t_u32 action, t_u8 wait_option,
1420 int *value)
1421 {
1422 mlan_ioctl_req *req = NULL;
1423 mlan_ds_snmp_mib *mib = NULL;
1424 mlan_status ret = MLAN_STATUS_SUCCESS;
1425
1426 ENTER();
1427
1428 /* Allocate an IOCTL request buffer */
1429 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
1430 if (req == NULL) {
1431 ret = MLAN_STATUS_FAILURE;
1432 goto done;
1433 }
1434
1435 /* Fill request buffer */
1436 mib = (mlan_ds_snmp_mib *)req->pbuf;
1437 mib->sub_command = MLAN_OID_SNMP_MIB_RTS_THRESHOLD;
1438 req->req_id = MLAN_IOCTL_SNMP_MIB;
1439 req->action = action;
1440
1441 if (action == MLAN_ACT_SET) {
1442 if (*value < MLAN_RTS_MIN_VALUE ||
1443 *value > MLAN_RTS_MAX_VALUE) {
1444 ret = MLAN_STATUS_FAILURE;
1445 goto done;
1446 }
1447 mib->param.rts_threshold = *value;
1448 }
1449
1450 /* Send IOCTL request to MLAN */
1451 ret = woal_request_ioctl(priv, req, wait_option);
1452 if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
1453 *value = mib->param.rts_threshold;
1454 #ifdef STA_CFG80211
1455 /* If set is invoked from other than iw i.e iwconfig,
1456 * wiphy RTS threshold should be updated as well */
1457 if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext) &&
1458 priv->wdev && priv->wdev->wiphy &&
1459 (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1460 (action == MLAN_ACT_SET))
1461 priv->wdev->wiphy->rts_threshold = *value;
1462 #endif
1463
1464 done:
1465 if (ret != MLAN_STATUS_PENDING)
1466 kfree(req);
1467 LEAVE();
1468 return ret;
1469 }
1470
1471 /**
1472 * @brief Set/Get Fragment threshold
1473 *
1474 * @param priv A pointer to moal_private structure
1475 * @param action Action set or get
1476 * @param wait_option Wait option
1477 * @param value Fragment threshold value
1478 *
1479 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
1480 * success, otherwise fail
1481 */
woal_set_get_frag(moal_private * priv,t_u32 action,t_u8 wait_option,int * value)1482 mlan_status woal_set_get_frag(moal_private *priv, t_u32 action,
1483 t_u8 wait_option, int *value)
1484 {
1485 mlan_ioctl_req *req = NULL;
1486 mlan_ds_snmp_mib *mib = NULL;
1487 mlan_status ret = MLAN_STATUS_SUCCESS;
1488
1489 ENTER();
1490
1491 /* Allocate an IOCTL request buffer */
1492 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
1493 if (req == NULL) {
1494 ret = MLAN_STATUS_FAILURE;
1495 goto done;
1496 }
1497
1498 /* Fill request buffer */
1499 mib = (mlan_ds_snmp_mib *)req->pbuf;
1500 mib->sub_command = MLAN_OID_SNMP_MIB_FRAG_THRESHOLD;
1501 req->req_id = MLAN_IOCTL_SNMP_MIB;
1502 req->action = action;
1503
1504 if (action == MLAN_ACT_SET) {
1505 if (*value < MLAN_FRAG_MIN_VALUE ||
1506 *value > MLAN_FRAG_MAX_VALUE) {
1507 ret = MLAN_STATUS_FAILURE;
1508 goto done;
1509 }
1510 mib->param.frag_threshold = *value;
1511 }
1512
1513 /* Send IOCTL request to MLAN */
1514 ret = woal_request_ioctl(priv, req, wait_option);
1515 if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
1516 *value = mib->param.frag_threshold;
1517 #ifdef STA_CFG80211
1518 /* If set is invoked from other than iw i.e iwconfig,
1519 * wiphy fragment threshold should be updated as well */
1520 if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext) &&
1521 priv->wdev && priv->wdev->wiphy &&
1522 (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1523 (action == MLAN_ACT_SET))
1524 priv->wdev->wiphy->frag_threshold = *value;
1525 #endif
1526
1527 done:
1528 if (ret != MLAN_STATUS_PENDING)
1529 kfree(req);
1530 LEAVE();
1531 return ret;
1532 }
1533
1534 /**
1535 * @brief Set/Get TX power
1536 *
1537 * @param priv A pointer to moal_private structure
1538 * @param action Action set or get
1539 * @param power_cfg A pinter to mlan_power_cfg_t structure
1540 *
1541 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
1542 * success, otherwise fail
1543 */
woal_set_get_tx_power(moal_private * priv,t_u32 action,mlan_power_cfg_t * power_cfg)1544 mlan_status woal_set_get_tx_power(moal_private *priv, t_u32 action,
1545 mlan_power_cfg_t *power_cfg)
1546 {
1547 mlan_ds_power_cfg *pcfg = NULL;
1548 mlan_ioctl_req *req = NULL;
1549 mlan_status ret = MLAN_STATUS_SUCCESS;
1550 ENTER();
1551
1552 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_power_cfg));
1553 if (req == NULL) {
1554 ret = MLAN_STATUS_FAILURE;
1555 goto done;
1556 }
1557 pcfg = (mlan_ds_power_cfg *)req->pbuf;
1558 pcfg->sub_command = MLAN_OID_POWER_CFG;
1559 req->req_id = MLAN_IOCTL_POWER_CFG;
1560 req->action = action;
1561 if (action == MLAN_ACT_SET && power_cfg)
1562 moal_memcpy_ext(priv->phandle, &pcfg->param.power_cfg,
1563 power_cfg, sizeof(mlan_power_cfg_t),
1564 sizeof(mlan_power_cfg_t));
1565
1566 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1567 if (ret != MLAN_STATUS_SUCCESS)
1568 goto done;
1569
1570 if (ret == MLAN_STATUS_SUCCESS && power_cfg)
1571 moal_memcpy_ext(priv->phandle, power_cfg,
1572 &pcfg->param.power_cfg,
1573 sizeof(mlan_power_cfg_t),
1574 sizeof(mlan_power_cfg_t));
1575
1576 done:
1577 if (ret != MLAN_STATUS_PENDING)
1578 kfree(req);
1579 LEAVE();
1580 return ret;
1581 }
1582
1583 /**
1584 * @brief Set/Get IEEE power management
1585 *
1586 * @param priv A pointer to moal_private structure
1587 * @param action Action set or get
1588 * @param disabled A pointer to disabled flag
1589 * @param power_type IEEE power type
1590 * @param wait_option wait option
1591 *
1592 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
1593 */
woal_set_get_power_mgmt(moal_private * priv,t_u32 action,int * disabled,int power_type,t_u8 wait_option)1594 mlan_status woal_set_get_power_mgmt(moal_private *priv, t_u32 action,
1595 int *disabled, int power_type,
1596 t_u8 wait_option)
1597 {
1598 mlan_status ret = MLAN_STATUS_SUCCESS;
1599 mlan_ioctl_req *req = NULL;
1600 mlan_ds_pm_cfg *pm_cfg = NULL;
1601
1602 ENTER();
1603
1604 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
1605 if (req == NULL) {
1606 ret = MLAN_STATUS_FAILURE;
1607 goto done;
1608 }
1609 pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
1610 pm_cfg->sub_command = MLAN_OID_PM_CFG_IEEE_PS;
1611 req->req_id = MLAN_IOCTL_PM_CFG;
1612 req->action = action;
1613
1614 if (action == MLAN_ACT_SET) {
1615 PRINTM(MINFO, "PS_MODE set power disabled=%d power type=%#x\n",
1616 *disabled, power_type);
1617 if (*disabled)
1618 pm_cfg->param.ps_mode = 0;
1619 else {
1620 /* Check not support case only (vwrq->disabled == FALSE)
1621 */
1622 if ((power_type & MW_POWER_TYPE) == MW_POWER_TIMEOUT) {
1623 PRINTM(MERROR,
1624 "Setting power timeout is not supported\n");
1625 ret = MLAN_STATUS_FAILURE;
1626 goto done;
1627 } else if ((power_type & MW_POWER_TYPE) ==
1628 MW_POWER_PERIOD) {
1629 PRINTM(MERROR,
1630 "Setting power period is not supported\n");
1631 ret = MLAN_STATUS_FAILURE;
1632 goto done;
1633 }
1634 pm_cfg->param.ps_mode = 1;
1635 }
1636 }
1637
1638 ret = woal_request_ioctl(priv, req, wait_option);
1639 if (ret != MLAN_STATUS_SUCCESS)
1640 goto done;
1641
1642 if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
1643 *disabled = pm_cfg->param.ps_mode;
1644
1645 #ifdef STA_CFG80211
1646 /* If set is invoked from other than iw i.e iwconfig,
1647 * wiphy IEEE power save mode should be updated */
1648 if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext) &&
1649 priv->wdev && (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1650 (action == MLAN_ACT_SET)) {
1651 if (*disabled)
1652 priv->wdev->ps = MFALSE;
1653 else
1654 priv->wdev->ps = MTRUE;
1655 }
1656 #endif
1657
1658 done:
1659 if (ret != MLAN_STATUS_PENDING)
1660 kfree(req);
1661 LEAVE();
1662 return ret;
1663 }
1664
1665 /**
1666 * @brief Set Country Code
1667 *
1668 * @param priv A pointer to moal_private structure
1669 * @param region A pointer to region string
1670 *
1671 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise
1672 * fail
1673 */
woal_set_countrycode(moal_private * priv,char * country)1674 static int woal_set_countrycode(moal_private *priv, char *country)
1675 {
1676 int ret = 0;
1677 mlan_ioctl_req *req = NULL;
1678 mlan_ds_misc_cfg *pcfg_misc = NULL;
1679 mlan_ds_misc_country_code *country_code = NULL;
1680 mlan_status status = MLAN_STATUS_SUCCESS;
1681
1682 ENTER();
1683
1684 /* Allocate an IOCTL request buffer */
1685 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1686 if (req == NULL) {
1687 ret = -ENOMEM;
1688 goto done;
1689 }
1690
1691 /* Fill request buffer */
1692 pcfg_misc = (mlan_ds_misc_cfg *)req->pbuf;
1693 country_code = &pcfg_misc->param.country_code;
1694 pcfg_misc->sub_command = MLAN_OID_MISC_COUNTRY_CODE;
1695 req->req_id = MLAN_IOCTL_MISC_CFG;
1696
1697 memset(country_code->country_code, 0, COUNTRY_CODE_LEN);
1698 moal_memcpy_ext(priv->phandle, country_code->country_code, country,
1699 COUNTRY_CODE_LEN - 1, COUNTRY_CODE_LEN - 1);
1700 req->action = MLAN_ACT_SET;
1701
1702 /* Send IOCTL request to MLAN */
1703 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1704 if (status != MLAN_STATUS_SUCCESS) {
1705 ret = -EFAULT;
1706 goto done;
1707 }
1708 done:
1709 if (status != MLAN_STATUS_PENDING)
1710 kfree(req);
1711
1712 LEAVE();
1713 return ret;
1714 }
1715
1716 /**
1717 * @brief Set region code
1718 *
1719 * @param priv A pointer to moal_private structure
1720 * @param region A pointer to region string
1721 *
1722 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise
1723 * fail
1724 */
woal_set_region_code(moal_private * priv,char * region)1725 mlan_status woal_set_region_code(moal_private *priv, char *region)
1726 {
1727 mlan_status ret = MLAN_STATUS_SUCCESS;
1728 mlan_ds_misc_cfg *cfg = NULL;
1729 mlan_ioctl_req *req = NULL;
1730
1731 ENTER();
1732 if (woal_is_country_code_supported(region))
1733 return woal_set_countrycode(priv, region);
1734
1735 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1736 if (req == NULL) {
1737 ret = MLAN_STATUS_FAILURE;
1738 goto done;
1739 }
1740 cfg = (mlan_ds_misc_cfg *)req->pbuf;
1741 cfg->sub_command = MLAN_OID_MISC_REGION;
1742 req->req_id = MLAN_IOCTL_MISC_CFG;
1743 req->action = MLAN_ACT_SET;
1744 cfg->param.region_code = region_string_2_region_code(region);
1745 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1746
1747 done:
1748 if (ret != MLAN_STATUS_PENDING)
1749 kfree(req);
1750 LEAVE();
1751 return ret;
1752 }
1753
1754 /**
1755 * @brief Set/Get data rate
1756 *
1757 * @param priv A pointer to moal_private structure
1758 * @param action Action set or get
1759 * @param datarate A pointer to mlan_rate_cfg_t structure
1760 *
1761 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
1762 */
woal_set_get_data_rate(moal_private * priv,t_u8 action,mlan_rate_cfg_t * datarate)1763 mlan_status woal_set_get_data_rate(moal_private *priv, t_u8 action,
1764 mlan_rate_cfg_t *datarate)
1765 {
1766 mlan_status ret = MLAN_STATUS_SUCCESS;
1767 mlan_ds_rate *rate = NULL;
1768 mlan_ioctl_req *req = NULL;
1769
1770 ENTER();
1771
1772 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
1773 if (req == NULL) {
1774 ret = MLAN_STATUS_FAILURE;
1775 goto done;
1776 }
1777
1778 rate = (mlan_ds_rate *)req->pbuf;
1779 rate->param.rate_cfg.rate_type = MLAN_RATE_VALUE;
1780 rate->sub_command = MLAN_OID_RATE_CFG;
1781 req->req_id = MLAN_IOCTL_RATE;
1782 req->action = action;
1783
1784 if (datarate && (action == MLAN_ACT_SET))
1785 moal_memcpy_ext(priv->phandle, &rate->param.rate_cfg, datarate,
1786 sizeof(mlan_rate_cfg_t),
1787 sizeof(mlan_rate_cfg_t));
1788
1789 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1790 if (ret == MLAN_STATUS_SUCCESS && datarate && action == MLAN_ACT_GET)
1791 moal_memcpy_ext(priv->phandle, datarate, &rate->param.rate_cfg,
1792 sizeof(mlan_rate_cfg_t),
1793 sizeof(mlan_rate_cfg_t));
1794
1795 done:
1796 if (ret != MLAN_STATUS_PENDING)
1797 kfree(req);
1798 LEAVE();
1799 return ret;
1800 }
1801
1802 /**
1803 * @brief Get assoc_resp buffer
1804 *
1805 * @param priv A pointer to moal_private structure
1806 * @param assoc_rsp A pointer to mlan_ds_misc_assoc_rsp structure
1807 * @param wait_option wait option
1808 *
1809 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
1810 */
woal_get_assoc_rsp(moal_private * priv,mlan_ds_misc_assoc_rsp * assoc_rsp,t_u8 wait_option)1811 mlan_status woal_get_assoc_rsp(moal_private *priv,
1812 mlan_ds_misc_assoc_rsp *assoc_rsp,
1813 t_u8 wait_option)
1814 {
1815 mlan_status ret = MLAN_STATUS_SUCCESS;
1816 mlan_ds_misc_cfg *misc = NULL;
1817 mlan_ioctl_req *req = NULL;
1818
1819 ENTER();
1820
1821 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1822 if (req == NULL) {
1823 PRINTM(MERROR, "Fail to allocate buffer for get assoc resp\n");
1824 ret = MLAN_STATUS_FAILURE;
1825 goto done;
1826 }
1827
1828 req->req_id = MLAN_IOCTL_MISC_CFG;
1829 misc = (pmlan_ds_misc_cfg)req->pbuf;
1830 misc->sub_command = MLAN_OID_MISC_ASSOC_RSP;
1831 req->action = MLAN_ACT_GET;
1832
1833 ret = woal_request_ioctl(priv, req, wait_option);
1834 if (ret == MLAN_STATUS_SUCCESS && assoc_rsp)
1835 moal_memcpy_ext(priv->phandle, assoc_rsp,
1836 &misc->param.assoc_resp,
1837 sizeof(mlan_ds_misc_assoc_rsp),
1838 sizeof(mlan_ds_misc_assoc_rsp));
1839
1840 done:
1841 if (ret != MLAN_STATUS_PENDING)
1842 kfree(req);
1843 LEAVE();
1844 return ret;
1845 }
1846
1847 /**
1848 * @brief Get assoc_req IEs buffer
1849 *
1850 * @param priv A pointer to moal_private structure
1851 * @param assoc_rsp A pointer to mlan_ds_misc_assoc_rsp structure
1852 * @param wait_option wait option
1853 *
1854 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
1855 */
woal_get_assoc_req(moal_private * priv,mlan_ds_misc_assoc_req * assoc_req,t_u8 wait_option)1856 mlan_status woal_get_assoc_req(moal_private *priv,
1857 mlan_ds_misc_assoc_req *assoc_req,
1858 t_u8 wait_option)
1859 {
1860 mlan_status ret = MLAN_STATUS_SUCCESS;
1861 mlan_ds_misc_cfg *misc = NULL;
1862 mlan_ioctl_req *req = NULL;
1863
1864 ENTER();
1865
1866 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1867 if (req == NULL) {
1868 PRINTM(MERROR,
1869 "Fail to allocate buffer for get assoc request\n");
1870 ret = MLAN_STATUS_FAILURE;
1871 goto done;
1872 }
1873
1874 req->req_id = MLAN_IOCTL_MISC_CFG;
1875 misc = (pmlan_ds_misc_cfg)req->pbuf;
1876 misc->sub_command = MLAN_OID_MISC_ASSOC_REQ;
1877 req->action = MLAN_ACT_GET;
1878
1879 ret = woal_request_ioctl(priv, req, wait_option);
1880 if (ret == MLAN_STATUS_SUCCESS && assoc_req)
1881 moal_memcpy_ext(priv->phandle, assoc_req,
1882 &misc->param.assoc_req,
1883 sizeof(mlan_ds_misc_assoc_req),
1884 sizeof(mlan_ds_misc_assoc_req));
1885
1886 done:
1887 if (ret != MLAN_STATUS_PENDING)
1888 kfree(req);
1889 LEAVE();
1890 return ret;
1891 }
1892
1893 #endif
1894
1895 /**
1896 * @brief Send get FW info request to MLAN
1897 *
1898 * @param priv A pointer to moal_private structure
1899 * @param wait_option Wait option
1900 * @param fw_info FW information
1901 *
1902 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
1903 * otherwise fail
1904 */
woal_request_get_fw_info(moal_private * priv,t_u8 wait_option,mlan_fw_info * fw_info)1905 mlan_status woal_request_get_fw_info(moal_private *priv, t_u8 wait_option,
1906 mlan_fw_info *fw_info)
1907 {
1908 mlan_ioctl_req *req = NULL;
1909 mlan_ds_get_info *info;
1910 mlan_status status;
1911 ENTER();
1912 memset(priv->current_addr, 0xff, ETH_ALEN);
1913
1914 /* Allocate an IOCTL request buffer */
1915 req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(
1916 sizeof(mlan_ds_get_info));
1917 if (req == NULL) {
1918 status = MLAN_STATUS_FAILURE;
1919 goto done;
1920 }
1921
1922 /* Fill request buffer */
1923 info = (mlan_ds_get_info *)req->pbuf;
1924 req->req_id = MLAN_IOCTL_GET_INFO;
1925 req->action = MLAN_ACT_GET;
1926 info->sub_command = MLAN_OID_GET_FW_INFO;
1927
1928 /* Send IOCTL request to MLAN */
1929 status = woal_request_ioctl(priv, req, wait_option);
1930 if (status == MLAN_STATUS_SUCCESS) {
1931 priv->phandle->fw_release_number = info->param.fw_info.fw_ver;
1932 priv->phandle->fw_hotfix_version =
1933 info->param.fw_info.hotfix_version;
1934 priv->phandle->fw_ecsa_enable = info->param.fw_info.ecsa_enable;
1935 priv->phandle->fw_bands = info->param.fw_info.fw_bands;
1936 priv->phandle->fw_getlog_enable =
1937 info->param.fw_info.getlog_enable;
1938 priv->phandle->fw_roaming_support =
1939 info->param.fw_info.fw_roaming_support;
1940 if (priv->current_addr[0] == 0xff)
1941 moal_memcpy_ext(priv->phandle, priv->current_addr,
1942 &info->param.fw_info.mac_addr,
1943 sizeof(mlan_802_11_mac_addr), ETH_ALEN);
1944 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)
1945 eth_hw_addr_set(priv->netdev, priv->current_addr);
1946 #else
1947 moal_memcpy_ext(priv->phandle, priv->netdev->dev_addr,
1948 priv->current_addr, ETH_ALEN, ETH_ALEN);
1949 #endif
1950 if (fw_info)
1951 moal_memcpy_ext(priv->phandle, fw_info,
1952 &info->param.fw_info,
1953 sizeof(mlan_fw_info),
1954 sizeof(mlan_fw_info));
1955 DBG_HEXDUMP(MCMD_D, "mac", priv->current_addr, 6);
1956 } else
1957 PRINTM(MERROR,
1958 "get fw info failed! status=%d, error_code=0x%x\n",
1959 status, req->status_code);
1960 done:
1961 if (status != MLAN_STATUS_PENDING)
1962 kfree(req);
1963 LEAVE();
1964 return status;
1965 }
1966
1967 /**
1968 * @brief Get current channel of active interface
1969 *
1970 * @param priv A pointer to moal_private
1971 * @param channel A pointer to chan_band_info structure
1972 *
1973 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1974 */
woal_get_active_intf_channel(moal_private * priv,chan_band_info * channel)1975 mlan_status woal_get_active_intf_channel(moal_private *priv,
1976 chan_band_info *channel)
1977 {
1978 moal_handle *handle = priv->phandle;
1979 int i;
1980 for (i = 0; i < handle->priv_num; i++) {
1981 #ifdef STA_SUPPORT
1982 if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA) {
1983 if (handle->priv[i]->media_connected == MTRUE)
1984 return woal_get_sta_channel(handle->priv[i],
1985 MOAL_IOCTL_WAIT,
1986 channel);
1987 }
1988 #endif
1989 #ifdef UAP_SUPPORT
1990 if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_UAP) {
1991 if (handle->priv[i]->bss_started == MTRUE)
1992 return woal_set_get_ap_channel(handle->priv[i],
1993 MLAN_ACT_GET,
1994 MOAL_IOCTL_WAIT,
1995 channel);
1996 }
1997 #endif
1998 }
1999 return MLAN_STATUS_FAILURE;
2000 }
2001
2002 #ifdef STA_SUPPORT
2003 /**
2004 * @brief Send get ext cap info request to MLAN
2005 *
2006 * @param priv A pointer to moal_private structure
2007 * @param buf data buffer
2008 * @param len data buffer length
2009 *
2010 * @return number of bytes of extended capability -- success,
2011 * otherwise error
2012 */
woal_request_extcap(moal_private * priv,t_u8 * buf,t_u8 len)2013 int woal_request_extcap(moal_private *priv, t_u8 *buf, t_u8 len)
2014 {
2015 int ret = 0;
2016 mlan_ioctl_req *req = NULL;
2017 mlan_ds_misc_cfg *cfg = NULL;
2018 mlan_status status = MLAN_STATUS_SUCCESS;
2019
2020 ENTER();
2021 if (buf == NULL || len <= 0 || len < sizeof(ExtCap_t)) {
2022 ret = -EINVAL;
2023 goto out;
2024 }
2025 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2026 if (req == NULL) {
2027 ret = -ENOMEM;
2028 goto out;
2029 }
2030 cfg = (mlan_ds_misc_cfg *)req->pbuf;
2031 cfg->sub_command = MLAN_OID_MISC_EXT_CAP_CFG;
2032 req->req_id = MLAN_IOCTL_MISC_CFG;
2033 req->action = MLAN_ACT_GET;
2034 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2035 if (status != MLAN_STATUS_SUCCESS) {
2036 ret = -EFAULT;
2037 goto out;
2038 }
2039 memset(buf, 0, len);
2040 moal_memcpy_ext(priv->phandle, buf, &cfg->param.ext_cap,
2041 sizeof(ExtCap_t), len);
2042 ret = sizeof(ExtCap_t);
2043 out:
2044 if (status != MLAN_STATUS_PENDING)
2045 kfree(req);
2046 LEAVE();
2047 return ret;
2048 }
2049 #endif
2050
2051 /**
2052 * @brief Get debug info
2053 *
2054 * @param priv A pointer to moal_private structure
2055 * @param wait_option Wait option
2056 * @param debug_info A pointer to mlan_debug_info structure
2057 *
2058 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
2059 * success, otherwise fail
2060 */
woal_get_debug_info(moal_private * priv,t_u8 wait_option,mlan_debug_info * debug_info)2061 mlan_status woal_get_debug_info(moal_private *priv, t_u8 wait_option,
2062 mlan_debug_info *debug_info)
2063 {
2064 mlan_ioctl_req *req = NULL;
2065 mlan_ds_get_info *info = NULL;
2066 mlan_status status = MLAN_STATUS_SUCCESS;
2067 ENTER();
2068
2069 /* Allocate an IOCTL request buffer */
2070 req = woal_alloc_mlan_ioctl_req(sizeof(t_u32) +
2071 sizeof(mlan_debug_info));
2072 if (req == NULL) {
2073 status = MLAN_STATUS_FAILURE;
2074 goto done;
2075 }
2076
2077 /* Fill request buffer */
2078 info = (mlan_ds_get_info *)req->pbuf;
2079 info->sub_command = MLAN_OID_GET_DEBUG_INFO;
2080 req->req_id = MLAN_IOCTL_GET_INFO;
2081 req->action = MLAN_ACT_GET;
2082
2083 /* Send IOCTL request to MLAN */
2084 status = woal_request_ioctl(priv, req, wait_option);
2085 if (status == MLAN_STATUS_SUCCESS) {
2086 if (debug_info) {
2087 moal_memcpy_ext(priv->phandle, debug_info,
2088 &info->param.debug_info,
2089 sizeof(mlan_debug_info),
2090 sizeof(mlan_debug_info));
2091 }
2092 }
2093 done:
2094 if (status != MLAN_STATUS_PENDING)
2095 kfree(req);
2096 LEAVE();
2097 return status;
2098 }
2099
2100 #if defined(STA_WEXT) || defined(UAP_WEXT)
2101 /**
2102 * @brief host command ioctl function
2103 *
2104 * @param priv A pointer to moal_private structure
2105 * @param wrq A pointer to iwreq structure
2106 * @return 0 --success, otherwise fail
2107 */
woal_host_command(moal_private * priv,struct iwreq * wrq)2108 int woal_host_command(moal_private *priv, struct iwreq *wrq)
2109 {
2110 HostCmd_Header cmd_header;
2111 int ret = 0;
2112 mlan_ds_misc_cfg *misc = NULL;
2113 mlan_ioctl_req *req = NULL;
2114 mlan_status status = MLAN_STATUS_SUCCESS;
2115
2116 ENTER();
2117
2118 /* Sanity check */
2119 if (wrq->u.data.pointer == NULL) {
2120 PRINTM(MERROR, "hostcmd IOCTL corrupt data\n");
2121 ret = -EINVAL;
2122 goto done;
2123 }
2124 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2125 if (req == NULL) {
2126 ret = -ENOMEM;
2127 goto done;
2128 }
2129 misc = (mlan_ds_misc_cfg *)req->pbuf;
2130 memset(&cmd_header, 0, sizeof(cmd_header));
2131
2132 /* get command header */
2133 if (copy_from_user(&cmd_header, wrq->u.data.pointer,
2134 sizeof(HostCmd_Header))) {
2135 PRINTM(MERROR, "copy from user failed: Host command header\n");
2136 ret = -EFAULT;
2137 goto done;
2138 }
2139 misc->param.hostcmd.len = woal_le16_to_cpu(cmd_header.size);
2140
2141 PRINTM(MINFO, "Host command len = %u\n", misc->param.hostcmd.len);
2142
2143 if (!misc->param.hostcmd.len ||
2144 misc->param.hostcmd.len > MRVDRV_SIZE_OF_CMD_BUFFER) {
2145 PRINTM(MERROR, "Invalid data buffer length\n");
2146 ret = -EINVAL;
2147 goto done;
2148 }
2149
2150 /* get the whole command from user */
2151 if (copy_from_user(misc->param.hostcmd.cmd, wrq->u.data.pointer,
2152 woal_le16_to_cpu(cmd_header.size))) {
2153 PRINTM(MERROR, "copy from user failed\n");
2154 ret = -EFAULT;
2155 goto done;
2156 }
2157 misc->sub_command = MLAN_OID_MISC_HOST_CMD;
2158 req->req_id = MLAN_IOCTL_MISC_CFG;
2159
2160 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2161 if (status != MLAN_STATUS_SUCCESS) {
2162 ret = -EFAULT;
2163 goto done;
2164 }
2165 if (copy_to_user(wrq->u.data.pointer, (t_u8 *)misc->param.hostcmd.cmd,
2166 misc->param.hostcmd.len)) {
2167 ret = -EFAULT;
2168 goto done;
2169 }
2170 wrq->u.data.length = misc->param.hostcmd.len;
2171 done:
2172 if (status != MLAN_STATUS_PENDING)
2173 kfree(req);
2174 LEAVE();
2175 return ret;
2176 }
2177 #endif
2178
2179 #if defined(WIFI_DIRECT_SUPPORT) || defined(UAP_SUPPORT)
2180 /**
2181 * @brief host command ioctl function
2182 *
2183 * @param dev A pointer to net_device structure
2184 * @param req A pointer to ifreq structure
2185 * @return 0 --success, otherwise fail
2186 */
2187 /********* format of ifr_data *************/
2188 /* buf_len + Hostcmd_body */
2189 /* buf_len: 4 bytes */
2190 /* the length of the buf which */
2191 /* can be used to return data */
2192 /* to application */
2193 /* Hostcmd_body */
2194 /*******************************************/
woal_hostcmd_ioctl(struct net_device * dev,struct ifreq * req)2195 int woal_hostcmd_ioctl(struct net_device *dev, struct ifreq *req)
2196 {
2197 moal_private *priv = (moal_private *)netdev_priv(dev);
2198 t_u32 buf_len = 0;
2199 HostCmd_Header cmd_header;
2200 int ret = 0;
2201 mlan_ds_misc_cfg *misc = NULL;
2202 mlan_ioctl_req *ioctl_req = NULL;
2203 mlan_status status = MLAN_STATUS_SUCCESS;
2204
2205 ENTER();
2206
2207 /* Sanity check */
2208 if (req->ifr_data == NULL) {
2209 PRINTM(MERROR, "uap_hostcmd_ioctl() corrupt data\n");
2210 ret = -EFAULT;
2211 goto done;
2212 }
2213
2214 if (copy_from_user(&buf_len, req->ifr_data, sizeof(buf_len))) {
2215 PRINTM(MERROR, "Copy from user failed\n");
2216 ret = -EFAULT;
2217 goto done;
2218 }
2219
2220 memset(&cmd_header, 0, sizeof(cmd_header));
2221
2222 /* get command header */
2223 if (copy_from_user(&cmd_header, req->ifr_data + sizeof(buf_len),
2224 sizeof(HostCmd_Header))) {
2225 PRINTM(MERROR, "Copy from user failed\n");
2226 ret = -EFAULT;
2227 goto done;
2228 }
2229
2230 PRINTM(MINFO, "Host command len = %d\n",
2231 woal_le16_to_cpu(cmd_header.size));
2232
2233 if (woal_le16_to_cpu(cmd_header.size) > MRVDRV_SIZE_OF_CMD_BUFFER) {
2234 ret = -EINVAL;
2235 goto done;
2236 }
2237
2238 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2239 if (ioctl_req == NULL) {
2240 ret = -ENOMEM;
2241 goto done;
2242 }
2243 misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
2244
2245 misc->param.hostcmd.len = woal_le16_to_cpu(cmd_header.size);
2246
2247 /* get the whole command from user */
2248 if (copy_from_user(misc->param.hostcmd.cmd,
2249 req->ifr_data + sizeof(buf_len),
2250 misc->param.hostcmd.len)) {
2251 PRINTM(MERROR, "copy from user failed\n");
2252 ret = -EFAULT;
2253 goto done;
2254 }
2255 misc->sub_command = MLAN_OID_MISC_HOST_CMD;
2256 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
2257
2258 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2259 if (status != MLAN_STATUS_SUCCESS) {
2260 ret = -EFAULT;
2261 goto done;
2262 }
2263 if (misc->param.hostcmd.len > buf_len) {
2264 PRINTM(MERROR,
2265 "buf_len is too small, resp_len=%d, buf_len=%d\n",
2266 (int)misc->param.hostcmd.len, (int)buf_len);
2267 ret = -EFAULT;
2268 goto done;
2269 }
2270 if (copy_to_user(req->ifr_data + sizeof(buf_len),
2271 (t_u8 *)misc->param.hostcmd.cmd,
2272 misc->param.hostcmd.len)) {
2273 ret = -EFAULT;
2274 goto done;
2275 }
2276 done:
2277 if (status != MLAN_STATUS_PENDING)
2278 kfree(ioctl_req);
2279 LEAVE();
2280 return ret;
2281 }
2282 #endif
2283
2284 /**
2285 * @brief CUSTOM_IE ioctl handler
2286 *
2287 * @param dev A pointer to net_device structure
2288 * @param req A pointer to ifreq structure
2289 * @return 0 --success, otherwise fail
2290 */
woal_custom_ie_ioctl(struct net_device * dev,struct ifreq * req)2291 int woal_custom_ie_ioctl(struct net_device *dev, struct ifreq *req)
2292 {
2293 moal_private *priv = (moal_private *)netdev_priv(dev);
2294 mlan_ioctl_req *ioctl_req = NULL;
2295 mlan_ds_misc_cfg *misc = NULL;
2296 mlan_ds_misc_custom_ie *pcustom_ie = NULL;
2297 int ret = 0;
2298 mlan_status status = MLAN_STATUS_SUCCESS;
2299 gfp_t flag;
2300
2301 ENTER();
2302
2303 /* Sanity check */
2304 if (req->ifr_data == NULL) {
2305 PRINTM(MERROR, "woal_custom_ie_ioctl() corrupt data\n");
2306 ret = -EFAULT;
2307 goto done;
2308 }
2309
2310 flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
2311 pcustom_ie = kzalloc(sizeof(mlan_ds_misc_custom_ie), flag);
2312 if (!pcustom_ie) {
2313 ret = -ENOMEM;
2314 goto done;
2315 }
2316
2317 if (copy_from_user(pcustom_ie, req->ifr_data,
2318 sizeof(mlan_ds_misc_custom_ie))) {
2319 PRINTM(MERROR, "Copy from user failed\n");
2320 ret = -EFAULT;
2321 goto done;
2322 }
2323
2324 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2325 if (ioctl_req == NULL) {
2326 ret = -ENOMEM;
2327 goto done;
2328 }
2329
2330 misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
2331 misc->sub_command = MLAN_OID_MISC_CUSTOM_IE;
2332 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
2333 if ((pcustom_ie->len == 0) ||
2334 (pcustom_ie->len == sizeof(pcustom_ie->ie_data_list[0].ie_index)))
2335 ioctl_req->action = MLAN_ACT_GET;
2336 else
2337 ioctl_req->action = MLAN_ACT_SET;
2338
2339 moal_memcpy_ext(priv->phandle, &misc->param.cust_ie, pcustom_ie,
2340 sizeof(mlan_ds_misc_custom_ie),
2341 sizeof(mlan_ds_misc_custom_ie));
2342
2343 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2344 if (status != MLAN_STATUS_SUCCESS) {
2345 ret = -EFAULT;
2346 goto done;
2347 }
2348
2349 if (ioctl_req->action == MLAN_ACT_GET) {
2350 if (copy_to_user(req->ifr_data, &misc->param.cust_ie,
2351 sizeof(mlan_ds_misc_custom_ie))) {
2352 PRINTM(MERROR, "Copy to user failed!\n");
2353 ret = -EFAULT;
2354 goto done;
2355 }
2356 } else if (ioctl_req->status_code == MLAN_ERROR_IOCTL_FAIL) {
2357 /* send a separate error code to indicate error from driver */
2358 ret = EFAULT;
2359 }
2360
2361 done:
2362 if (status != MLAN_STATUS_PENDING)
2363 kfree(ioctl_req);
2364 kfree(pcustom_ie);
2365 LEAVE();
2366 return ret;
2367 }
2368
2369 /**
2370 * @brief send raw data packet ioctl function
2371 *
2372 * @param dev A pointer to net_device structure
2373 * @param req A pointer to ifreq structure
2374 * @return 0 --success, otherwise fail
2375 */
woal_send_host_packet(struct net_device * dev,struct ifreq * req)2376 int woal_send_host_packet(struct net_device *dev, struct ifreq *req)
2377 {
2378 moal_private *priv = (moal_private *)netdev_priv(dev);
2379 t_u32 packet_len = 0;
2380 int ret = 0;
2381 pmlan_buffer pmbuf = NULL;
2382 mlan_status status;
2383
2384 ENTER();
2385
2386 if (!priv || !priv->phandle) {
2387 PRINTM(MERROR, "priv or handle is NULL\n");
2388 ret = -EFAULT;
2389 goto done;
2390 }
2391
2392 /* Sanity check */
2393 if (req->ifr_data == NULL) {
2394 PRINTM(MERROR, "woal_send_host_packet() corrupt data\n");
2395 ret = -EFAULT;
2396 goto done;
2397 }
2398
2399 if (copy_from_user(&packet_len, req->ifr_data, sizeof(packet_len))) {
2400 PRINTM(MERROR, "Copy from user failed\n");
2401 ret = -EFAULT;
2402 goto done;
2403 }
2404 #define PACKET_HEADER_LEN 8
2405 #define MV_ETH_FRAME_LEN 1514
2406 if (packet_len > MV_ETH_FRAME_LEN) {
2407 PRINTM(MERROR, "Invalid packet length %d\n", packet_len);
2408 ret = -EFAULT;
2409 goto done;
2410 }
2411 pmbuf = woal_alloc_mlan_buffer(
2412 priv->phandle, (int)(MLAN_MIN_DATA_HEADER_LEN +
2413 (int)packet_len + PACKET_HEADER_LEN));
2414 if (!pmbuf) {
2415 PRINTM(MERROR, "Fail to allocate mlan_buffer\n");
2416 ret = -ENOMEM;
2417 goto done;
2418 }
2419 pmbuf->data_offset = MLAN_MIN_DATA_HEADER_LEN;
2420
2421 /* get whole packet and header */
2422 if (copy_from_user(pmbuf->pbuf + pmbuf->data_offset,
2423 req->ifr_data + sizeof(packet_len),
2424 PACKET_HEADER_LEN + packet_len)) {
2425 PRINTM(MERROR, "Copy from user failed\n");
2426 ret = -EFAULT;
2427 woal_free_mlan_buffer(priv->phandle, pmbuf);
2428 goto done;
2429 }
2430 pmbuf->data_len = PACKET_HEADER_LEN + packet_len;
2431 pmbuf->buf_type = MLAN_BUF_TYPE_RAW_DATA;
2432 pmbuf->bss_index = priv->bss_index;
2433
2434 status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf);
2435 switch (status) {
2436 case MLAN_STATUS_PENDING:
2437 atomic_inc(&priv->phandle->tx_pending);
2438 queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
2439 break;
2440 case MLAN_STATUS_SUCCESS:
2441 woal_free_mlan_buffer(priv->phandle, pmbuf);
2442 break;
2443 case MLAN_STATUS_FAILURE:
2444 default:
2445 woal_free_mlan_buffer(priv->phandle, pmbuf);
2446 ret = -EFAULT;
2447 break;
2448 }
2449 done:
2450 LEAVE();
2451 return ret;
2452 }
2453
2454 #if defined(UAP_WEXT)
2455 /**
2456 * @brief Set/Get CUSTOM_IE ioctl handler
2457 *
2458 * @param priv A pointer to moal_private structure
2459 * @param mask Mask to set or clear from caller
2460 * @param ie IE buffer to set for beacon
2461 * @param ie_len Length of the IE
2462 *
2463 * @return 0 --success, otherwise fail
2464 */
woal_set_get_custom_ie(moal_private * priv,t_u16 mask,t_u8 * ie,int ie_len)2465 int woal_set_get_custom_ie(moal_private *priv, t_u16 mask, t_u8 *ie, int ie_len)
2466 {
2467 mlan_ioctl_req *ioctl_req = NULL;
2468 mlan_ds_misc_cfg *misc = NULL;
2469 mlan_ds_misc_custom_ie *misc_ie = NULL;
2470 int ret = 0;
2471 custom_ie *pcust_bcn_ie = NULL;
2472 mlan_status status = MLAN_STATUS_SUCCESS;
2473
2474 ENTER();
2475
2476 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2477 if (ioctl_req == NULL) {
2478 LEAVE();
2479 return -ENOMEM;
2480 }
2481
2482 misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
2483 misc->sub_command = MLAN_OID_MISC_CUSTOM_IE;
2484 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
2485 ioctl_req->action = MLAN_ACT_SET;
2486 misc_ie = &misc->param.cust_ie;
2487
2488 misc_ie->type = TLV_TYPE_MGMT_IE;
2489 misc_ie->len = (sizeof(custom_ie) - MAX_IE_SIZE) + ie_len;
2490 pcust_bcn_ie = misc_ie->ie_data_list;
2491 pcust_bcn_ie->ie_index = 0xffff;
2492 pcust_bcn_ie->mgmt_subtype_mask = mask;
2493 pcust_bcn_ie->ie_length = ie_len;
2494 moal_memcpy_ext(priv->phandle, pcust_bcn_ie->ie_buffer, ie, ie_len,
2495 MAX_IE_SIZE);
2496
2497 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2498 if (status != MLAN_STATUS_SUCCESS)
2499 ret = -EFAULT;
2500
2501 if (status != MLAN_STATUS_PENDING)
2502 kfree(ioctl_req);
2503 LEAVE();
2504 return ret;
2505 }
2506 #endif /* defined(HOST_TXRX_MGMT_FRAME) && defined(UAP_WEXT) */
2507
2508 /**
2509 * @brief TDLS configuration ioctl handler
2510 *
2511 * @param dev A pointer to net_device structure
2512 * @param req A pointer to ifreq structure
2513 * @return 0 --success, otherwise fail
2514 */
woal_tdls_config_ioctl(struct net_device * dev,struct ifreq * req)2515 int woal_tdls_config_ioctl(struct net_device *dev, struct ifreq *req)
2516 {
2517 moal_private *priv = (moal_private *)netdev_priv(dev);
2518 mlan_ioctl_req *ioctl_req = NULL;
2519 mlan_ds_misc_cfg *misc = NULL;
2520 mlan_ds_misc_tdls_config *tdls_data = NULL;
2521 int ret = 0;
2522 mlan_status status = MLAN_STATUS_SUCCESS;
2523 gfp_t flag;
2524
2525 ENTER();
2526
2527 /* Sanity check */
2528 if (req->ifr_data == NULL) {
2529 PRINTM(MERROR, "woal_tdls_config_ioctl() corrupt data\n");
2530 ret = -EFAULT;
2531 goto done;
2532 }
2533 flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
2534 tdls_data = kzalloc(sizeof(mlan_ds_misc_tdls_config), flag);
2535 if (!tdls_data) {
2536 ret = -ENOMEM;
2537 goto done;
2538 }
2539
2540 if (copy_from_user(tdls_data, req->ifr_data,
2541 sizeof(mlan_ds_misc_tdls_config))) {
2542 PRINTM(MERROR, "Copy from user failed\n");
2543 ret = -EFAULT;
2544 goto done;
2545 }
2546
2547 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2548 if (ioctl_req == NULL) {
2549 ret = -ENOMEM;
2550 goto done;
2551 }
2552
2553 misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
2554 misc->sub_command = MLAN_OID_MISC_TDLS_CONFIG;
2555 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
2556 if (tdls_data->tdls_action == WLAN_TDLS_DISCOVERY_REQ ||
2557 tdls_data->tdls_action == WLAN_TDLS_LINK_STATUS)
2558 ioctl_req->action = MLAN_ACT_GET;
2559 else
2560 ioctl_req->action = MLAN_ACT_SET;
2561
2562 moal_memcpy_ext(priv->phandle, &misc->param.tdls_config, tdls_data,
2563 sizeof(mlan_ds_misc_tdls_config),
2564 sizeof(mlan_ds_misc_tdls_config));
2565
2566 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2567 if (status != MLAN_STATUS_SUCCESS) {
2568 ret = -EFAULT;
2569 goto done;
2570 }
2571
2572 if (tdls_data->tdls_action == WLAN_TDLS_DISCOVERY_REQ ||
2573 tdls_data->tdls_action == WLAN_TDLS_LINK_STATUS) {
2574 if (copy_to_user(req->ifr_data, &misc->param.tdls_config,
2575 sizeof(mlan_ds_misc_tdls_config))) {
2576 PRINTM(MERROR, "Copy to user failed!\n");
2577 ret = -EFAULT;
2578 goto done;
2579 }
2580 }
2581
2582 done:
2583 if (status != MLAN_STATUS_PENDING)
2584 kfree(ioctl_req);
2585 kfree(tdls_data);
2586 LEAVE();
2587 return ret;
2588 }
2589
2590 /**
2591 * @brief ioctl function get BSS type
2592 *
2593 * @param dev A pointer to net_device structure
2594 * @param req A pointer to ifreq structure
2595 * @return 0 --success, otherwise fail
2596 */
woal_get_bss_type(struct net_device * dev,struct ifreq * req)2597 int woal_get_bss_type(struct net_device *dev, struct ifreq *req)
2598 {
2599 int ret = 0;
2600 moal_private *priv = (moal_private *)netdev_priv(dev);
2601 int bss_type;
2602
2603 ENTER();
2604
2605 bss_type = (int)priv->bss_type;
2606 if (copy_to_user(req->ifr_data, &bss_type, sizeof(int))) {
2607 PRINTM(MINFO, "Copy to user failed!\n");
2608 ret = -EFAULT;
2609 }
2610
2611 LEAVE();
2612 return ret;
2613 }
2614
2615 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
2616 /**
2617 * @brief Swithces BSS role of interface
2618 *
2619 * @param priv A pointer to moal_private structure
2620 * @param action Action: set or get
2621 * @param wait_option Wait option (MOAL_WAIT or MOAL_NO_WAIT)
2622 * @param bss_role A pointer to bss role
2623 *
2624 * @return 0 --success, otherwise fail
2625 */
woal_bss_role_cfg(moal_private * priv,t_u8 action,t_u8 wait_option,t_u8 * bss_role)2626 mlan_status woal_bss_role_cfg(moal_private *priv, t_u8 action, t_u8 wait_option,
2627 t_u8 *bss_role)
2628 {
2629 int ret = 0;
2630 mlan_ds_bss *bss = NULL;
2631 mlan_ioctl_req *req = NULL;
2632 struct net_device *dev = priv->netdev;
2633 mlan_status status = MLAN_STATUS_SUCCESS;
2634
2635 ENTER();
2636
2637 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
2638 if (req == NULL) {
2639 ret = -ENOMEM;
2640 goto done;
2641 }
2642 bss = (mlan_ds_bss *)req->pbuf;
2643 bss->sub_command = MLAN_OID_BSS_ROLE;
2644 req->req_id = MLAN_IOCTL_BSS;
2645 req->action = action;
2646 if (action == MLAN_ACT_SET) {
2647 if (priv->bss_role == *bss_role) {
2648 PRINTM(MWARN, "BSS is in desired role already\n");
2649 goto done;
2650 } else {
2651 bss->param.bss_role = *bss_role;
2652 }
2653 }
2654 status = woal_request_ioctl(priv, req, wait_option);
2655 if (status != MLAN_STATUS_SUCCESS) {
2656 ret = -EFAULT;
2657 goto done;
2658 }
2659
2660 if (action == MLAN_ACT_GET) {
2661 *bss_role = bss->param.bss_role;
2662 } else {
2663 /* Update moal_private */
2664 priv->bss_role = *bss_role;
2665 if (priv->bss_type == MLAN_BSS_TYPE_UAP)
2666 priv->bss_type = MLAN_BSS_TYPE_STA;
2667 else if (priv->bss_type == MLAN_BSS_TYPE_STA)
2668 priv->bss_type = MLAN_BSS_TYPE_UAP;
2669
2670 if (*bss_role == MLAN_BSS_ROLE_UAP) {
2671 /* Switch: STA -> uAP */
2672 /* Setup the OS Interface to our functions */
2673 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
2674 dev->do_ioctl = woal_uap_do_ioctl;
2675 dev->set_multicast_list = woal_uap_set_multicast_list;
2676 #else
2677 dev->netdev_ops = &woal_uap_netdev_ops;
2678 #endif
2679 #ifdef UAP_WEXT
2680 if (IS_UAP_WEXT(priv->phandle->params.cfg80211_wext)) {
2681 #if WIRELESS_EXT < 21
2682 dev->get_wireless_stats =
2683 woal_get_uap_wireless_stats;
2684 #endif
2685 dev->wireless_handlers =
2686 (struct iw_handler_def
2687 *)&woal_uap_handler_def;
2688 }
2689 #endif /* UAP_WEXT */
2690 } else if (*bss_role == MLAN_BSS_ROLE_STA) {
2691 /* Switch: uAP -> STA */
2692 /* Setup the OS Interface to our functions */
2693 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
2694 dev->do_ioctl = woal_do_ioctl;
2695 dev->set_multicast_list = woal_set_multicast_list;
2696 #else
2697 dev->netdev_ops = &woal_netdev_ops;
2698 #endif
2699 #ifdef STA_WEXT
2700 if (IS_STA_WEXT(priv->phandle->params.cfg80211_wext)) {
2701 #if WIRELESS_EXT < 21
2702 dev->get_wireless_stats =
2703 woal_get_wireless_stats;
2704 #endif
2705 dev->wireless_handlers =
2706 (struct iw_handler_def
2707 *)&woal_handler_def;
2708 }
2709 #endif /* STA_WEXT */
2710 }
2711 }
2712
2713 done:
2714 if (status != MLAN_STATUS_PENDING)
2715 kfree(req);
2716 LEAVE();
2717 return ret;
2718 }
2719
2720 #if defined(STA_WEXT) || defined(UAP_WEXT)
2721 /**
2722 * @brief Set/Get BSS role
2723 *
2724 * @param priv A pointer to moal_private structure
2725 * @param wrq A pointer to iwreq structure
2726 *
2727 * @return 0 --success, otherwise fail
2728 */
woal_set_get_bss_role(moal_private * priv,struct iwreq * wrq)2729 int woal_set_get_bss_role(moal_private *priv, struct iwreq *wrq)
2730 {
2731 int ret = 0;
2732 int bss_role = 0;
2733 t_u8 action = MLAN_ACT_GET;
2734
2735 ENTER();
2736
2737 if (wrq->u.data.length) {
2738 if (copy_from_user(&bss_role, wrq->u.data.pointer,
2739 sizeof(int))) {
2740 PRINTM(MERROR, "Copy from user failed\n");
2741 ret = -EFAULT;
2742 goto done;
2743 }
2744 if ((bss_role != MLAN_BSS_ROLE_STA &&
2745 bss_role != MLAN_BSS_ROLE_UAP)
2746 #ifdef WIFI_DIRECT_SUPPORT
2747 || (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT)
2748 #endif
2749 ) {
2750 PRINTM(MWARN, "Invalid BSS role\n");
2751 ret = -EINVAL;
2752 goto done;
2753 }
2754 if (bss_role == (int)GET_BSS_ROLE(priv)) {
2755 PRINTM(MWARN, "Already BSS is in desired role\n");
2756 ret = -EINVAL;
2757 goto done;
2758 }
2759 action = MLAN_ACT_SET;
2760 /* Reset interface */
2761 if (MLAN_STATUS_SUCCESS !=
2762 woal_reset_intf(priv, MOAL_IOCTL_WAIT, MFALSE)) {
2763 PRINTM(MERROR, "%s: reset_intf failed \n", __func__);
2764 ret = -EFAULT;
2765 goto done;
2766 }
2767 }
2768
2769 if (MLAN_STATUS_SUCCESS != woal_bss_role_cfg(priv, action,
2770 MOAL_IOCTL_WAIT,
2771 (t_u8 *)&bss_role)) {
2772 ret = -EFAULT;
2773 goto done;
2774 }
2775
2776 if (!wrq->u.data.length) {
2777 if (copy_to_user(wrq->u.data.pointer, &bss_role, sizeof(int))) {
2778 ret = -EFAULT;
2779 goto done;
2780 }
2781 wrq->u.data.length = 1;
2782 } else {
2783 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
2784 if (IS_STA_OR_UAP_CFG80211(priv->phandle->params.cfg80211_wext))
2785 woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_WAIT);
2786 #endif
2787 /* Initialize private structures */
2788 woal_init_priv(priv, MOAL_IOCTL_WAIT);
2789
2790 /* Enable interfaces */
2791 netif_device_attach(priv->netdev);
2792 woal_start_queue(priv->netdev);
2793 }
2794
2795 done:
2796 LEAVE();
2797 return ret;
2798 }
2799 #endif /* STA_WEXT || UAP_WEXT */
2800 #endif /* STA_SUPPORT && UAP_SUPPORT */
2801
2802 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
2803 /**
2804 * @brief Enable IPv6 Router Advertisement offload
2805 *
2806 * @param handle A pointer to moal_handle structure
2807 * @param enable enable or disable
2808 *
2809 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise
2810 * fail
2811 */
woal_set_ipv6_ra_offload(moal_handle * handle,t_u8 enable)2812 static mlan_status woal_set_ipv6_ra_offload(moal_handle *handle, t_u8 enable)
2813 {
2814 mlan_status ret = MLAN_STATUS_SUCCESS;
2815 moal_private *priv = NULL;
2816 mlan_ds_misc_cfg *misc = NULL;
2817 mlan_ioctl_req *req = NULL;
2818 mlan_ds_misc_ipv6_ra_offload *ipv6_ra;
2819 int i = 0;
2820
2821 ENTER();
2822
2823 for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) {
2824 if (priv->ipv6_addr_configured)
2825 break;
2826 }
2827
2828 if (!priv || !priv->ipv6_addr_configured) {
2829 PRINTM(MIOCTL, "No IPv6 address configured\n");
2830 goto done;
2831 }
2832
2833 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2834 if (req == NULL) {
2835 PRINTM(MIOCTL, "IOCTL req allocated failed!\n");
2836 ret = MLAN_STATUS_FAILURE;
2837 goto done;
2838 }
2839 misc = (mlan_ds_misc_cfg *)req->pbuf;
2840 misc->sub_command = MLAN_OID_MISC_IPV6_RA_OFFLOAD;
2841 req->req_id = MLAN_IOCTL_MISC_CFG;
2842 req->action = MLAN_ACT_SET;
2843 ipv6_ra = &misc->param.ipv6_ra_offload;
2844 ipv6_ra->enable = enable;
2845 moal_memcpy_ext(priv->phandle, ipv6_ra->ipv6_addr, priv->ipv6_addr, 16,
2846 sizeof(ipv6_ra->ipv6_addr));
2847 ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_STA), req,
2848 MOAL_NO_WAIT);
2849 if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
2850 PRINTM(MIOCTL, "Set IPv6 RA offload failed\n");
2851
2852 done:
2853 if (ret != MLAN_STATUS_PENDING && req != NULL)
2854 kfree(req);
2855 LEAVE();
2856 return ret;
2857 }
2858 #endif
2859
woal_set_wake_on_mdns(moal_handle * handle,t_u8 enable)2860 static mlan_status woal_set_wake_on_mdns(moal_handle *handle, t_u8 enable)
2861 {
2862 mlan_status ret = MLAN_STATUS_SUCCESS;
2863 mlan_ds_misc_cfg *misc = NULL;
2864 mlan_ioctl_req *req = NULL;
2865 mlan_ds_misc_mef_flt_cfg *mef_cfg = NULL;
2866 mef_entry_t *entry = NULL;
2867 mef_filter_t *filter = NULL;
2868
2869 ENTER();
2870
2871 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2872 if (req == NULL) {
2873 PRINTM(MIOCTL, "IOCTL req allocated failed!\n");
2874 ret = MLAN_STATUS_FAILURE;
2875 goto done;
2876 }
2877 misc = (mlan_ds_misc_cfg *)req->pbuf;
2878 misc->sub_command = MLAN_OID_MISC_MEF_FLT_CFG;
2879 req->req_id = MLAN_IOCTL_MISC_CFG;
2880 req->action = MLAN_ACT_SET;
2881
2882 mef_cfg = (mlan_ds_misc_mef_flt_cfg *)(&misc->param.mef_flt_cfg);
2883 mef_cfg->mef_act_type = MEF_ACT_WOWLAN;
2884 mef_cfg->criteria = MBIT(3);
2885
2886 entry = (mef_entry_t *)&mef_cfg->mef_entry;
2887 entry->mode = MBIT(0);
2888 entry->action = 3;
2889
2890 filter = (mef_filter_t *)entry->filter_item;
2891 filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | FILLING_OFFSET |
2892 FILLING_BYTE_SEQ);
2893 filter->type = TYPE_BYTE_EQ;
2894 filter->repeat = 1;
2895 filter->offset = 20;
2896 filter->num_byte_seq = 2;
2897 moal_memcpy_ext(handle, filter->byte_seq, "\x08\x00", 2,
2898 sizeof(filter->byte_seq));
2899 entry->rpn[1] = RPN_TYPE_AND;
2900
2901 filter++;
2902 filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | FILLING_OFFSET |
2903 FILLING_BYTE_SEQ);
2904 filter->type = TYPE_BYTE_EQ;
2905 filter->repeat = 1;
2906 filter->offset = 38;
2907 filter->num_bytes = 4;
2908 moal_memcpy_ext(handle, filter->byte_seq, "\xe0\x00\x00\xfb", 4,
2909 sizeof(filter->byte_seq));
2910 entry->rpn[2] = RPN_TYPE_AND;
2911 filter++;
2912 filter->fill_flag = (FILLING_TYPE | FILLING_PATTERN | FILLING_OFFSET |
2913 FILLING_NUM_BYTES);
2914 filter->type = TYPE_BYTE_EQ + 1;
2915 filter->pattern = 17;
2916 filter->offset = 31;
2917 filter->num_bytes = 1;
2918 entry->rpn[3] = RPN_TYPE_AND;
2919 filter++;
2920 filter->fill_flag = (FILLING_TYPE | FILLING_PATTERN | FILLING_OFFSET |
2921 FILLING_NUM_BYTES);
2922 filter->type = TYPE_BYTE_EQ + 1;
2923 filter->pattern = 5353;
2924 filter->offset = 44;
2925 filter->num_bytes = 2;
2926 filter++;
2927 entry->filter_num = 4;
2928 if (enable) {
2929 mef_cfg->op_code = MLAN_OP_ADD_MDNS;
2930 } else {
2931 mef_cfg->op_code = MLAN_IPADDR_OP_IP_REMOVE;
2932 }
2933 ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), req,
2934 MOAL_NO_WAIT);
2935 if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
2936 PRINTM(MIOCTL, "Set Mdns wake up failed! ret=%d\n", ret);
2937 done:
2938 if (ret != MLAN_STATUS_PENDING)
2939 kfree(req);
2940 LEAVE();
2941 return ret;
2942 }
2943
2944 /**
2945 * @brief Enable IPv6 Neighbor Solicitation offload
2946 *
2947 * @param handle A pointer to moal_handle structure
2948 * @param enable enable or disable mef entry
2949 *
2950 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise
2951 * fail
2952 */
woal_set_ipv6_ns_offload(moal_handle * handle,t_u8 enable)2953 static mlan_status woal_set_ipv6_ns_offload(moal_handle *handle, t_u8 enable)
2954 {
2955 mlan_status ret = MLAN_STATUS_SUCCESS;
2956 mlan_ds_misc_cfg *misc = NULL;
2957 mlan_ioctl_req *req = NULL;
2958 mlan_ds_misc_mef_flt_cfg *mef_cfg = NULL;
2959 mef_entry_t *entry = NULL;
2960 mef_filter_t *filter = NULL;
2961
2962 ENTER();
2963
2964 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2965 if (req == NULL) {
2966 PRINTM(MIOCTL, "IOCTL req allocated failed!\n");
2967 ret = MLAN_STATUS_FAILURE;
2968 goto done;
2969 }
2970 misc = (mlan_ds_misc_cfg *)req->pbuf;
2971 misc->sub_command = MLAN_OID_MISC_MEF_FLT_CFG;
2972 req->req_id = MLAN_IOCTL_MISC_CFG;
2973 req->action = MLAN_ACT_SET;
2974
2975 mef_cfg = (mlan_ds_misc_mef_flt_cfg *)(&misc->param.mef_flt_cfg);
2976 mef_cfg->mef_act_type = MEF_ACT_IPV6_NS;
2977 mef_cfg->criteria = (MBIT(1) | MBIT(3));
2978
2979 entry = (mef_entry_t *)&mef_cfg->mef_entry;
2980 entry->mode = MBIT(0);
2981 entry->action = 0x40;
2982 filter = (mef_filter_t *)entry->filter_item;
2983 filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | FILLING_OFFSET |
2984 FILLING_BYTE_SEQ);
2985 filter->type = TYPE_BYTE_EQ;
2986 filter->repeat = 1;
2987 filter->offset = 20;
2988 filter->num_byte_seq = 2;
2989 moal_memcpy_ext(handle, filter->byte_seq, "\x86\xdd", 2,
2990 sizeof(filter->byte_seq));
2991 entry->rpn[1] = RPN_TYPE_AND;
2992
2993 filter++;
2994 filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | FILLING_OFFSET |
2995 FILLING_BYTE_SEQ);
2996 filter->type = TYPE_BYTE_EQ;
2997 filter->repeat = 1;
2998 filter->offset = 62;
2999 filter->num_byte_seq = 1;
3000 moal_memcpy_ext(handle, filter->byte_seq, "\x87", 1,
3001 sizeof(filter->byte_seq));
3002 entry->filter_num = 2;
3003 if (enable) {
3004 mef_cfg->op_code = MLAN_OP_ADD_IPV6_NS;
3005 } else {
3006 mef_cfg->op_code = MLAN_IPADDR_OP_IP_REMOVE;
3007 }
3008 ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), req,
3009 MOAL_NO_WAIT);
3010 if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
3011 PRINTM(MIOCTL, "Set ipv6 ns offload failed! ret=%d\n", ret);
3012
3013 done:
3014 if (ret != MLAN_STATUS_PENDING)
3015 kfree(req);
3016 LEAVE();
3017 return ret;
3018 }
3019
3020 /**
3021 * @brief Set auto arp resp
3022 *
3023 * @param handle A pointer to moal_handle structure
3024 * @param enable enable/disable
3025 *
3026 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
3027 * otherwise fail
3028 */
woal_set_auto_arp(moal_handle * handle,t_u8 enable)3029 static mlan_status woal_set_auto_arp(moal_handle *handle, t_u8 enable)
3030 {
3031 mlan_status ret = MLAN_STATUS_SUCCESS;
3032 int i = 0;
3033 moal_private *priv = NULL;
3034 mlan_ds_misc_cfg *misc = NULL;
3035 mlan_ioctl_req *req = NULL;
3036 mlan_ds_misc_ipaddr_cfg ipaddr_cfg;
3037
3038 ENTER();
3039
3040 memset(&ipaddr_cfg, 0, sizeof(ipaddr_cfg));
3041 for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) {
3042 if (priv && priv->ip_addr_type != IPADDR_TYPE_NONE) {
3043 moal_memcpy_ext(
3044 handle,
3045 ipaddr_cfg.ip_addr[ipaddr_cfg.ip_addr_num],
3046 priv->ip_addr, IPADDR_LEN, IPADDR_LEN);
3047 ipaddr_cfg.ip_addr_num++;
3048 }
3049 }
3050 if (ipaddr_cfg.ip_addr_num == 0) {
3051 PRINTM(MIOCTL, "No IP addr configured.\n");
3052 goto done;
3053 }
3054
3055 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3056 if (req == NULL) {
3057 PRINTM(MIOCTL, "IOCTL req allocated failed!\n");
3058 ret = MLAN_STATUS_FAILURE;
3059 goto done;
3060 }
3061 misc = (mlan_ds_misc_cfg *)req->pbuf;
3062 misc->sub_command = MLAN_OID_MISC_IP_ADDR;
3063 req->req_id = MLAN_IOCTL_MISC_CFG;
3064 req->action = MLAN_ACT_SET;
3065 moal_memcpy_ext(handle, &misc->param.ipaddr_cfg, &ipaddr_cfg,
3066 sizeof(ipaddr_cfg), sizeof(misc->param.ipaddr_cfg));
3067 if (enable) {
3068 misc->param.ipaddr_cfg.op_code = MLAN_IPADDR_OP_ARP_FILTER |
3069 MLAN_IPADDR_OP_AUTO_ARP_RESP;
3070 misc->param.ipaddr_cfg.ip_addr_type = IPADDR_TYPE_IPV4;
3071 } else {
3072 /** remove ip */
3073 misc->param.ipaddr_cfg.op_code = MLAN_IPADDR_OP_IP_REMOVE;
3074 }
3075 ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), req,
3076 MOAL_NO_WAIT);
3077 if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
3078 PRINTM(MIOCTL, "Set auto arp IOCTL failed!\n");
3079 done:
3080 if (ret != MLAN_STATUS_PENDING)
3081 kfree(req);
3082 LEAVE();
3083 return ret;
3084 }
3085
3086 /**
3087 * @brief Set auto arp resp with enhancement method
3088 *
3089 * @param handle A pointer to moal_handle structure
3090 * @param enable enable/disable
3091 *
3092 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
3093 * otherwise fail
3094 */
woal_set_auto_arp_ext(moal_handle * handle,t_u8 enable)3095 mlan_status woal_set_auto_arp_ext(moal_handle *handle, t_u8 enable)
3096 {
3097 mlan_status ret = MLAN_STATUS_SUCCESS;
3098 int i = 0, ip_addr_num = 0;
3099 moal_private *priv = NULL;
3100 mlan_ds_misc_cfg *misc = NULL;
3101 mlan_ioctl_req *req = NULL;
3102 mlan_ds_misc_mef_flt_cfg *mef_cfg = NULL;
3103 mef_entry_t *entry = NULL;
3104 mef_filter_t *filter = NULL;
3105 t_u8 ip_addr[MAX_IPADDR][IPADDR_LEN];
3106
3107 ENTER();
3108
3109 memset(&mef_cfg, 0, sizeof(mef_cfg));
3110 for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) {
3111 if (priv && priv->ip_addr_type != IPADDR_TYPE_NONE) {
3112 moal_memcpy_ext(handle, ip_addr[ip_addr_num],
3113 priv->ip_addr, IPADDR_LEN, IPADDR_LEN);
3114 ip_addr_num++;
3115 }
3116 }
3117 if (ip_addr_num == 0) {
3118 PRINTM(MIOCTL, "No IP addr configured.\n");
3119 goto done;
3120 }
3121
3122 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3123 if (req == NULL) {
3124 PRINTM(MIOCTL, "IOCTL req allocated failed!\n");
3125 ret = MLAN_STATUS_FAILURE;
3126 goto done;
3127 }
3128 misc = (mlan_ds_misc_cfg *)req->pbuf;
3129 misc->sub_command = MLAN_OID_MISC_MEF_FLT_CFG;
3130 req->req_id = MLAN_IOCTL_MISC_CFG;
3131 req->action = MLAN_ACT_SET;
3132
3133 mef_cfg = (mlan_ds_misc_mef_flt_cfg *)(&(misc->param.mef_flt_cfg));
3134 mef_cfg->mef_act_type = MEF_ACT_AUTOARP;
3135 mef_cfg->criteria = (MBIT(0) | MBIT(1));
3136
3137 entry = (mef_entry_t *)&mef_cfg->mef_entry;
3138 entry->mode = MBIT(0);
3139 entry->action = 0x10;
3140
3141 filter = (mef_filter_t *)(entry->filter_item);
3142 filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | FILLING_OFFSET |
3143 FILLING_BYTE_SEQ);
3144 filter->type = TYPE_BYTE_EQ;
3145 filter->repeat = 1;
3146 filter->offset = 20;
3147 filter->num_byte_seq = 2;
3148 moal_memcpy_ext(handle, filter->byte_seq, "\x08\x06", 2,
3149 sizeof(filter->byte_seq));
3150 entry->rpn[1] = RPN_TYPE_AND;
3151
3152 for (i = 0; i < ip_addr_num; i++) {
3153 filter++;
3154 filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT |
3155 FILLING_OFFSET | FILLING_BYTE_SEQ);
3156 filter->type = TYPE_BYTE_EQ;
3157 filter->repeat = 1;
3158 filter->offset = 46;
3159 filter->num_byte_seq = 4;
3160 moal_memcpy_ext(handle, filter->byte_seq, &ip_addr[i],
3161 sizeof(t_u32), sizeof(filter->byte_seq));
3162 if (i > 1)
3163 entry->rpn[i] = RPN_TYPE_OR;
3164 }
3165 entry->filter_num = ip_addr_num + 1;
3166
3167 if (enable)
3168 mef_cfg->op_code = MLAN_IPADDR_OP_ARP_FILTER |
3169 MLAN_IPADDR_OP_AUTO_ARP_RESP;
3170 else
3171 /** remove ip */
3172 mef_cfg->op_code = MLAN_IPADDR_OP_IP_REMOVE;
3173 ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), req,
3174 MOAL_NO_WAIT);
3175 if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
3176 PRINTM(MIOCTL, "Set auto arp IOCTL failed!\n");
3177 done:
3178 if (ret != MLAN_STATUS_PENDING)
3179 kfree(req);
3180 LEAVE();
3181 return ret;
3182 }
3183
3184 /**
3185 * @brief Set/Get DTIM period
3186 *
3187 * @param priv A pointer to moal_private structure
3188 * @param action Action set or get
3189 * @param wait_option Wait option
3190 * @param value DTIM period
3191 *
3192 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
3193 * success, otherwise fail
3194 */
woal_set_get_dtim_period(moal_private * priv,t_u32 action,t_u8 wait_option,t_u8 * value)3195 mlan_status woal_set_get_dtim_period(moal_private *priv, t_u32 action,
3196 t_u8 wait_option, t_u8 *value)
3197 {
3198 mlan_ioctl_req *req = NULL;
3199 mlan_ds_snmp_mib *mib = NULL;
3200 mlan_status ret = MLAN_STATUS_SUCCESS;
3201
3202 ENTER();
3203
3204 /* Allocate an IOCTL request buffer */
3205 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
3206 if (req == NULL) {
3207 ret = MLAN_STATUS_FAILURE;
3208 goto done;
3209 }
3210
3211 /* Fill request buffer */
3212 mib = (mlan_ds_snmp_mib *)req->pbuf;
3213 mib->sub_command = MLAN_OID_SNMP_MIB_DTIM_PERIOD;
3214 req->req_id = MLAN_IOCTL_SNMP_MIB;
3215 req->action = action;
3216
3217 if (action == MLAN_ACT_SET)
3218 mib->param.dtim_period = *value;
3219
3220 /* Send IOCTL request to MLAN */
3221 ret = woal_request_ioctl(priv, req, wait_option);
3222 if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
3223 *value = (t_u8)mib->param.dtim_period;
3224
3225 done:
3226 if (ret != MLAN_STATUS_PENDING)
3227 kfree(req);
3228 LEAVE();
3229 return ret;
3230 }
3231
3232 /**
3233 * @brief Get Host Sleep parameters
3234 *
3235 * @param priv A pointer to moal_private structure
3236 * @param action Action: set or get
3237 * @param wait_option Wait option (MOAL_WAIT or MOAL_NO_WAIT)
3238 * @param hscfg A pointer to mlan_ds_hs_cfg structure
3239 *
3240 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
3241 * otherwise fail
3242 */
woal_set_get_hs_params(moal_private * priv,t_u16 action,t_u8 wait_option,mlan_ds_hs_cfg * hscfg)3243 mlan_status woal_set_get_hs_params(moal_private *priv, t_u16 action,
3244 t_u8 wait_option, mlan_ds_hs_cfg *hscfg)
3245 {
3246 mlan_status ret = MLAN_STATUS_SUCCESS;
3247 mlan_ds_pm_cfg *pmcfg = NULL;
3248 mlan_ioctl_req *req = NULL;
3249
3250 ENTER();
3251
3252 /* Allocate an IOCTL request buffer */
3253 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
3254 if (req == NULL) {
3255 ret = MLAN_STATUS_FAILURE;
3256 goto done;
3257 }
3258
3259 /* Fill request buffer */
3260 pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
3261 pmcfg->sub_command = MLAN_OID_PM_CFG_HS_CFG;
3262 req->req_id = MLAN_IOCTL_PM_CFG;
3263 req->action = action;
3264 if (action == MLAN_ACT_SET)
3265 moal_memcpy_ext(priv->phandle, &pmcfg->param.hs_cfg, hscfg,
3266 sizeof(mlan_ds_hs_cfg), sizeof(mlan_ds_hs_cfg));
3267
3268 /* Send IOCTL request to MLAN */
3269 ret = woal_request_ioctl(priv, req, wait_option);
3270 if (ret == MLAN_STATUS_SUCCESS) {
3271 if (hscfg && action == MLAN_ACT_GET) {
3272 moal_memcpy_ext(priv->phandle, hscfg,
3273 &pmcfg->param.hs_cfg,
3274 sizeof(mlan_ds_hs_cfg),
3275 sizeof(mlan_ds_hs_cfg));
3276 }
3277 }
3278 done:
3279 if (ret != MLAN_STATUS_PENDING)
3280 kfree(req);
3281 LEAVE();
3282 return ret;
3283 }
3284
3285 /**
3286 * @brief Get wakeup reason
3287 *
3288 * @param priv A pointer to moal_private structure
3289 * @param wakeup_reason A pointer to mlan_ds_hs_wakeup_reason structure
3290 *
3291 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
3292 * otherwise fail
3293 */
woal_get_wakeup_reason(moal_private * priv,mlan_ds_hs_wakeup_reason * wakeup_reason)3294 mlan_status woal_get_wakeup_reason(moal_private *priv,
3295 mlan_ds_hs_wakeup_reason *wakeup_reason)
3296 {
3297 mlan_status ret = MLAN_STATUS_SUCCESS;
3298 mlan_ds_pm_cfg *pmcfg = NULL;
3299 mlan_ioctl_req *req = NULL;
3300
3301 ENTER();
3302
3303 /* Allocate an IOCTL request buffer */
3304 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
3305 if (req == NULL) {
3306 ret = -ENOMEM;
3307 goto done;
3308 }
3309
3310 /* Fill request buffer */
3311 pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
3312 pmcfg->sub_command = MLAN_OID_PM_HS_WAKEUP_REASON;
3313 req->req_id = MLAN_IOCTL_PM_CFG;
3314 req->action = MLAN_ACT_GET;
3315
3316 /* Send IOCTL request to MLAN */
3317 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT_TIMEOUT);
3318 if (ret == MLAN_STATUS_SUCCESS) {
3319 wakeup_reason->hs_wakeup_reason =
3320 pmcfg->param.wakeup_reason.hs_wakeup_reason;
3321 }
3322 done:
3323 if (ret != MLAN_STATUS_PENDING)
3324 kfree(req);
3325 LEAVE();
3326 return ret;
3327 }
3328
3329 /**
3330 * @brief Set or Get wowlan config
3331 *
3332 * @param priv A pointer to moal_private structure
3333 * @param action Action: action to config wowlan
3334 * @param wait_option Wait option (MOAL_WAIT or MOAL_NO_WAIT)
3335 * @param mefcfg A pointer to mlan_ds_misc_mef_flt_cfg structure
3336 *
3337 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
3338 */
woal_set_get_wowlan_config(moal_private * priv,t_u16 action,t_u8 wait_option,mlan_ds_misc_mef_flt_cfg * mefcfg)3339 mlan_status woal_set_get_wowlan_config(moal_private *priv, t_u16 action,
3340 t_u8 wait_option,
3341 mlan_ds_misc_mef_flt_cfg *mefcfg)
3342 {
3343 mlan_status ret = MLAN_STATUS_SUCCESS;
3344 mlan_ds_misc_cfg *misccfg = NULL;
3345 mlan_ioctl_req *req = NULL;
3346
3347 ENTER();
3348
3349 /** Allocate an IOCTL request buffer*/
3350 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3351 if (req == NULL) {
3352 ret = -ENOMEM;
3353 goto done;
3354 }
3355 /** Fill request buffer */
3356 misccfg = (mlan_ds_misc_cfg *)req->pbuf;
3357 misccfg->sub_command = MLAN_OID_MISC_MEF_FLT_CFG;
3358 req->req_id = MLAN_IOCTL_MISC_CFG;
3359 req->action = action;
3360 moal_memcpy_ext(priv->phandle, &misccfg->param.mef_flt_cfg, mefcfg,
3361 sizeof(mlan_ds_misc_mef_flt_cfg),
3362 sizeof(mlan_ds_misc_mef_flt_cfg));
3363 /* Send IOCTL request to MLAN */
3364 ret = woal_request_ioctl(priv, req, wait_option);
3365 if (ret == MLAN_STATUS_SUCCESS) {
3366 if (mefcfg && action == MLAN_ACT_GET) {
3367 moal_memcpy_ext(priv->phandle, mefcfg,
3368 &misccfg->param.mef_flt_cfg,
3369 sizeof(mlan_ds_misc_mef_flt_cfg),
3370 sizeof(mlan_ds_misc_mef_flt_cfg));
3371 }
3372 }
3373 if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
3374 PRINTM(MIOCTL, "Set Get wowlan IOCTL failed!\n");
3375 done:
3376 if (ret != MLAN_STATUS_PENDING)
3377 kfree(req);
3378 LEAVE();
3379 return ret;
3380 }
3381
3382 /**
3383 * @brief Cancel Host Sleep configuration
3384 *
3385 * @param priv A pointer to moal_private structure
3386 * @param wait_option wait option
3387 *
3388 * @return MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING,
3389 * or MLAN_STATUS_FAILURE
3390 */
woal_cancel_hs(moal_private * priv,t_u8 wait_option)3391 mlan_status woal_cancel_hs(moal_private *priv, t_u8 wait_option)
3392 {
3393 #ifdef STA_CFG80211
3394 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
3395 moal_handle *handle = NULL;
3396 #endif
3397 #endif
3398 mlan_status ret = MLAN_STATUS_SUCCESS;
3399 mlan_ds_hs_cfg hscfg;
3400 #ifdef STA_CFG80211
3401 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
3402 int i;
3403 #endif
3404 #endif
3405 ENTER();
3406
3407 if (!priv) {
3408 LEAVE();
3409 return MLAN_STATUS_FAILURE;
3410 }
3411 /* Cancel Host Sleep */
3412 hscfg.conditions = HOST_SLEEP_CFG_CANCEL;
3413 hscfg.is_invoke_hostcmd = MTRUE;
3414 ret = woal_set_get_hs_params(priv, MLAN_ACT_SET, wait_option, &hscfg);
3415 if (ret != MLAN_STATUS_SUCCESS) {
3416 PRINTM(MERROR, "%s: woal_set_get_hs_params failed \n",
3417 __func__);
3418 LEAVE();
3419 return ret;
3420 }
3421 if (moal_extflg_isset(priv->phandle, EXT_ROAMOFFLOAD_IN_HS)) {
3422 /*Disable firmware roaming*/
3423 woal_enable_fw_roaming(priv, 0);
3424 }
3425 if (priv->phandle->fw_roam_enable == ROAM_OFFLOAD_WITH_BSSID ||
3426 priv->phandle->fw_roam_enable == ROAM_OFFLOAD_WITH_SSID ||
3427 priv->phandle->fw_roam_enable == AUTO_RECONNECT)
3428 woal_config_fw_roaming(priv, ROAM_OFFLOAD_RESUME_CFG, NULL);
3429 #ifdef STA_CFG80211
3430 if (priv->phandle->fw_roam_enable == AUTO_RECONNECT)
3431 woal_set_clear_pmk(priv, MLAN_ACT_CLEAR);
3432 #endif
3433
3434 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
3435 #if IS_ENABLED(CONFIG_IPV6)
3436 if (priv->phandle->hs_auto_arp) {
3437 PRINTM(MIOCTL, "Cancel Host Sleep... remove ipv6 offload\n");
3438 /** Set ipv6 router advertisement message offload */
3439 woal_set_ipv6_ra_offload(priv->phandle, MFALSE);
3440 }
3441 /** Set Neighbor Solitation message offload */
3442 woal_set_ipv6_ns_offload(priv->phandle, MFALSE);
3443 #endif
3444 #endif
3445
3446 if (priv->phandle->hs_auto_arp) {
3447 PRINTM(MIOCTL, "Cancel Host Sleep... remove Mdns wake up\n");
3448 /** Set ipv6 router advertisement message offload */
3449 woal_set_wake_on_mdns(priv->phandle, MFALSE);
3450 }
3451
3452 if (priv->phandle->hs_auto_arp) {
3453 PRINTM(MIOCTL, "Cancel Host Sleep... remove FW auto arp\n");
3454 /* remove auto arp from FW */
3455 woal_set_auto_arp(priv->phandle, MFALSE);
3456 /* remove auto arp from FW */
3457 woal_set_auto_arp_ext(priv->phandle, MFALSE);
3458 }
3459
3460 #ifdef STA_CFG80211
3461 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
3462 handle = priv->phandle;
3463 if (GTK_REKEY_OFFLOAD_SUSPEND == handle->params.gtk_rekey_offload) {
3464 PRINTM(MIOCTL,
3465 "Cancel Host Sleep... clear gtk rekey offload of FW\n");
3466 for (i = 0; i < handle->priv_num; i++) {
3467 if (handle->priv[i] &&
3468 handle->priv[i]->gtk_data_ready) {
3469 PRINTM(MCMND, "clear GTK in resume\n");
3470 if (MLAN_STATUS_SUCCESS !=
3471 woal_set_rekey_data(handle->priv[i], NULL,
3472 MLAN_ACT_CLEAR,
3473 wait_option))
3474 PRINTM(MERROR,
3475 "%s: clear GTK in resume failed \n",
3476 __func__);
3477 }
3478 }
3479 }
3480 #endif
3481 #endif
3482
3483 LEAVE();
3484 return ret;
3485 }
3486
3487 /** @brief This function config fw roaming parameters
3488 *
3489 * @param priv A Pointer to the moal_private structure
3490 * @return MTRUE or MFALSE
3491 */
woal_set_fw_roaming_params(moal_private * priv)3492 static int woal_set_fw_roaming_params(moal_private *priv)
3493 {
3494 int ret = 0;
3495 mlan_status status = MLAN_STATUS_SUCCESS;
3496 mlan_ioctl_req *req = NULL;
3497 mlan_ds_sec_cfg *sec = NULL;
3498 woal_roam_offload_cfg roam_offload_cfg;
3499 #ifdef STA_CFG80211
3500 t_u8 zero[MLAN_MAX_KEY_LENGTH] = {0};
3501 #endif
3502
3503 /*Enable fw roaming*/
3504 woal_config_fw_roaming(priv, ROAM_OFFLOAD_ENABLE, NULL);
3505 /*Download fw roaming parameters*/
3506 woal_config_fw_roaming(priv, ROAM_OFFLOAD_PARAM_CFG,
3507 &priv->phandle->fw_roam_params);
3508
3509 /*Download userset passphrase key and current connection's PMK*/
3510 #ifdef STA_CFG80211
3511 if (!priv->phandle->fw_roam_params.userset_passphrase) {
3512 woal_set_clear_pmk(priv, MLAN_ACT_SET);
3513 goto done;
3514 }
3515 #endif
3516
3517 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
3518 if (req == NULL) {
3519 ret = -ENOMEM;
3520 goto done;
3521 }
3522
3523 req->req_id = MLAN_IOCTL_SEC_CFG;
3524 sec = (mlan_ds_sec_cfg *)req->pbuf;
3525 sec->sub_command = MLAN_OID_SEC_CFG_PASSPHRASE;
3526 sec->multi_passphrase = 1;
3527 req->action = MLAN_ACT_SET;
3528
3529 /*Copy user set passphrase*/
3530 moal_memcpy_ext(priv->phandle, (char *)sec->param.roam_passphrase,
3531 (char *)priv->phandle->ssid_passphrase,
3532 MAX_SEC_SSID_NUM * sizeof(mlan_ds_passphrase),
3533 MAX_SEC_SSID_NUM * sizeof(mlan_ds_passphrase));
3534 roam_offload_cfg.userset_passphrase =
3535 priv->phandle->fw_roam_params.userset_passphrase;
3536 #ifdef STA_CFG80211
3537 if (memcmp(priv->pmk.pmk, zero, MLAN_MAX_KEY_LENGTH)) {
3538 /*Download current connection PMK*/
3539 if (priv->pmk_saved) {
3540 woal_set_clear_pmk(priv, MLAN_ACT_SET);
3541 priv->pmk_saved = false;
3542 }
3543 }
3544 #endif
3545 /*Set userset to mlan adapter*/
3546 woal_config_fw_roaming(priv, ROAM_OFFLOAD_ENABLE, &roam_offload_cfg);
3547
3548 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3549 if (status != MLAN_STATUS_SUCCESS) {
3550 ret = -EFAULT;
3551 goto done;
3552 }
3553 done:
3554 if (status != MLAN_STATUS_PENDING)
3555 kfree(req);
3556 LEAVE();
3557 return ret;
3558 }
3559
3560 /** @brief This function enable/disable fw roaming
3561 *
3562 * @param priv A Pointer to the moal_private structure
3563 * @param enable Enable/disable fw roaming
3564 * @return MTRUE or MFALSE
3565 */
woal_enable_fw_roaming(moal_private * priv,int data)3566 int woal_enable_fw_roaming(moal_private *priv, int data)
3567 {
3568 mlan_ioctl_req *ioctl_req = NULL;
3569 mlan_ds_misc_cfg *misc = NULL;
3570 mlan_ds_misc_roam_offload *roam = NULL;
3571 mlan_status status = MLAN_STATUS_SUCCESS;
3572 int ret = 0;
3573
3574 ENTER();
3575
3576 if (!priv || !priv->phandle) {
3577 PRINTM(MERROR, "priv or handle is null\n");
3578 ret = -EFAULT;
3579 goto done;
3580 }
3581
3582 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3583 if (ioctl_req == NULL) {
3584 ret = -ENOMEM;
3585 goto done;
3586 }
3587
3588 if (!data && !priv->phandle->fw_roam_enable) {
3589 PRINTM(MIOCTL, "Fw roaming already disabled\n");
3590 goto done;
3591 }
3592
3593 misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
3594 misc->sub_command = MLAN_OID_MISC_ROAM_OFFLOAD;
3595 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
3596
3597 roam = (mlan_ds_misc_roam_offload *)&misc->param.roam_offload;
3598 roam->aplist.ap_num = 0;
3599 /* SET operation */
3600 ioctl_req->action = MLAN_ACT_SET;
3601 roam->enable = data;
3602 roam->config_mode = ROAM_OFFLOAD_ENABLE;
3603
3604 if (moal_extflg_isset(priv->phandle, EXT_ROAMOFFLOAD_IN_HS) && data) {
3605 priv->phandle->fw_roam_enable = data;
3606 goto done;
3607 }
3608
3609 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
3610 if (status != MLAN_STATUS_SUCCESS) {
3611 ret = -EFAULT;
3612 goto done;
3613 }
3614 priv->phandle->fw_roam_enable = data;
3615 if (!data) {
3616 memset((char *)&priv->phandle->fw_roam_params, 0,
3617 sizeof(woal_roam_offload_cfg));
3618 memset((char *)&priv->phandle->ssid_passphrase, 0,
3619 MAX_SEC_SSID_NUM * sizeof(mlan_ds_passphrase));
3620 }
3621 #ifdef STA_CFG80211
3622 else if (priv->media_connected && priv->pmk_saved) {
3623 woal_set_clear_pmk(priv, MLAN_ACT_SET);
3624 priv->pmk_saved = false;
3625 }
3626 #endif
3627 done:
3628 if (status != MLAN_STATUS_PENDING)
3629 kfree(ioctl_req);
3630
3631 LEAVE();
3632 return ret;
3633 }
3634
3635 /** @brief This function enables the host sleep
3636 *
3637 * @param priv A Pointer to the moal_private structure
3638 * @return MTRUE or MFALSE
3639 */
woal_enable_hs(moal_private * priv)3640 int woal_enable_hs(moal_private *priv)
3641 {
3642 mlan_ds_hs_cfg hscfg;
3643 moal_handle *handle = NULL;
3644 int hs_actived = MFALSE;
3645 int timeout = 0;
3646 int i;
3647 #ifdef SDIO_SUSPEND_RESUME
3648 mlan_ds_ps_info pm_info;
3649 #endif
3650 pmlan_ds_misc_keep_alive keep_alive = NULL;
3651 t_u8 media_connected = MFALSE;
3652
3653 ENTER();
3654
3655 if (priv == NULL) {
3656 PRINTM(MERROR, "Invalid priv\n");
3657 goto done;
3658 }
3659 handle = priv->phandle;
3660 if (handle->hs_activated == MTRUE) {
3661 PRINTM(MIOCTL, "HS Already actived\n");
3662 hs_actived = MTRUE;
3663 goto done;
3664 }
3665 for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
3666 if (handle->priv[i] &&
3667 (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA)) {
3668 if (moal_extflg_isset(handle,
3669 EXT_DISCONNECT_ON_SUSPEND) &&
3670 handle->priv[i]->media_connected == MTRUE) {
3671 PRINTM(MIOCTL, "disconnect on suspend\n");
3672 woal_disconnect(handle->priv[i], MOAL_NO_WAIT,
3673 NULL, DEF_DEAUTH_REASON_CODE);
3674 }
3675 }
3676 if (handle->priv[i]) {
3677 PRINTM(MIOCTL, "woal_delba_all on priv[%d]\n", i);
3678 woal_delba_all(handle->priv[i], MOAL_NO_WAIT);
3679 }
3680 }
3681
3682 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
3683 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
3684 if (priv->phandle->is_remain_timer_set) {
3685 woal_cancel_timer(&priv->phandle->remain_timer);
3686 woal_remain_timer_func(priv->phandle);
3687 }
3688 /* cancel pending remain on channel */
3689 if (priv->phandle->remain_on_channel) {
3690 t_u8 channel_status;
3691 moal_private *remain_priv =
3692 priv->phandle->priv[priv->phandle->remain_bss_index];
3693 if (remain_priv) {
3694 woal_cfg80211_remain_on_channel_cfg(remain_priv,
3695 MOAL_NO_WAIT, MTRUE,
3696 &channel_status,
3697 NULL, 0, 0);
3698 if (priv->phandle->cookie) {
3699 cfg80211_remain_on_channel_expired(
3700 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
3701 remain_priv->netdev,
3702 #else
3703 remain_priv->wdev,
3704 #endif
3705 priv->phandle->cookie,
3706 &priv->phandle->chan,
3707 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
3708 priv->phandle->channel_type,
3709 #endif
3710 GFP_ATOMIC);
3711 priv->phandle->cookie = 0;
3712 }
3713 }
3714 priv->phandle->remain_on_channel = MFALSE;
3715 }
3716 #endif
3717 #endif
3718
3719 #ifdef STA_SUPPORT
3720 woal_reconfig_bgscan(priv->phandle);
3721 #endif
3722
3723 if (moal_extflg_isset(priv->phandle, EXT_ROAMOFFLOAD_IN_HS) &&
3724 handle->fw_roam_enable) {
3725 woal_set_fw_roaming_params(priv);
3726 }
3727 if (handle->fw_roam_enable == ROAM_OFFLOAD_WITH_BSSID ||
3728 handle->fw_roam_enable == ROAM_OFFLOAD_WITH_SSID ||
3729 handle->fw_roam_enable == AUTO_RECONNECT) {
3730 woal_config_fw_roaming(priv, ROAM_OFFLOAD_SUSPEND_CFG, NULL);
3731 #ifdef STA_CFG80211
3732 if (priv->phandle->fw_roam_enable == AUTO_RECONNECT)
3733 woal_set_clear_pmk(priv, MLAN_ACT_SET);
3734 #endif
3735 }
3736 media_connected = woal_check_media_connected(handle);
3737 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
3738 #if IS_ENABLED(CONFIG_IPV6)
3739 if (handle->hs_auto_arp && media_connected) {
3740 PRINTM(MIOCTL, "Host Sleep enabled... set ipv6 offload\n");
3741 /** Set ipv6 router advertisement message offload */
3742 woal_set_ipv6_ra_offload(handle, MTRUE);
3743 /** Set Neighbor Solitation message offload */
3744 woal_set_ipv6_ns_offload(handle, MTRUE);
3745 }
3746 #endif
3747 #endif
3748
3749 if (handle->hs_auto_arp) {
3750 PRINTM(MIOCTL, "Host Sleep enabled... set mdns wake up\n");
3751 /**MDNS wake up**/
3752 woal_set_wake_on_mdns(handle, MTRUE);
3753 }
3754
3755 if (handle->hs_auto_arp && media_connected) {
3756 PRINTM(MIOCTL, "Host Sleep enabled... set FW auto arp\n");
3757 /* Set auto arp response configuration to Fw */
3758 woal_set_auto_arp(handle, MTRUE);
3759 /* Set auto arp response configuration to Fw */
3760 woal_set_auto_arp_ext(handle, MTRUE);
3761 }
3762
3763 #ifdef STA_CFG80211
3764 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
3765 if (GTK_REKEY_OFFLOAD_SUSPEND == handle->params.gtk_rekey_offload) {
3766 PRINTM(MIOCTL,
3767 "Host Sleep enabled... set gtk rekey offload to FW\n");
3768 for (i = 0; i < handle->priv_num; i++) {
3769 if (handle->priv[i] &&
3770 handle->priv[i]->gtk_data_ready) {
3771 PRINTM(MCMND, "set GTK before suspend\n");
3772 if (MLAN_STATUS_SUCCESS !=
3773 woal_set_rekey_data(
3774 handle->priv[i],
3775 &handle->priv[i]->gtk_rekey_data,
3776 MLAN_ACT_SET, MOAL_NO_WAIT))
3777 PRINTM(MERROR,
3778 "%s: set GTR before suspend failed \n",
3779 __func__);
3780 }
3781 }
3782 }
3783 #endif
3784 #endif
3785
3786 for (i = 0; i < MAX_KEEP_ALIVE_ID; i++) {
3787 keep_alive = &handle->keep_alive[i];
3788 if (keep_alive && keep_alive->cached && keep_alive->enable) {
3789 keep_alive->cached = false;
3790 woal_start_mkeep_alive(
3791 woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
3792 keep_alive->mkeep_alive_id, keep_alive->packet,
3793 keep_alive->pkt_len, keep_alive->src_mac,
3794 keep_alive->dst_mac, keep_alive->send_interval,
3795 keep_alive->retry_interval,
3796 keep_alive->retry_count);
3797 keep_alive->pkt_len = 0;
3798 memset(keep_alive->packet, 0, MKEEP_ALIVE_IP_PKT_MAX);
3799 }
3800 }
3801 /* Enable Host Sleep */
3802 handle->hs_activate_wait_q_woken = MFALSE;
3803 memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg));
3804 hscfg.is_invoke_hostcmd = MTRUE;
3805 if (woal_set_get_hs_params(priv, MLAN_ACT_SET, MOAL_NO_WAIT, &hscfg) ==
3806 MLAN_STATUS_FAILURE) {
3807 PRINTM(MIOCTL, "IOCTL request HS enable failed\n");
3808 goto done;
3809 }
3810 timeout = wait_event_timeout(handle->hs_activate_wait_q,
3811 handle->hs_activate_wait_q_woken,
3812 HS_ACTIVE_TIMEOUT);
3813 #ifdef SDIO_MMC
3814 if (IS_SD(handle->card_type)) {
3815 sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
3816 }
3817 #endif
3818
3819 #ifdef SDIO_SUSPEND_RESUME
3820 memset(&pm_info, 0, sizeof(mlan_ds_ps_info));
3821 #endif
3822 if ((handle->hs_activated == MTRUE) ||
3823 (handle->is_suspended == MTRUE)) {
3824 PRINTM(MCMND, "suspend success! force=%u skip=%u\n",
3825 handle->hs_force_count, handle->hs_skip_count);
3826 hs_actived = MTRUE;
3827 }
3828 #ifdef SDIO_SUSPEND_RESUME
3829 else if (IS_SD(handle->card_type)) {
3830 handle->suspend_fail = MTRUE;
3831 woal_get_pm_info(priv, &pm_info);
3832 if (pm_info.is_suspend_allowed == MTRUE) {
3833 #ifdef MMC_PM_FUNC_SUSPENDED
3834 woal_wlan_is_suspended(priv->phandle);
3835 #endif
3836 handle->hs_force_count++;
3837 PRINTM(MCMND, "suspend allowed! force=%u skip=%u\n",
3838 handle->hs_force_count, handle->hs_skip_count);
3839 hs_actived = MTRUE;
3840 }
3841 }
3842 #endif /* SDIO_SUSPEND_RESUME*/
3843 #ifdef SDIO_MMC
3844 if (IS_SD(handle->card_type)) {
3845 sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
3846 }
3847 #endif
3848 if (hs_actived != MTRUE) {
3849 handle->hs_skip_count++;
3850 #ifdef SDIO_SUSPEND_RESUME
3851 if (IS_SD(handle->card_type)) {
3852 PRINTM(MCMND,
3853 "suspend skipped! timeout=%d allow=%d force=%u skip=%u\n",
3854 timeout, (int)pm_info.is_suspend_allowed,
3855 handle->hs_force_count, handle->hs_skip_count);
3856 }
3857 #else
3858 PRINTM(MCMND, "suspend skipped! timeout=%d skip=%u\n", timeout,
3859 handle->hs_skip_count);
3860 #endif
3861 woal_cancel_hs(priv, MOAL_NO_WAIT);
3862 }
3863 done:
3864 LEAVE();
3865 return hs_actived;
3866 }
3867
3868 #ifdef CONFIG_PROC_FS
3869 /**
3870 * @brief This function send soft_reset command to firmware
3871 *
3872 * @param handle A pointer to moal_handle structure
3873 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING on success,
3874 * otherwise failure code
3875 */
woal_request_soft_reset(moal_handle * handle)3876 mlan_status woal_request_soft_reset(moal_handle *handle)
3877 {
3878 mlan_status ret = MLAN_STATUS_SUCCESS;
3879 mlan_ioctl_req *req = NULL;
3880 mlan_ds_misc_cfg *misc = NULL;
3881
3882 ENTER();
3883 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3884 if (req) {
3885 misc = (mlan_ds_misc_cfg *)req->pbuf;
3886 misc->sub_command = MLAN_OID_MISC_SOFT_RESET;
3887 req->req_id = MLAN_IOCTL_MISC_CFG;
3888 req->action = MLAN_ACT_SET;
3889 ret = woal_request_ioctl(woal_get_priv(handle,
3890 MLAN_BSS_ROLE_ANY),
3891 req, MOAL_IOCTL_WAIT);
3892 }
3893
3894 handle->surprise_removed = MTRUE;
3895 woal_sched_timeout(5);
3896 if (ret != MLAN_STATUS_PENDING)
3897 kfree(req);
3898 LEAVE();
3899 return ret;
3900 }
3901 #endif /* CONFIG_PROC_FS */
3902
3903 /**
3904 * @brief Set wapi enable
3905 *
3906 * @param priv A pointer to moal_private structure
3907 * @param wait_option Wait option
3908 * @param enable MTRUE or MFALSE
3909 *
3910 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
3911 * success, otherwise fail
3912 */
woal_set_wapi_enable(moal_private * priv,t_u8 wait_option,t_u32 enable)3913 mlan_status woal_set_wapi_enable(moal_private *priv, t_u8 wait_option,
3914 t_u32 enable)
3915 {
3916 mlan_ioctl_req *req = NULL;
3917 mlan_ds_sec_cfg *sec = NULL;
3918 mlan_status status = MLAN_STATUS_SUCCESS;
3919 ENTER();
3920
3921 /* Allocate an IOCTL request buffer */
3922 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
3923 if (req == NULL) {
3924 status = MLAN_STATUS_FAILURE;
3925 goto done;
3926 }
3927
3928 /* Fill request buffer */
3929 sec = (mlan_ds_sec_cfg *)req->pbuf;
3930 sec->sub_command = MLAN_OID_SEC_CFG_WAPI_ENABLED;
3931 req->req_id = MLAN_IOCTL_SEC_CFG;
3932 req->action = MLAN_ACT_SET;
3933 sec->param.wapi_enabled = enable;
3934
3935 /* Send IOCTL request to MLAN */
3936 status = woal_request_ioctl(priv, req, wait_option);
3937 done:
3938 if (status != MLAN_STATUS_PENDING)
3939 kfree(req);
3940 LEAVE();
3941 return status;
3942 }
3943
3944 /**
3945 * @brief Get version
3946 *
3947 * @param handle A pointer to moal_handle structure
3948 * @param version A pointer to version buffer
3949 * @param max_len max length of version buffer
3950 *
3951 * @return N/A
3952 */
woal_get_version(moal_handle * handle,char * version,int max_len)3953 void woal_get_version(moal_handle *handle, char *version, int max_len)
3954 {
3955 t_u8 hotfix_ver = 0;
3956 union {
3957 t_u32 l;
3958 t_u8 c[4];
3959 } ver;
3960 char fw_ver[32];
3961
3962 ENTER();
3963
3964 hotfix_ver = handle->fw_hotfix_version;
3965 ver.l = handle->fw_release_number;
3966
3967 if (hotfix_ver) {
3968 snprintf(fw_ver, sizeof(fw_ver), "%u.%u.%u.p%u.%u", ver.c[2],
3969 ver.c[1], ver.c[0], ver.c[3], hotfix_ver);
3970
3971 } else {
3972 snprintf(fw_ver, sizeof(fw_ver), "%u.%u.%u.p%u", ver.c[2],
3973 ver.c[1], ver.c[0], ver.c[3]);
3974 }
3975
3976 snprintf(version, max_len, handle->driver_version, fw_ver);
3977
3978 LEAVE();
3979 }
3980
3981 #if defined(STA_WEXT) || defined(UAP_WEXT)
3982 /**
3983 * @brief Get Driver Version
3984 *
3985 * @param priv A pointer to moal_private structure
3986 * @param req A pointer to ifreq structure
3987 *
3988 * @return 0 --success, otherwise fail
3989 */
woal_get_driver_version(moal_private * priv,struct ifreq * req)3990 int woal_get_driver_version(moal_private *priv, struct ifreq *req)
3991 {
3992 struct iwreq *wrq = (struct iwreq *)req;
3993 int len;
3994 char buf[MLAN_MAX_VER_STR_LEN];
3995 ENTER();
3996
3997 woal_get_version(priv->phandle, buf, sizeof(buf) - 1);
3998
3999 len = strlen(buf);
4000 if (wrq->u.data.pointer) {
4001 if (copy_to_user(wrq->u.data.pointer, buf, len)) {
4002 PRINTM(MERROR, "Copy to user failed\n");
4003 LEAVE();
4004 return -EFAULT;
4005 }
4006 wrq->u.data.length = len;
4007 }
4008 PRINTM(MINFO, "MOAL VERSION: %s\n", buf);
4009 LEAVE();
4010 return 0;
4011 }
4012
4013 /**
4014 * @brief Get extended driver version
4015 *
4016 * @param priv A pointer to moal_private structure
4017 * @param ireq A pointer to ifreq structure
4018 *
4019 * @return 0 --success, otherwise fail
4020 */
woal_get_driver_verext(moal_private * priv,struct ifreq * ireq)4021 int woal_get_driver_verext(moal_private *priv, struct ifreq *ireq)
4022 {
4023 struct iwreq *wrq = (struct iwreq *)ireq;
4024 mlan_ds_get_info *info = NULL;
4025 mlan_ioctl_req *req = NULL;
4026 int ret = 0;
4027 mlan_status status = MLAN_STATUS_SUCCESS;
4028
4029 ENTER();
4030
4031 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
4032 if (req == NULL) {
4033 LEAVE();
4034 return -ENOMEM;
4035 }
4036
4037 info = (mlan_ds_get_info *)req->pbuf;
4038 info->sub_command = MLAN_OID_GET_VER_EXT;
4039 req->req_id = MLAN_IOCTL_GET_INFO;
4040 req->action = MLAN_ACT_GET;
4041
4042 if (!wrq->u.data.flags) {
4043 info->param.ver_ext.version_str_sel =
4044 *((int *)(wrq->u.name + SUBCMD_OFFSET));
4045 } else {
4046 if (copy_from_user(
4047 &info->param.ver_ext.version_str_sel,
4048 wrq->u.data.pointer,
4049 sizeof(info->param.ver_ext.version_str_sel))) {
4050 PRINTM(MERROR, "Copy from user failed\n");
4051 ret = -EFAULT;
4052 goto done;
4053 } else {
4054 if (((t_s32)(info->param.ver_ext.version_str_sel)) <
4055 0) {
4056 PRINTM(MERROR, "Invalid arguments!\n");
4057 ret = -EINVAL;
4058 goto done;
4059 }
4060 }
4061 }
4062
4063 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4064 if (status != MLAN_STATUS_SUCCESS) {
4065 ret = -EFAULT;
4066 goto done;
4067 }
4068
4069 if (wrq->u.data.pointer) {
4070 if (copy_to_user(wrq->u.data.pointer,
4071 info->param.ver_ext.version_str,
4072 strlen(info->param.ver_ext.version_str))) {
4073 PRINTM(MERROR, "Copy to user failed\n");
4074 ret = -EFAULT;
4075 goto done;
4076 }
4077 wrq->u.data.length = strlen(info->param.ver_ext.version_str);
4078 }
4079
4080 PRINTM(MINFO, "MOAL EXTENDED VERSION: %s\n",
4081 info->param.ver_ext.version_str);
4082 done:
4083 if (status != MLAN_STATUS_PENDING)
4084 kfree(req);
4085
4086 LEAVE();
4087 return ret;
4088 }
4089 #endif
4090
4091 #ifdef DEBUG_LEVEL1
4092 /**
4093 * @brief Set driver debug bit masks to mlan in order to enhance performance
4094 *
4095 * @param priv A pointer to moal_private structure
4096 * @param drv_dbg Driver debug level
4097 *
4098 * @return 0 --success, otherwise fail
4099 */
woal_set_drvdbg(moal_private * priv,t_u32 drv_dbg)4100 int woal_set_drvdbg(moal_private *priv, t_u32 drv_dbg)
4101 {
4102 mlan_ioctl_req *req = NULL;
4103 mlan_ds_misc_cfg *misc = NULL;
4104 int ret = 0;
4105
4106 ENTER();
4107
4108 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
4109 if (req == NULL) {
4110 LEAVE();
4111 return -ENOMEM;
4112 }
4113
4114 misc = (mlan_ds_misc_cfg *)req->pbuf;
4115 misc->sub_command = MLAN_OID_MISC_DRVDBG;
4116 req->req_id = MLAN_IOCTL_MISC_CFG;
4117 req->action = MLAN_ACT_SET;
4118 misc->param.drvdbg = drv_dbg;
4119
4120 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4121
4122 if (ret != MLAN_STATUS_PENDING)
4123 kfree(req);
4124
4125 LEAVE();
4126 return ret;
4127 }
4128 #endif
4129
4130 /**
4131 * @brief Mgmt frame forward registration
4132 *
4133 * @param priv A pointer to moal_private structure
4134 * @param action Action: set or get
4135 * @param pmgmt_subtype_mask A Pointer to mgmt frame subtype mask
4136 * @param wait_option wait option (MOAL_WAIT or MOAL_NO_WAIT)
4137 *
4138 * @return 0 --success, otherwise fail
4139 */
woal_reg_rx_mgmt_ind(moal_private * priv,t_u16 action,t_u32 * pmgmt_subtype_mask,t_u8 wait_option)4140 int woal_reg_rx_mgmt_ind(moal_private *priv, t_u16 action,
4141 t_u32 *pmgmt_subtype_mask, t_u8 wait_option)
4142 {
4143 mlan_ioctl_req *req = NULL;
4144 mlan_ds_misc_cfg *misc = NULL;
4145 int ret = 0;
4146
4147 ENTER();
4148
4149 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
4150 if (req == NULL) {
4151 LEAVE();
4152 return -ENOMEM;
4153 }
4154
4155 misc = (mlan_ds_misc_cfg *)req->pbuf;
4156 misc->sub_command = MLAN_OID_MISC_RX_MGMT_IND;
4157 req->req_id = MLAN_IOCTL_MISC_CFG;
4158 req->action = action;
4159 misc->param.mgmt_subtype_mask = *pmgmt_subtype_mask;
4160 if (req->action == MLAN_ACT_SET)
4161 moal_memcpy_ext(priv->phandle, &misc->param.mgmt_subtype_mask,
4162 pmgmt_subtype_mask,
4163 sizeof(misc->param.mgmt_subtype_mask),
4164 sizeof(misc->param.mgmt_subtype_mask));
4165
4166 ret = woal_request_ioctl(priv, req, wait_option);
4167
4168 if (req->action == MLAN_ACT_GET)
4169 moal_memcpy_ext(priv->phandle, pmgmt_subtype_mask,
4170 &misc->param.mgmt_subtype_mask,
4171 sizeof(misc->param.mgmt_subtype_mask),
4172 sizeof(misc->param.mgmt_subtype_mask));
4173
4174 if (ret != MLAN_STATUS_PENDING)
4175 kfree(req);
4176
4177 LEAVE();
4178 return ret;
4179 }
4180
4181 /**
4182 * @brief Set/Get Transmit beamforming capabilities
4183 *
4184 * @param priv A pointer to moal_private structure
4185 * @param action Action: set or get
4186 * @param tx_bf_cap A pointer to tx_buf_cap buffer
4187 *
4188 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
4189 */
woal_set_get_tx_bf_cap(moal_private * priv,t_u16 action,t_u32 * tx_bf_cap)4190 mlan_status woal_set_get_tx_bf_cap(moal_private *priv, t_u16 action,
4191 t_u32 *tx_bf_cap)
4192 {
4193 mlan_ioctl_req *req = NULL;
4194 mlan_ds_11n_cfg *bf_cfg = NULL;
4195 mlan_status ret = MLAN_STATUS_SUCCESS;
4196
4197 ENTER();
4198
4199 if (!tx_bf_cap) {
4200 ret = MLAN_STATUS_FAILURE;
4201 goto done;
4202 }
4203 /* Allocate an IOCTL request buffer */
4204 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
4205 if (req == NULL) {
4206 ret = MLAN_STATUS_FAILURE;
4207 goto done;
4208 }
4209
4210 /* Fill request buffer */
4211 bf_cfg = (mlan_ds_11n_cfg *)req->pbuf;
4212 req->req_id = MLAN_IOCTL_11N_CFG;
4213 bf_cfg->sub_command = MLAN_OID_11N_CFG_TX_BF_CAP;
4214 req->action = action;
4215 if (action == MLAN_ACT_SET)
4216 bf_cfg->param.tx_bf_cap = *tx_bf_cap;
4217
4218 /* Send IOCTL request to MLAN */
4219 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4220 if (ret != MLAN_STATUS_SUCCESS) {
4221 goto done;
4222 }
4223
4224 if (action == MLAN_ACT_GET)
4225 *tx_bf_cap = bf_cfg->param.tx_bf_cap;
4226
4227 done:
4228 if (ret != MLAN_STATUS_PENDING)
4229 kfree(req);
4230 LEAVE();
4231 return ret;
4232 }
4233
4234 /**
4235 * @brief Set/Get Transmit beamforming configuration
4236 *
4237 * @param priv A pointer to moal_private structure
4238 * @param action Action: set or get
4239 * @param tx_bf_cfg A pointer to tx_bf_cfg structure
4240 *
4241 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
4242 */
woal_set_get_tx_bf_cfg(moal_private * priv,t_u16 action,mlan_ds_11n_tx_bf_cfg * tx_bf_cfg)4243 mlan_status woal_set_get_tx_bf_cfg(moal_private *priv, t_u16 action,
4244 mlan_ds_11n_tx_bf_cfg *tx_bf_cfg)
4245 {
4246 mlan_status ret = MLAN_STATUS_SUCCESS;
4247 mlan_ioctl_req *req = NULL;
4248 mlan_ds_11n_cfg *bf_cfg = NULL;
4249
4250 ENTER();
4251
4252 /* Sanity test */
4253 if (tx_bf_cfg == NULL) {
4254 ret = MLAN_STATUS_FAILURE;
4255 goto done;
4256 }
4257
4258 /* Allocate an IOCTL request buffer */
4259 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
4260 if (req == NULL) {
4261 ret = MLAN_STATUS_FAILURE;
4262 goto done;
4263 }
4264
4265 /* Fill request buffer */
4266 bf_cfg = (mlan_ds_11n_cfg *)req->pbuf;
4267 req->req_id = MLAN_IOCTL_11N_CFG;
4268 bf_cfg->sub_command = MLAN_OID_11N_CFG_TX_BF_CFG;
4269
4270 req->action = action;
4271 moal_memcpy_ext(priv->phandle, &bf_cfg->param.tx_bf, tx_bf_cfg,
4272 sizeof(mlan_ds_11n_tx_bf_cfg),
4273 sizeof(mlan_ds_11n_tx_bf_cfg));
4274
4275 /* Send IOCTL request to MLAN */
4276 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4277 if (ret != MLAN_STATUS_SUCCESS)
4278 goto done;
4279
4280 if (action == MLAN_ACT_GET)
4281 moal_memcpy_ext(priv->phandle, tx_bf_cfg, &bf_cfg->param.tx_bf,
4282 sizeof(mlan_ds_11n_tx_bf_cfg),
4283 sizeof(mlan_ds_11n_tx_bf_cfg));
4284
4285 done:
4286 if (ret != MLAN_STATUS_PENDING)
4287 kfree(req);
4288 LEAVE();
4289 return ret;
4290 }
4291
4292 /**
4293 * @brief Handle ioctl resp
4294 *
4295 * @param priv Pointer to moal_private structure
4296 * @param req Pointer to mlan_ioctl_req structure
4297 *
4298 * @return N/A
4299 */
woal_process_ioctl_resp(moal_private * priv,mlan_ioctl_req * req)4300 void woal_process_ioctl_resp(moal_private *priv, mlan_ioctl_req *req)
4301 {
4302 int cfg80211_wext;
4303
4304 ENTER();
4305
4306 if (priv == NULL) {
4307 LEAVE();
4308 return;
4309 }
4310 cfg80211_wext = priv->phandle->params.cfg80211_wext;
4311 switch (req->req_id) {
4312 case MLAN_IOCTL_GET_INFO:
4313 #ifdef STA_WEXT
4314 #ifdef STA_SUPPORT
4315 if (IS_STA_WEXT(cfg80211_wext) &&
4316 GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
4317 woal_ioctl_get_info_resp(priv,
4318 (mlan_ds_get_info *)req->pbuf);
4319 #endif
4320 #endif
4321 #ifdef UAP_WEXT
4322 #ifdef UAP_SUPPORT
4323 if (IS_UAP_WEXT(cfg80211_wext) &&
4324 GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
4325 woal_ioctl_get_uap_info_resp(
4326 priv, (mlan_ds_get_info *)req->pbuf);
4327 #endif
4328 #endif
4329 break;
4330 #ifdef STA_WEXT
4331 #ifdef STA_SUPPORT
4332 case MLAN_IOCTL_BSS:
4333 if (IS_STA_WEXT(cfg80211_wext) &&
4334 GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
4335 woal_ioctl_get_bss_resp(priv, (mlan_ds_bss *)req->pbuf);
4336 break;
4337 #endif
4338 #endif
4339 case MLAN_IOCTL_MISC_CFG:
4340 woal_ioctl_get_misc_conf(priv, (mlan_ds_misc_cfg *)req->pbuf);
4341 default:
4342 break;
4343 }
4344
4345 LEAVE();
4346 return;
4347 }
4348
4349 /**
4350 * @brief Get PM info
4351 *
4352 * @param priv A pointer to moal_private structure
4353 * @param pm_info A pointer to mlan_ds_ps_info structure
4354 *
4355 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
4356 * success, otherwise fail
4357 */
woal_get_pm_info(moal_private * priv,mlan_ds_ps_info * pm_info)4358 mlan_status woal_get_pm_info(moal_private *priv, mlan_ds_ps_info *pm_info)
4359 {
4360 mlan_status ret = MLAN_STATUS_SUCCESS;
4361 mlan_ds_pm_cfg *pmcfg = NULL;
4362 mlan_ioctl_req *req = NULL;
4363
4364 ENTER();
4365
4366 /* Allocate an IOCTL request buffer */
4367 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
4368 if (req == NULL) {
4369 PRINTM(MERROR, "Fail to alloc mlan_ds_pm_cfg buffer\n");
4370 ret = MLAN_STATUS_FAILURE;
4371 goto done;
4372 }
4373
4374 /* Fill request buffer */
4375 pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
4376 pmcfg->sub_command = MLAN_OID_PM_INFO;
4377 req->req_id = MLAN_IOCTL_PM_CFG;
4378 req->action = MLAN_ACT_GET;
4379
4380 /* Send IOCTL request to MLAN */
4381 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4382 if (ret == MLAN_STATUS_SUCCESS) {
4383 if (pm_info) {
4384 moal_memcpy_ext(priv->phandle, pm_info,
4385 &pmcfg->param.ps_info,
4386 sizeof(mlan_ds_ps_info),
4387 sizeof(mlan_ds_ps_info));
4388 }
4389 }
4390 done:
4391 if (ret != MLAN_STATUS_PENDING)
4392 kfree(req);
4393 LEAVE();
4394 return ret;
4395 }
4396
4397 /**
4398 * @brief Get Deep Sleep
4399 *
4400 * @param priv Pointer to the moal_private driver data struct
4401 * @param data Pointer to return deep_sleep setting
4402 *
4403 * @return 0 --success, otherwise fail
4404 */
woal_get_deep_sleep(moal_private * priv,t_u32 * data)4405 int woal_get_deep_sleep(moal_private *priv, t_u32 *data)
4406 {
4407 int ret = 0;
4408 mlan_ioctl_req *req = NULL;
4409 mlan_ds_pm_cfg *pm = NULL;
4410 mlan_status status = MLAN_STATUS_SUCCESS;
4411
4412 ENTER();
4413
4414 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
4415 if (req == NULL) {
4416 LEAVE();
4417 return -ENOMEM;
4418 }
4419 pm = (mlan_ds_pm_cfg *)req->pbuf;
4420 pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP;
4421 req->req_id = MLAN_IOCTL_PM_CFG;
4422
4423 req->action = MLAN_ACT_GET;
4424 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4425 if (status != MLAN_STATUS_SUCCESS) {
4426 ret = -EFAULT;
4427 goto done;
4428 }
4429 *data = pm->param.auto_deep_sleep.auto_ds;
4430 *(data + 1) = pm->param.auto_deep_sleep.idletime;
4431
4432 done:
4433 if (status != MLAN_STATUS_PENDING)
4434 kfree(req);
4435 LEAVE();
4436 return ret;
4437 }
4438
4439 /**
4440 * @brief Set Deep Sleep
4441 *
4442 * @param priv Pointer to the moal_private driver data struct
4443 * @param wait_option wait option
4444 * @param bdeep_sleep TRUE--enalbe deepsleep, FALSE--disable deepsleep
4445 * @param idletime Idle time for optimized PS API
4446 *
4447 * @return 0 --success, otherwise fail
4448 */
woal_set_deep_sleep(moal_private * priv,t_u8 wait_option,BOOLEAN bdeep_sleep,t_u16 idletime)4449 int woal_set_deep_sleep(moal_private *priv, t_u8 wait_option,
4450 BOOLEAN bdeep_sleep, t_u16 idletime)
4451 {
4452 int ret = 0;
4453 mlan_ioctl_req *req = NULL;
4454 mlan_ds_pm_cfg *pm = NULL;
4455
4456 ENTER();
4457
4458 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
4459 if (req == NULL) {
4460 LEAVE();
4461 return -ENOMEM;
4462 }
4463 pm = (mlan_ds_pm_cfg *)req->pbuf;
4464 pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP;
4465 req->req_id = MLAN_IOCTL_PM_CFG;
4466
4467 req->action = MLAN_ACT_SET;
4468 if (bdeep_sleep == MTRUE) {
4469 PRINTM(MIOCTL, "Deep Sleep: sleep\n");
4470 pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_ON;
4471 if (idletime)
4472 pm->param.auto_deep_sleep.idletime = idletime;
4473 ret = woal_request_ioctl(priv, req, wait_option);
4474 if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING) {
4475 ret = -EFAULT;
4476 goto done;
4477 }
4478 } else {
4479 PRINTM(MIOCTL, "%lu : Deep Sleep: wakeup\n", jiffies);
4480 pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_OFF;
4481 ret = woal_request_ioctl(priv, req, wait_option);
4482 if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING) {
4483 ret = -EFAULT;
4484 goto done;
4485 }
4486 }
4487 done:
4488 if (ret != MLAN_STATUS_PENDING)
4489 kfree(req);
4490 LEAVE();
4491 return ret;
4492 }
4493
4494 /**
4495 * @brief Cancel CAC period block
4496 *
4497 * @param priv A pointer to moal_private structure
4498 *
4499 * @return N/A
4500 */
woal_cancel_cac_block(moal_private * priv)4501 void woal_cancel_cac_block(moal_private *priv)
4502 {
4503 ENTER();
4504 /* if during CAC period, wake up wait queue */
4505 if (priv->phandle->cac_period == MTRUE) {
4506 priv->phandle->cac_period = MFALSE;
4507 /* Make sure Chan Report is cancelled */
4508 if (woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT))
4509 PRINTM(MERROR,
4510 "%s: Cancelling CAC chan report in FW failed \n",
4511 __func__);
4512 priv->phandle->meas_start_jiffies = 0;
4513 if (priv->phandle->delay_bss_start == MTRUE)
4514 priv->phandle->delay_bss_start = MFALSE;
4515 if (priv->phandle->meas_wait_q_woken == MFALSE) {
4516 priv->phandle->meas_wait_q_woken = MTRUE;
4517 wake_up_interruptible(&priv->phandle->meas_wait_q);
4518 }
4519 #ifdef UAP_SUPPORT
4520 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
4521 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
4522 if (priv->uap_host_based &&
4523 moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
4524 woal_cfg80211_dfs_vendor_event(
4525 priv, event_dfs_cac_aborted, &priv->chan);
4526 #endif
4527 #endif
4528 #endif
4529 }
4530 LEAVE();
4531 }
4532
4533 /** MEAS report timeout value in seconds */
4534
4535 /**
4536 * @brief Issue MLAN_OID_11H_CHANNEL_CHECK ioctl
4537 *
4538 * @param priv Pointer to the moal_private driver data struct
4539 * @param wait_option wait option
4540 *
4541 * @return 0 --success, otherwise fail
4542 */
woal_11h_channel_check_ioctl(moal_private * priv,t_u8 wait_option)4543 int woal_11h_channel_check_ioctl(moal_private *priv, t_u8 wait_option)
4544 {
4545 int ret = 0;
4546 mlan_ioctl_req *req = NULL;
4547 mlan_ds_11h_cfg *ds_11hcfg = NULL;
4548 mlan_status status = MLAN_STATUS_SUCCESS;
4549
4550 ENTER();
4551
4552 #ifdef UAP_SUPPORT
4553 if (priv->skip_cac) {
4554 LEAVE();
4555 return ret;
4556 }
4557 #endif
4558
4559 /* Skip sending request/report query when DFS_REPEATER_MODE is on. This
4560 * would get rid of CAC timers before starting BSSes in
4561 * DFS_REPEATER_MODE
4562 */
4563 if (priv->phandle->dfs_repeater_mode) {
4564 LEAVE();
4565 return ret;
4566 }
4567
4568 if (woal_is_any_interface_active(priv->phandle)) {
4569 }
4570
4571 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
4572 if (req == NULL) {
4573 ret = -ENOMEM;
4574 goto done;
4575 }
4576 ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
4577
4578 ds_11hcfg->sub_command = MLAN_OID_11H_CHANNEL_CHECK;
4579 ds_11hcfg->param.chan_rpt_req.host_based = MFALSE;
4580 req->req_id = MLAN_IOCTL_11H_CFG;
4581 req->action = MLAN_ACT_SET;
4582 /* Send Channel Check command and wait until the report is ready */
4583 status = woal_request_ioctl(priv, req, wait_option);
4584 if (status != MLAN_STATUS_SUCCESS) {
4585 goto done;
4586 }
4587
4588 /* set flag from here */
4589 priv->phandle->cac_period = MTRUE;
4590 priv->phandle->meas_start_jiffies = jiffies;
4591 priv->phandle->cac_timer_jiffies =
4592 ds_11hcfg->param.chan_rpt_req.millisec_dwell_time * HZ / 1000;
4593
4594 #ifdef UAP_SUPPORT
4595 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
4596 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
4597 if (priv->uap_host_based &&
4598 moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
4599 woal_cfg80211_dfs_vendor_event(priv, event_dfs_cac_started,
4600 &priv->chan);
4601 #endif
4602 #endif
4603 #endif
4604 done:
4605 if (status != MLAN_STATUS_PENDING)
4606 kfree(req);
4607 LEAVE();
4608 return ret;
4609 }
4610
4611 /**
4612 * @brief Issue MLAN_OID_11H_CHAN_REPORT_REQUEST ioctl to cancel dozer
4613 *
4614 * @param priv Pointer to the moal_private driver data struct
4615 * @param wait_option wait option
4616 *
4617 * @return 0 --success, otherwise fail
4618 */
woal_11h_cancel_chan_report_ioctl(moal_private * priv,t_u8 wait_option)4619 int woal_11h_cancel_chan_report_ioctl(moal_private *priv, t_u8 wait_option)
4620 {
4621 int ret = 0;
4622 mlan_ioctl_req *req = NULL;
4623 mlan_ds_11h_cfg *ds_11hcfg = NULL;
4624 mlan_status status = MLAN_STATUS_SUCCESS;
4625
4626 ENTER();
4627 PRINTM(MCMND, "wlan: woal_11h_cancel_chan_report\n");
4628 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
4629 if (req == NULL) {
4630 ret = -ENOMEM;
4631 goto done;
4632 }
4633 ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
4634
4635 ds_11hcfg->sub_command = MLAN_OID_11H_CHAN_REPORT_REQUEST;
4636 req->req_id = MLAN_IOCTL_11H_CFG;
4637 req->action = MLAN_ACT_SET;
4638 ds_11hcfg->param.chan_rpt_req.millisec_dwell_time = 0;
4639 /* Send Channel Check command and wait until the report is ready */
4640 status = woal_request_ioctl(priv, req, wait_option);
4641 if (status != MLAN_STATUS_SUCCESS) {
4642 ret = -EFAULT;
4643 goto done;
4644 }
4645
4646 done:
4647 if (status != MLAN_STATUS_PENDING)
4648 kfree(req);
4649 LEAVE();
4650 return ret;
4651 }
4652
4653 /**
4654 * @brief set remain channel
4655 *
4656 * @param priv A pointer to moal_private structure
4657 * @param wait_option Wait option
4658 * @param pchan A pointer to mlan_ds_remain_chan structure
4659 *
4660 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
4661 */
woal_set_remain_channel_ioctl(moal_private * priv,t_u8 wait_option,mlan_ds_remain_chan * pchan)4662 mlan_status woal_set_remain_channel_ioctl(moal_private *priv, t_u8 wait_option,
4663 mlan_ds_remain_chan *pchan)
4664 {
4665 mlan_status ret = MLAN_STATUS_SUCCESS;
4666 mlan_ioctl_req *req = NULL;
4667 mlan_ds_radio_cfg *radio_cfg = NULL;
4668
4669 ENTER();
4670 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
4671 if (req == NULL) {
4672 ret = MLAN_STATUS_FAILURE;
4673 goto done;
4674 }
4675 radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
4676 radio_cfg->sub_command = MLAN_OID_REMAIN_CHAN_CFG;
4677 req->req_id = MLAN_IOCTL_RADIO_CFG;
4678
4679 req->action = MLAN_ACT_SET;
4680 moal_memcpy_ext(priv->phandle, &radio_cfg->param.remain_chan, pchan,
4681 sizeof(mlan_ds_remain_chan),
4682 sizeof(mlan_ds_remain_chan));
4683 ret = woal_request_ioctl(priv, req, wait_option);
4684 if (ret == MLAN_STATUS_SUCCESS) {
4685 moal_memcpy_ext(priv->phandle, pchan,
4686 &radio_cfg->param.remain_chan,
4687 sizeof(mlan_ds_remain_chan),
4688 sizeof(mlan_ds_remain_chan));
4689 PRINTM(MCMND,
4690 "Remain_chan_cfg: remove=%d, channel=%d, remain_period=%d\n",
4691 pchan->remove, pchan->channel, pchan->remain_period);
4692 }
4693 done:
4694 if (ret != MLAN_STATUS_PENDING)
4695 kfree(req);
4696 LEAVE();
4697 return ret;
4698 }
4699
4700 #ifdef WIFI_DIRECT_SUPPORT
4701 /**
4702 * @brief set/get wifi direct mode
4703 *
4704 * @param priv A pointer to moal_private structure
4705 * @param action set or get
4706 * @param mode A pointer to wifi direct mode
4707 *
4708 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
4709 */
woal_wifi_direct_mode_cfg(moal_private * priv,t_u16 action,t_u16 * mode)4710 mlan_status woal_wifi_direct_mode_cfg(moal_private *priv, t_u16 action,
4711 t_u16 *mode)
4712 {
4713 mlan_status ret = MLAN_STATUS_SUCCESS;
4714 mlan_ioctl_req *req = NULL;
4715 mlan_ds_bss *bss = NULL;
4716
4717 ENTER();
4718 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4719 if (req == NULL) {
4720 ret = MLAN_STATUS_FAILURE;
4721 goto done;
4722 }
4723 bss = (mlan_ds_bss *)req->pbuf;
4724 bss->sub_command = MLAN_OID_WIFI_DIRECT_MODE;
4725 req->req_id = MLAN_IOCTL_BSS;
4726
4727 req->action = action;
4728 if (action == MLAN_ACT_SET)
4729 bss->param.wfd_mode = *mode;
4730 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4731 if (ret == MLAN_STATUS_SUCCESS) {
4732 *mode = bss->param.wfd_mode;
4733 PRINTM(MIOCTL, "ACT=%d, wifi_direct_mode=%d\n", action, *mode);
4734 }
4735 done:
4736 if (ret != MLAN_STATUS_PENDING)
4737 kfree(req);
4738 LEAVE();
4739 return ret;
4740 }
4741
4742 /**
4743 * @brief Set p2p config
4744 *
4745 * @param priv A pointer to moal_private structure
4746 * @param action Action set or get
4747 * @param p2p_config A pointer to mlan_ds_wifi_direct_config structure
4748 *
4749 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
4750 */
woal_p2p_config(moal_private * priv,t_u32 action,mlan_ds_wifi_direct_config * p2p_config)4751 mlan_status woal_p2p_config(moal_private *priv, t_u32 action,
4752 mlan_ds_wifi_direct_config *p2p_config)
4753 {
4754 mlan_status ret = MLAN_STATUS_SUCCESS;
4755 mlan_ioctl_req *req = NULL;
4756 mlan_ds_misc_cfg *misc_cfg = NULL;
4757
4758 ENTER();
4759 if (!p2p_config) {
4760 LEAVE();
4761 return MLAN_STATUS_FAILURE;
4762 }
4763 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
4764 if (req == NULL) {
4765 ret = MLAN_STATUS_FAILURE;
4766 goto done;
4767 }
4768 misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
4769 misc_cfg->sub_command = MLAN_OID_MISC_WIFI_DIRECT_CONFIG;
4770 req->req_id = MLAN_IOCTL_MISC_CFG;
4771 req->action = action;
4772 moal_memcpy_ext(priv->phandle, &misc_cfg->param.p2p_config, p2p_config,
4773 sizeof(mlan_ds_wifi_direct_config),
4774 sizeof(mlan_ds_wifi_direct_config));
4775 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4776 if (ret == MLAN_STATUS_SUCCESS) {
4777 if (action == MLAN_ACT_GET)
4778 moal_memcpy_ext(priv->phandle, p2p_config,
4779 &misc_cfg->param.p2p_config,
4780 sizeof(mlan_ds_wifi_direct_config),
4781 sizeof(mlan_ds_wifi_direct_config));
4782 }
4783 done:
4784 if (ret != MLAN_STATUS_PENDING)
4785 kfree(req);
4786 LEAVE();
4787 return ret;
4788 }
4789 #endif /* WIFI_DIRECT_SUPPORT */
4790
4791 #ifdef STA_SUPPORT
4792 /**
4793 * @brief Get STA Channel Info
4794 *
4795 * @param priv A pointer to moal_private structure
4796 * @param wait_option Wait option
4797 * @param channel A pointer to channel info
4798 *
4799 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
4800 * success, otherwise fail
4801 */
woal_get_sta_channel(moal_private * priv,t_u8 wait_option,chan_band_info * channel)4802 mlan_status woal_get_sta_channel(moal_private *priv, t_u8 wait_option,
4803 chan_band_info *channel)
4804 {
4805 mlan_ioctl_req *req = NULL;
4806 mlan_ds_bss *bss = NULL;
4807 mlan_status status = MLAN_STATUS_SUCCESS;
4808 ENTER();
4809
4810 /* Allocate an IOCTL request buffer */
4811 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4812 if (req == NULL) {
4813 PRINTM(MERROR, "woal_get_sta_channel req alloc fail\n");
4814 status = MLAN_STATUS_FAILURE;
4815 goto done;
4816 }
4817
4818 /* Fill request buffer */
4819 bss = (mlan_ds_bss *)req->pbuf;
4820 bss->sub_command = MLAN_OID_BSS_CHAN_INFO;
4821 req->req_id = MLAN_IOCTL_BSS;
4822 req->action = MLAN_ACT_GET;
4823
4824 /* Send IOCTL request to MLAN */
4825 status = woal_request_ioctl(priv, req, wait_option);
4826 if (status == MLAN_STATUS_SUCCESS && channel)
4827 moal_memcpy_ext(priv->phandle, channel,
4828 &(bss->param.sta_channel),
4829 sizeof(chan_band_info), sizeof(chan_band_info));
4830
4831 done:
4832 if (status != MLAN_STATUS_PENDING)
4833 kfree(req);
4834 LEAVE();
4835 return status;
4836 }
4837
4838 /**
4839 * @brief Get RSSI info
4840 *
4841 * @param priv A pointer to moal_private structure
4842 * @param wait_option Wait option
4843 * @param signal A pointer tp mlan_ds_get_signal structure
4844 *
4845 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
4846 * otherwise fail
4847 */
woal_get_signal_info(moal_private * priv,t_u8 wait_option,mlan_ds_get_signal * signal)4848 mlan_status woal_get_signal_info(moal_private *priv, t_u8 wait_option,
4849 mlan_ds_get_signal *signal)
4850 {
4851 mlan_ds_get_info *info = NULL;
4852 mlan_ioctl_req *req = NULL;
4853 mlan_status status = MLAN_STATUS_SUCCESS;
4854
4855 ENTER();
4856
4857 /* Allocate an IOCTL request buffer */
4858 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
4859 if (req == NULL) {
4860 status = MLAN_STATUS_FAILURE;
4861 goto done;
4862 }
4863
4864 /* Fill request buffer */
4865 info = (mlan_ds_get_info *)req->pbuf;
4866 info->sub_command = MLAN_OID_GET_SIGNAL;
4867 info->param.signal.selector = ALL_RSSI_INFO_MASK;
4868 req->req_id = MLAN_IOCTL_GET_INFO;
4869 req->action = MLAN_ACT_GET;
4870
4871 /* Send IOCTL request to MLAN */
4872 status = woal_request_ioctl(priv, req, wait_option);
4873 if (status == MLAN_STATUS_SUCCESS) {
4874 if (signal)
4875 moal_memcpy_ext(priv->phandle, signal,
4876 &info->param.signal,
4877 sizeof(mlan_ds_get_signal),
4878 sizeof(mlan_ds_get_signal));
4879 #ifdef STA_WEXT
4880 if (IS_STA_WEXT(priv->phandle->params.cfg80211_wext)) {
4881 if (info->param.signal.selector & BCN_RSSI_AVG_MASK)
4882 priv->w_stats.qual.level =
4883 info->param.signal.bcn_rssi_avg;
4884 if (info->param.signal.selector & BCN_NF_AVG_MASK)
4885 priv->w_stats.qual.noise =
4886 info->param.signal.bcn_nf_avg;
4887 }
4888 #endif
4889 }
4890 done:
4891 if (status != MLAN_STATUS_PENDING)
4892 kfree(req);
4893 LEAVE();
4894 return status;
4895 }
4896
4897 /**
4898 * @brief Get scan table
4899 *
4900 * @param priv A pointer to moal_private structure
4901 * @param wait_option Wait option
4902 * @param scan_resp A pointer to mlan_scan_resp structure
4903 *
4904 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
4905 * otherwise fail
4906 */
woal_get_scan_table(moal_private * priv,t_u8 wait_option,mlan_scan_resp * scan_resp)4907 mlan_status woal_get_scan_table(moal_private *priv, t_u8 wait_option,
4908 mlan_scan_resp *scan_resp)
4909 {
4910 mlan_ioctl_req *req = NULL;
4911 mlan_ds_scan *scan = NULL;
4912 mlan_status status = MLAN_STATUS_SUCCESS;
4913 ENTER();
4914
4915 if (!scan_resp) {
4916 LEAVE();
4917 return MLAN_STATUS_FAILURE;
4918 }
4919
4920 /* Allocate an IOCTL request buffer */
4921 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
4922 if (req == NULL) {
4923 status = MLAN_STATUS_FAILURE;
4924 goto done;
4925 }
4926
4927 /* Fill request buffer */
4928 scan = (mlan_ds_scan *)req->pbuf;
4929 scan->sub_command = MLAN_OID_SCAN_NORMAL;
4930 req->req_id = MLAN_IOCTL_SCAN;
4931 req->action = MLAN_ACT_GET;
4932 moal_memcpy_ext(priv->phandle, (void *)&scan->param.scan_resp,
4933 (void *)scan_resp, sizeof(mlan_scan_resp),
4934 sizeof(mlan_scan_resp));
4935
4936 /* Send IOCTL request to MLAN */
4937 status = woal_request_ioctl(priv, req, wait_option);
4938 if (status == MLAN_STATUS_SUCCESS) {
4939 if (scan_resp) {
4940 moal_memcpy_ext(priv->phandle, scan_resp,
4941 &scan->param.scan_resp,
4942 sizeof(mlan_scan_resp),
4943 sizeof(mlan_scan_resp));
4944 }
4945 }
4946
4947 done:
4948 if (status != MLAN_STATUS_PENDING)
4949 kfree(req);
4950 LEAVE();
4951 return status;
4952 }
4953
4954 /**
4955 * @brief Request a scan
4956 *
4957 * @param priv A pointer to moal_private structure
4958 * @param wait_option Wait option
4959 * @param req_ssid A pointer to mlan_802_11_ssid structure
4960 *
4961 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
4962 */
woal_request_scan(moal_private * priv,t_u8 wait_option,mlan_802_11_ssid * req_ssid)4963 mlan_status woal_request_scan(moal_private *priv, t_u8 wait_option,
4964 mlan_802_11_ssid *req_ssid)
4965 {
4966 mlan_status ret = MLAN_STATUS_SUCCESS;
4967 moal_handle *handle = priv->phandle;
4968 mlan_ioctl_req *ioctl_req = NULL;
4969 mlan_ds_scan *scan = NULL;
4970 mlan_status status = MLAN_STATUS_SUCCESS;
4971 ENTER();
4972
4973 if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->async_sem)) {
4974 PRINTM(MERROR, "Acquire semaphore error, request_scan\n");
4975 LEAVE();
4976 return MLAN_STATUS_FAILURE;
4977 }
4978 handle->scan_pending_on_block = MTRUE;
4979 handle->scan_priv = priv;
4980
4981 /* Allocate an IOCTL request buffer */
4982 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
4983 if (ioctl_req == NULL) {
4984 ret = MLAN_STATUS_FAILURE;
4985 goto done;
4986 }
4987
4988 scan = (mlan_ds_scan *)ioctl_req->pbuf;
4989
4990 if (req_ssid && req_ssid->ssid_len != 0) {
4991 /* Specific SSID scan */
4992 ioctl_req->req_id = MLAN_IOCTL_SCAN;
4993 ioctl_req->action = MLAN_ACT_SET;
4994
4995 scan->sub_command = MLAN_OID_SCAN_SPECIFIC_SSID;
4996
4997 moal_memcpy_ext(handle, scan->param.scan_req.scan_ssid.ssid,
4998 req_ssid->ssid, req_ssid->ssid_len,
4999 MLAN_MAX_SSID_LENGTH);
5000 scan->param.scan_req.scan_ssid.ssid_len =
5001 MIN(MLAN_MAX_SSID_LENGTH, req_ssid->ssid_len);
5002 } else {
5003 /* Normal scan */
5004 ioctl_req->req_id = MLAN_IOCTL_SCAN;
5005 ioctl_req->action = MLAN_ACT_SET;
5006
5007 scan->sub_command = MLAN_OID_SCAN_NORMAL;
5008 }
5009 /* Send IOCTL request to MLAN */
5010 status = woal_request_ioctl(priv, ioctl_req, wait_option);
5011
5012 if (status == MLAN_STATUS_FAILURE) {
5013 ret = MLAN_STATUS_FAILURE;
5014 goto done;
5015 }
5016 done:
5017 if (status != MLAN_STATUS_PENDING)
5018 kfree(ioctl_req);
5019
5020 if (ret == MLAN_STATUS_FAILURE) {
5021 handle->scan_pending_on_block = MFALSE;
5022 handle->scan_priv = NULL;
5023 MOAL_REL_SEMAPHORE(&handle->async_sem);
5024 }
5025 LEAVE();
5026 return ret;
5027 }
5028
5029 /**
5030 * @brief Change Adhoc Channel
5031 *
5032 * @param priv A pointer to moal_private structure
5033 * @param channel The channel to be set.
5034 * @param wait_option wait_option
5035 *
5036 * @return MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail
5037 */
woal_change_adhoc_chan(moal_private * priv,int channel,t_u8 wait_option)5038 mlan_status woal_change_adhoc_chan(moal_private *priv, int channel,
5039 t_u8 wait_option)
5040 {
5041 mlan_status ret = MLAN_STATUS_SUCCESS;
5042 mlan_bss_info bss_info;
5043 mlan_ds_bss *bss = NULL;
5044 mlan_ioctl_req *req = NULL;
5045
5046 ENTER();
5047
5048 memset(&bss_info, 0, sizeof(bss_info));
5049
5050 /* Get BSS information */
5051 if (MLAN_STATUS_SUCCESS !=
5052 woal_get_bss_info(priv, wait_option, &bss_info)) {
5053 ret = MLAN_STATUS_FAILURE;
5054 goto done;
5055 }
5056 if (bss_info.bss_mode == MLAN_BSS_MODE_INFRA) {
5057 ret = MLAN_STATUS_SUCCESS;
5058 goto done;
5059 }
5060
5061 /* Allocate an IOCTL request buffer */
5062 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
5063 if (req == NULL) {
5064 ret = MLAN_STATUS_FAILURE;
5065 goto done;
5066 }
5067
5068 /* Get current channel */
5069 bss = (mlan_ds_bss *)req->pbuf;
5070 bss->sub_command = MLAN_OID_IBSS_CHANNEL;
5071 req->req_id = MLAN_IOCTL_BSS;
5072 req->action = MLAN_ACT_GET;
5073
5074 /* Send IOCTL request to MLAN */
5075 ret = woal_request_ioctl(priv, req, wait_option);
5076 if (ret != MLAN_STATUS_SUCCESS)
5077 goto done;
5078
5079 if (bss->param.bss_chan.channel == (unsigned int)channel) {
5080 ret = MLAN_STATUS_SUCCESS;
5081 goto done;
5082 }
5083 PRINTM(MINFO, "Updating Channel from %d to %d\n",
5084 (int)bss->param.bss_chan.channel, channel);
5085
5086 if (bss_info.media_connected != MTRUE) {
5087 ret = MLAN_STATUS_SUCCESS;
5088 goto done;
5089 }
5090
5091 /* Do disonnect*/
5092 bss->sub_command = MLAN_OID_BSS_STOP;
5093 memset((t_u8 *)&bss->param.bssid, 0, ETH_ALEN);
5094
5095 /* Send IOCTL request to MLAN */
5096 ret = woal_request_ioctl(priv, req, wait_option);
5097 if (ret != MLAN_STATUS_SUCCESS)
5098 goto done;
5099
5100 /* Do specific SSID scanning */
5101 if (MLAN_STATUS_SUCCESS !=
5102 woal_request_scan(priv, wait_option, &bss_info.ssid)) {
5103 ret = MLAN_STATUS_FAILURE;
5104 goto done;
5105 }
5106 /* Start/Join Adhoc network */
5107 bss->sub_command = MLAN_OID_BSS_START;
5108 memset(&bss->param.ssid_bssid, 0, sizeof(mlan_ssid_bssid));
5109 moal_memcpy_ext(priv->phandle, &bss->param.ssid_bssid.ssid,
5110 &bss_info.ssid, sizeof(mlan_802_11_ssid),
5111 sizeof(mlan_802_11_ssid));
5112
5113 /* Send IOCTL request to MLAN */
5114 ret = woal_request_ioctl(priv, req, wait_option);
5115
5116 done:
5117 if (ret != MLAN_STATUS_PENDING)
5118 kfree(req);
5119 LEAVE();
5120 return ret;
5121 }
5122
5123 /**
5124 * @brief Find the best network to associate
5125 *
5126 * @param priv A pointer to moal_private structure
5127 * @param wait_option Wait option
5128 * @param ssid_bssid A pointer to mlan_ssid_bssid structure
5129 *
5130 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5131 * success, otherwise fail
5132 */
woal_find_best_network(moal_private * priv,t_u8 wait_option,mlan_ssid_bssid * ssid_bssid)5133 mlan_status woal_find_best_network(moal_private *priv, t_u8 wait_option,
5134 mlan_ssid_bssid *ssid_bssid)
5135 {
5136 mlan_ioctl_req *req = NULL;
5137 mlan_ds_bss *bss = NULL;
5138 mlan_status ret = MLAN_STATUS_SUCCESS;
5139
5140 ENTER();
5141
5142 if (!ssid_bssid) {
5143 ret = MLAN_STATUS_FAILURE;
5144 goto done;
5145 }
5146
5147 /* Allocate an IOCTL request buffer */
5148 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
5149 if (req == NULL) {
5150 ret = MLAN_STATUS_FAILURE;
5151 goto done;
5152 }
5153
5154 /* Fill request buffer */
5155 bss = (mlan_ds_bss *)req->pbuf;
5156 req->req_id = MLAN_IOCTL_BSS;
5157 req->action = MLAN_ACT_GET;
5158 bss->sub_command = MLAN_OID_BSS_FIND_BSS;
5159
5160 moal_memcpy_ext(priv->phandle, &bss->param.ssid_bssid, ssid_bssid,
5161 sizeof(mlan_ssid_bssid), sizeof(mlan_ssid_bssid));
5162
5163 /* Send IOCTL request to MLAN */
5164 ret = woal_request_ioctl(priv, req, wait_option);
5165 if (ret == MLAN_STATUS_SUCCESS) {
5166 moal_memcpy_ext(priv->phandle, ssid_bssid,
5167 &bss->param.ssid_bssid, sizeof(mlan_ssid_bssid),
5168 sizeof(mlan_ssid_bssid));
5169 PRINTM(MINFO, "Find network: ssid=%s, " MACSTR ", idx=%d\n",
5170 ssid_bssid->ssid.ssid,
5171 MAC2STR((t_u8 *)&ssid_bssid->bssid),
5172 (int)ssid_bssid->idx);
5173 }
5174
5175 done:
5176 if (ret != MLAN_STATUS_PENDING)
5177 kfree(req);
5178 LEAVE();
5179 return ret;
5180 }
5181
5182 /**
5183 * @brief Find the best network to associate
5184 *
5185 * @param priv A pointer to moal_private structure
5186 * @param bssid A pointer to bssid
5187 *
5188 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5189 * success, otherwise fail
5190 */
woal_find_bssid(moal_private * priv,mlan_802_11_mac_addr bssid)5191 mlan_status woal_find_bssid(moal_private *priv, mlan_802_11_mac_addr bssid)
5192 {
5193 mlan_ioctl_req *req = NULL;
5194 mlan_ds_bss *bss = NULL;
5195 mlan_status ret = MLAN_STATUS_SUCCESS;
5196
5197 ENTER();
5198 /* Allocate an IOCTL request buffer */
5199 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
5200 if (req == NULL) {
5201 ret = MLAN_STATUS_FAILURE;
5202 goto done;
5203 }
5204
5205 /* Fill request buffer */
5206 bss = (mlan_ds_bss *)req->pbuf;
5207 req->req_id = MLAN_IOCTL_BSS;
5208 req->action = MLAN_ACT_GET;
5209 bss->sub_command = MLAN_OID_BSS_FIND_BSSID;
5210
5211 moal_memcpy_ext(priv->phandle, &bss->param.bssid, bssid,
5212 sizeof(mlan_802_11_mac_addr),
5213 sizeof(mlan_802_11_mac_addr));
5214
5215 /* Send IOCTL request to MLAN */
5216 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5217 done:
5218 if (ret != MLAN_STATUS_PENDING)
5219 kfree(req);
5220 LEAVE();
5221 return ret;
5222 }
5223
5224 /**
5225 * @brief Check if AP channel is valid for STA Region
5226 *
5227 * @param priv A pointer to moal_private structure
5228 * @param wait_option Wait option
5229 * @param ssid_bssid A pointer to mlan_ssid_bssid structure
5230 *
5231 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
5232 * otherwise fail
5233 */
woal_11d_check_ap_channel(moal_private * priv,t_u8 wait_option,mlan_ssid_bssid * ssid_bssid)5234 mlan_status woal_11d_check_ap_channel(moal_private *priv, t_u8 wait_option,
5235 mlan_ssid_bssid *ssid_bssid)
5236 {
5237 mlan_ioctl_req *req = NULL;
5238 mlan_ds_bss *bss = NULL;
5239 mlan_status ret = MLAN_STATUS_SUCCESS;
5240
5241 ENTER();
5242
5243 if (!ssid_bssid) {
5244 ret = MLAN_STATUS_FAILURE;
5245 goto done;
5246 }
5247
5248 /* Allocate an IOCTL request buffer */
5249 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
5250 if (req == NULL) {
5251 ret = MLAN_STATUS_FAILURE;
5252 goto done;
5253 }
5254
5255 /* Fill request buffer */
5256 bss = (mlan_ds_bss *)req->pbuf;
5257 req->req_id = MLAN_IOCTL_BSS;
5258 req->action = MLAN_ACT_GET;
5259 bss->sub_command = MLAN_OID_BSS_11D_CHECK_CHANNEL;
5260
5261 moal_memcpy_ext(priv->phandle, &bss->param.ssid_bssid, ssid_bssid,
5262 sizeof(mlan_ssid_bssid), sizeof(mlan_ssid_bssid));
5263
5264 PRINTM(MINFO, "ssid=%s, " MACSTR ", idx=%d\n", ssid_bssid->ssid.ssid,
5265 MAC2STR((t_u8 *)&ssid_bssid->bssid), (int)ssid_bssid->idx);
5266
5267 /* Send IOCTL request to MLAN */
5268 ret = woal_request_ioctl(priv, req, wait_option);
5269
5270 done:
5271 if (ret != MLAN_STATUS_PENDING)
5272 kfree(req);
5273 LEAVE();
5274 return ret;
5275 }
5276
5277 /**
5278 * @brief Get authentication mode
5279 *
5280 * @param priv A pointer to moal_private structure
5281 * @param wait_option Wait option
5282 * @param auth_mode A pointer to authentication mode
5283 *
5284 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5285 * success, otherwise fail
5286 */
woal_get_auth_mode(moal_private * priv,t_u8 wait_option,t_u32 * auth_mode)5287 mlan_status woal_get_auth_mode(moal_private *priv, t_u8 wait_option,
5288 t_u32 *auth_mode)
5289 {
5290 mlan_ioctl_req *req = NULL;
5291 mlan_ds_sec_cfg *sec = NULL;
5292 mlan_status status = MLAN_STATUS_SUCCESS;
5293 ENTER();
5294
5295 /* Allocate an IOCTL request buffer */
5296 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
5297 if (req == NULL) {
5298 status = MLAN_STATUS_FAILURE;
5299 goto done;
5300 }
5301
5302 /* Fill request buffer */
5303 sec = (mlan_ds_sec_cfg *)req->pbuf;
5304 sec->sub_command = MLAN_OID_SEC_CFG_AUTH_MODE;
5305 req->req_id = MLAN_IOCTL_SEC_CFG;
5306 req->action = MLAN_ACT_GET;
5307
5308 /* Send IOCTL request to MLAN */
5309 status = woal_request_ioctl(priv, req, wait_option);
5310 if (status == MLAN_STATUS_SUCCESS && auth_mode)
5311 *auth_mode = sec->param.auth_mode;
5312 done:
5313 if (status != MLAN_STATUS_PENDING)
5314 kfree(req);
5315 LEAVE();
5316 return status;
5317 }
5318
5319 /**
5320 * @brief Get encrypt mode
5321 *
5322 * @param priv A pointer to moal_private structure
5323 * @param wait_option Wait option
5324 * @param encrypt_mode A pointer to encrypt mode
5325 *
5326 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5327 * success, otherwise fail
5328 */
woal_get_encrypt_mode(moal_private * priv,t_u8 wait_option,t_u32 * encrypt_mode)5329 mlan_status woal_get_encrypt_mode(moal_private *priv, t_u8 wait_option,
5330 t_u32 *encrypt_mode)
5331 {
5332 mlan_ioctl_req *req = NULL;
5333 mlan_ds_sec_cfg *sec = NULL;
5334 mlan_status status = MLAN_STATUS_SUCCESS;
5335
5336 ENTER();
5337
5338 /* Allocate an IOCTL request buffer */
5339 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
5340 if (req == NULL) {
5341 status = MLAN_STATUS_FAILURE;
5342 goto done;
5343 }
5344
5345 /* Fill request buffer */
5346 sec = (mlan_ds_sec_cfg *)req->pbuf;
5347 sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_MODE;
5348 req->req_id = MLAN_IOCTL_SEC_CFG;
5349 req->action = MLAN_ACT_GET;
5350
5351 /* Send IOCTL request to MLAN */
5352 status = woal_request_ioctl(priv, req, wait_option);
5353 if (status == MLAN_STATUS_SUCCESS && encrypt_mode)
5354 *encrypt_mode = sec->param.encrypt_mode;
5355 done:
5356 if (status != MLAN_STATUS_PENDING)
5357 kfree(req);
5358 LEAVE();
5359 return status;
5360 }
5361
5362 /**
5363 * @brief Get WPA enable
5364 *
5365 * @param priv A pointer to moal_private structure
5366 * @param wait_option Wait option
5367 * @param enable A pointer to wpa enable status
5368 *
5369 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5370 * success, otherwise fail
5371 */
woal_get_wpa_enable(moal_private * priv,t_u8 wait_option,t_u32 * enable)5372 mlan_status woal_get_wpa_enable(moal_private *priv, t_u8 wait_option,
5373 t_u32 *enable)
5374 {
5375 mlan_ioctl_req *req = NULL;
5376 mlan_ds_sec_cfg *sec = NULL;
5377 mlan_status status = MLAN_STATUS_SUCCESS;
5378
5379 ENTER();
5380
5381 /* Allocate an IOCTL request buffer */
5382 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
5383 if (req == NULL) {
5384 status = MLAN_STATUS_FAILURE;
5385 goto done;
5386 }
5387
5388 /* Fill request buffer */
5389 sec = (mlan_ds_sec_cfg *)req->pbuf;
5390 sec->sub_command = MLAN_OID_SEC_CFG_WPA_ENABLED;
5391 req->req_id = MLAN_IOCTL_SEC_CFG;
5392 req->action = MLAN_ACT_GET;
5393
5394 /* Send IOCTL request to MLAN */
5395 status = woal_request_ioctl(priv, req, wait_option);
5396 if (status == MLAN_STATUS_SUCCESS && enable)
5397 *enable = sec->param.wpa_enabled;
5398 done:
5399 if (status != MLAN_STATUS_PENDING)
5400 kfree(req);
5401 LEAVE();
5402 return status;
5403 }
5404
5405 /**
5406 * @brief Set authentication mode
5407 *
5408 * @param priv A pointer to moal_private structure
5409 * @param wait_option Wait option
5410 * @param auth_mode Authentication mode
5411 *
5412 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5413 * success, otherwise fail
5414 */
woal_set_auth_mode(moal_private * priv,t_u8 wait_option,t_u32 auth_mode)5415 mlan_status woal_set_auth_mode(moal_private *priv, t_u8 wait_option,
5416 t_u32 auth_mode)
5417 {
5418 mlan_ioctl_req *req = NULL;
5419 mlan_ds_sec_cfg *sec = NULL;
5420 mlan_status status = MLAN_STATUS_SUCCESS;
5421 ENTER();
5422
5423 /* Allocate an IOCTL request buffer */
5424 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
5425 if (req == NULL) {
5426 status = MLAN_STATUS_FAILURE;
5427 goto done;
5428 }
5429
5430 /* Fill request buffer */
5431 sec = (mlan_ds_sec_cfg *)req->pbuf;
5432 sec->sub_command = MLAN_OID_SEC_CFG_AUTH_MODE;
5433 req->req_id = MLAN_IOCTL_SEC_CFG;
5434 req->action = MLAN_ACT_SET;
5435 sec->param.auth_mode = auth_mode;
5436
5437 /* Send IOCTL request to MLAN */
5438 status = woal_request_ioctl(priv, req, wait_option);
5439 done:
5440 if (status != MLAN_STATUS_PENDING)
5441 kfree(req);
5442 LEAVE();
5443 return status;
5444 }
5445
5446 /**
5447 * @brief Set encrypt mode
5448 *
5449 * @param priv A pointer to moal_private structure
5450 * @param wait_option Wait option
5451 * @param encrypt_mode Encryption mode
5452 *
5453 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5454 * success, otherwise fail
5455 */
woal_set_encrypt_mode(moal_private * priv,t_u8 wait_option,t_u32 encrypt_mode)5456 mlan_status woal_set_encrypt_mode(moal_private *priv, t_u8 wait_option,
5457 t_u32 encrypt_mode)
5458 {
5459 mlan_ioctl_req *req = NULL;
5460 mlan_ds_sec_cfg *sec = NULL;
5461 mlan_status status = MLAN_STATUS_SUCCESS;
5462 ENTER();
5463
5464 /* Allocate an IOCTL request buffer */
5465 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
5466 if (req == NULL) {
5467 status = MLAN_STATUS_FAILURE;
5468 goto done;
5469 }
5470
5471 /* Fill request buffer */
5472 sec = (mlan_ds_sec_cfg *)req->pbuf;
5473 sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_MODE;
5474 req->req_id = MLAN_IOCTL_SEC_CFG;
5475 req->action = MLAN_ACT_SET;
5476 sec->param.encrypt_mode = encrypt_mode;
5477
5478 /* Send IOCTL request to MLAN */
5479 status = woal_request_ioctl(priv, req, wait_option);
5480 done:
5481 if (status != MLAN_STATUS_PENDING)
5482 kfree(req);
5483 LEAVE();
5484 return status;
5485 }
5486
5487 /**
5488 * @brief Set wpa enable
5489 *
5490 * @param priv A pointer to moal_private structure
5491 * @param wait_option Wait option
5492 * @param enable MTRUE or MFALSE
5493 *
5494 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5495 * success, otherwise fail
5496 */
woal_set_wpa_enable(moal_private * priv,t_u8 wait_option,t_u32 enable)5497 mlan_status woal_set_wpa_enable(moal_private *priv, t_u8 wait_option,
5498 t_u32 enable)
5499 {
5500 mlan_ioctl_req *req = NULL;
5501 mlan_ds_sec_cfg *sec = NULL;
5502 mlan_status status = MLAN_STATUS_SUCCESS;
5503 ENTER();
5504
5505 /* Allocate an IOCTL request buffer */
5506 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
5507 if (req == NULL) {
5508 status = MLAN_STATUS_FAILURE;
5509 goto done;
5510 }
5511
5512 /* Fill request buffer */
5513 sec = (mlan_ds_sec_cfg *)req->pbuf;
5514 sec->sub_command = MLAN_OID_SEC_CFG_WPA_ENABLED;
5515 req->req_id = MLAN_IOCTL_SEC_CFG;
5516 req->action = MLAN_ACT_SET;
5517 sec->param.wpa_enabled = enable;
5518
5519 /* Send IOCTL request to MLAN */
5520 status = woal_request_ioctl(priv, req, wait_option);
5521 done:
5522 if (status != MLAN_STATUS_PENDING)
5523 kfree(req);
5524 LEAVE();
5525 return status;
5526 }
5527
5528 /**
5529 * @brief enable wep key
5530 *
5531 * @param priv A pointer to moal_private structure
5532 * @param wait_option Wait option
5533 *
5534 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5535 * success, otherwise fail
5536 */
woal_enable_wep_key(moal_private * priv,t_u8 wait_option)5537 mlan_status woal_enable_wep_key(moal_private *priv, t_u8 wait_option)
5538 {
5539 mlan_ioctl_req *req = NULL;
5540 mlan_ds_sec_cfg *sec = NULL;
5541 mlan_status status = MLAN_STATUS_SUCCESS;
5542 ENTER();
5543
5544 /* Allocate an IOCTL request buffer */
5545 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
5546 if (req == NULL) {
5547 status = MLAN_STATUS_FAILURE;
5548 goto done;
5549 }
5550
5551 /* Fill request buffer */
5552 sec = (mlan_ds_sec_cfg *)req->pbuf;
5553 sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
5554 req->req_id = MLAN_IOCTL_SEC_CFG;
5555 req->action = MLAN_ACT_SET;
5556 sec->param.encrypt_key.key_disable = MFALSE;
5557 sec->param.encrypt_key.key_index = MLAN_KEY_INDEX_DEFAULT;
5558 sec->param.encrypt_key.is_current_wep_key = MTRUE;
5559
5560 /* Send IOCTL request to MLAN */
5561 status = woal_request_ioctl(priv, req, wait_option);
5562 done:
5563 if (status != MLAN_STATUS_PENDING)
5564 kfree(req);
5565 LEAVE();
5566 return status;
5567 }
5568
5569 /**
5570 * @brief Request user scan
5571 *
5572 * @param priv A pointer to moal_private structure
5573 * @param wait_option Wait option
5574 * @param scan_cfg A pointer to wlan_user_scan_config structure
5575 *
5576 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5577 */
woal_request_userscan(moal_private * priv,t_u8 wait_option,wlan_user_scan_cfg * scan_cfg)5578 mlan_status woal_request_userscan(moal_private *priv, t_u8 wait_option,
5579 wlan_user_scan_cfg *scan_cfg)
5580 {
5581 mlan_status ret = MLAN_STATUS_SUCCESS;
5582 mlan_ioctl_req *ioctl_req = NULL;
5583 mlan_ds_scan *scan = NULL;
5584 mlan_status status = MLAN_STATUS_SUCCESS;
5585 moal_handle *handle = priv->phandle;
5586 ENTER();
5587
5588 if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->async_sem)) {
5589 PRINTM(MERROR, "Acquire semaphore error, request_scan\n");
5590 LEAVE();
5591 return MLAN_STATUS_FAILURE;
5592 }
5593 handle->scan_pending_on_block = MTRUE;
5594 handle->scan_priv = priv;
5595
5596 /* Allocate an IOCTL request buffer */
5597 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan) +
5598 sizeof(wlan_user_scan_cfg));
5599 if (ioctl_req == NULL) {
5600 ret = MLAN_STATUS_FAILURE;
5601 goto done;
5602 }
5603
5604 scan = (mlan_ds_scan *)ioctl_req->pbuf;
5605 scan->sub_command = MLAN_OID_SCAN_USER_CONFIG;
5606 ioctl_req->req_id = MLAN_IOCTL_SCAN;
5607 ioctl_req->action = MLAN_ACT_SET;
5608 moal_memcpy_ext(handle, scan->param.user_scan.scan_cfg_buf, scan_cfg,
5609 sizeof(wlan_user_scan_cfg), sizeof(wlan_user_scan_cfg));
5610 /* Send IOCTL request to MLAN */
5611 status = woal_request_ioctl(priv, ioctl_req, wait_option);
5612 if (status == MLAN_STATUS_FAILURE) {
5613 ret = MLAN_STATUS_FAILURE;
5614 goto done;
5615 }
5616
5617 done:
5618 if (status != MLAN_STATUS_PENDING)
5619 kfree(ioctl_req);
5620 else if (wait_option != MOAL_NO_WAIT) {
5621 PRINTM(MMSG, "scan interrupted by Signal, Cancel it...");
5622 woal_cancel_scan(priv, MOAL_IOCTL_WAIT_TIMEOUT);
5623 }
5624 if (ret == MLAN_STATUS_FAILURE) {
5625 handle->scan_pending_on_block = MFALSE;
5626 handle->scan_priv = NULL;
5627 MOAL_REL_SEMAPHORE(&handle->async_sem);
5628 }
5629 LEAVE();
5630 return ret;
5631 }
5632
5633 /**
5634 * @brief woal_get_scan_config
5635 *
5636 * @param priv A pointer to moal_private structure
5637 * @param scan_cfg A pointer to scan_cfg structure
5638 *
5639 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5640 */
woal_get_scan_config(moal_private * priv,mlan_scan_cfg * scan_cfg)5641 mlan_status woal_get_scan_config(moal_private *priv, mlan_scan_cfg *scan_cfg)
5642 {
5643 mlan_status ret = MLAN_STATUS_SUCCESS;
5644 mlan_ds_scan *scan = NULL;
5645 mlan_ioctl_req *req = NULL;
5646
5647 ENTER();
5648
5649 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
5650 if (req == NULL) {
5651 ret = MLAN_STATUS_FAILURE;
5652 goto done;
5653 }
5654 scan = (mlan_ds_scan *)req->pbuf;
5655 scan->sub_command = MLAN_OID_SCAN_CONFIG;
5656 req->req_id = MLAN_IOCTL_SCAN;
5657 req->action = MLAN_ACT_GET;
5658 memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
5659 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5660 if (ret == MLAN_STATUS_SUCCESS && scan_cfg)
5661 moal_memcpy_ext(priv->phandle, scan_cfg, &scan->param.scan_cfg,
5662 sizeof(mlan_scan_cfg), sizeof(mlan_scan_cfg));
5663
5664 done:
5665 if (ret != MLAN_STATUS_PENDING)
5666 kfree(req);
5667 LEAVE();
5668 return ret;
5669 }
5670
5671 /**
5672 * @brief set scan time
5673 *
5674 * @param priv A pointer to moal_private structure
5675 * @param active_scan_time Active scan time
5676 * @param passive_scan_time Passive scan time
5677 * @param specific_scan_time Specific scan time
5678 *
5679 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5680 */
woal_set_scan_time(moal_private * priv,t_u16 active_scan_time,t_u16 passive_scan_time,t_u16 specific_scan_time)5681 mlan_status woal_set_scan_time(moal_private *priv, t_u16 active_scan_time,
5682 t_u16 passive_scan_time,
5683 t_u16 specific_scan_time)
5684 {
5685 mlan_status ret = MLAN_STATUS_SUCCESS;
5686 mlan_ds_scan *scan = NULL;
5687 mlan_ioctl_req *req = NULL;
5688 mlan_scan_cfg scan_cfg;
5689
5690 ENTER();
5691
5692 memset(&scan_cfg, 0, sizeof(scan_cfg));
5693 if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) {
5694 ret = MLAN_STATUS_FAILURE;
5695 goto done;
5696 }
5697 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
5698 if (req == NULL) {
5699 ret = MLAN_STATUS_FAILURE;
5700 goto done;
5701 }
5702 scan = (mlan_ds_scan *)req->pbuf;
5703 scan->sub_command = MLAN_OID_SCAN_CONFIG;
5704 req->req_id = MLAN_IOCTL_SCAN;
5705 req->action = MLAN_ACT_SET;
5706 memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
5707 scan_cfg.scan_time.active_scan_time = active_scan_time;
5708 scan_cfg.scan_time.specific_scan_time = specific_scan_time;
5709 scan_cfg.scan_time.passive_scan_time = passive_scan_time;
5710 PRINTM(MIOCTL, "Set specific=%d, active=%d, passive=%d\n",
5711 (int)active_scan_time, (int)passive_scan_time,
5712 (int)specific_scan_time);
5713 moal_memcpy_ext(priv->phandle, &scan->param.scan_cfg, &scan_cfg,
5714 sizeof(mlan_scan_cfg), sizeof(mlan_scan_cfg));
5715 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5716
5717 done:
5718 if (ret != MLAN_STATUS_PENDING)
5719 kfree(req);
5720 LEAVE();
5721 return ret;
5722 }
5723
5724 /**
5725 * @brief request scan
5726 *
5727 * @param priv A pointer to moal_private structure
5728 * @param scan_cfg A pointer to wlan_user_scan_cfg structure
5729 *
5730 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5731 */
woal_do_scan(moal_private * priv,wlan_user_scan_cfg * scan_cfg)5732 mlan_status woal_do_scan(moal_private *priv, wlan_user_scan_cfg *scan_cfg)
5733 {
5734 mlan_status ret = MLAN_STATUS_SUCCESS;
5735 moal_handle *handle = priv->phandle;
5736
5737 ENTER();
5738 if (handle->scan_pending_on_block == MTRUE) {
5739 PRINTM(MINFO, "scan already in processing...\n");
5740 LEAVE();
5741 return ret;
5742 }
5743 #ifdef REASSOCIATION
5744 if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->reassoc_sem)) {
5745 PRINTM(MERROR, "Acquire semaphore error, woal_do_combo_scan\n");
5746 LEAVE();
5747 return -EBUSY;
5748 }
5749 #endif /* REASSOCIATION */
5750 priv->report_scan_result = MTRUE;
5751
5752 if (!scan_cfg)
5753 ret = woal_request_scan(priv, MOAL_NO_WAIT, NULL);
5754 else
5755 ret = woal_request_userscan(priv, MOAL_NO_WAIT, scan_cfg);
5756
5757 #ifdef REASSOCIATION
5758 MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
5759 #endif
5760 LEAVE();
5761 return ret;
5762 }
5763
5764 /**
5765 * @brief Cancel pending scan
5766 *
5767 * @param priv A pointer to moal_private structure
5768 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5769 */
woal_cancel_scan(moal_private * priv,t_u8 wait_option)5770 mlan_status woal_cancel_scan(moal_private *priv, t_u8 wait_option)
5771 {
5772 mlan_ioctl_req *req = NULL;
5773 mlan_status ret = MLAN_STATUS_SUCCESS;
5774 moal_handle *handle = priv->phandle;
5775 moal_private *scan_priv = handle->scan_priv;
5776 #ifdef STA_CFG80211
5777 unsigned long flags;
5778 #endif
5779 /* If scan is in process, cancel the scan command */
5780 if (!handle->scan_pending_on_block || !scan_priv)
5781 return ret;
5782 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
5783 if (req == NULL) {
5784 ret = MLAN_STATUS_FAILURE;
5785 goto done;
5786 }
5787 req->req_id = MLAN_IOCTL_SCAN;
5788 req->action = MLAN_ACT_SET;
5789 ((mlan_ds_scan *)req->pbuf)->sub_command = MLAN_OID_SCAN_CANCEL;
5790 ret = woal_request_ioctl(scan_priv, req, wait_option);
5791 handle->scan_pending_on_block = MFALSE;
5792 MOAL_REL_SEMAPHORE(&handle->async_sem);
5793 #ifdef STA_CFG80211
5794 spin_lock_irqsave(&handle->scan_req_lock, flags);
5795 if (IS_STA_CFG80211(handle->params.cfg80211_wext) &&
5796 handle->scan_request) {
5797 cancel_delayed_work(&handle->scan_timeout_work);
5798 /** some supplicant can not handle SCAN abort event */
5799 if (scan_priv->bss_type == MLAN_BSS_TYPE_STA)
5800 woal_cfg80211_scan_done(handle->scan_request, MTRUE);
5801 else
5802 woal_cfg80211_scan_done(handle->scan_request, MFALSE);
5803 handle->scan_request = NULL;
5804 }
5805 spin_unlock_irqrestore(&handle->scan_req_lock, flags);
5806 #endif
5807 /* add 10ms delay, incase firmware delay 0x7f event after scan cancel
5808 * command response */
5809 woal_sched_timeout(10);
5810 handle->scan_priv = NULL;
5811 done:
5812 if (ret != MLAN_STATUS_PENDING)
5813 kfree(req);
5814 return ret;
5815 }
5816
5817 /**
5818 * @brief find ssid in scan_table
5819 *
5820 * @param priv A pointer to moal_private
5821 * @param ssid_bssid A pointer to mlan_ssid_bssid structure
5822 *
5823 *
5824 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
5825 */
woal_find_essid(moal_private * priv,mlan_ssid_bssid * ssid_bssid,t_u8 wait_option)5826 int woal_find_essid(moal_private *priv, mlan_ssid_bssid *ssid_bssid,
5827 t_u8 wait_option)
5828 {
5829 int ret = 0;
5830 mlan_scan_resp scan_resp;
5831 wifi_timeval t;
5832 ENTER();
5833
5834 if (MLAN_STATUS_SUCCESS !=
5835 woal_get_scan_table(priv, wait_option, &scan_resp)) {
5836 LEAVE();
5837 return MLAN_STATUS_FAILURE;
5838 }
5839 #ifdef STA_CFG80211
5840 if (priv->ft_pre_connect || priv->ft_ie_len) {
5841 /** skip check the scan age out */
5842 ret = woal_find_best_network(priv, wait_option, ssid_bssid);
5843 LEAVE();
5844 return ret;
5845 }
5846 #endif
5847 woal_get_monotonic_time(&t);
5848 /** scan result timeout value */
5849 #define SCAN_RESULT_AGEOUT 10
5850 if (t.time_sec > (scan_resp.age_in_secs + SCAN_RESULT_AGEOUT)) {
5851 LEAVE();
5852 return MLAN_STATUS_FAILURE;
5853 }
5854 ret = woal_find_best_network(priv, wait_option, ssid_bssid);
5855 LEAVE();
5856 return ret;
5857 }
5858
5859 /**
5860 * @brief auto reconnection configure
5861 *
5862 * @param priv Pointer to moal_private structure
5863 * @param cfg_mode configure mode
5864 * @param roam_offload_cfg Pointer to woal_roam_offload_cfg structure
5865 *
5866 * @return 0-success, negative for failure.
5867 */
woal_config_fw_roaming(moal_private * priv,t_u8 cfg_mode,woal_roam_offload_cfg * roam_offload_cfg)5868 int woal_config_fw_roaming(moal_private *priv, t_u8 cfg_mode,
5869 woal_roam_offload_cfg *roam_offload_cfg)
5870 {
5871 mlan_ioctl_req *ioctl_req = NULL;
5872 mlan_ds_misc_cfg *misc = NULL;
5873 mlan_ds_misc_roam_offload *roam = NULL;
5874 mlan_status status = MLAN_STATUS_SUCCESS;
5875 int ret = 0;
5876
5877 ENTER();
5878
5879 if (!priv || !priv->phandle) {
5880 PRINTM(MERROR, "priv or handle is null\n");
5881 ret = -EFAULT;
5882 goto done;
5883 }
5884
5885 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
5886 if (ioctl_req == NULL) {
5887 ret = -ENOMEM;
5888 goto done;
5889 }
5890
5891 misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
5892 misc->sub_command = MLAN_OID_MISC_ROAM_OFFLOAD;
5893 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
5894
5895 roam = (mlan_ds_misc_roam_offload *)&misc->param.roam_offload;
5896 roam->aplist.ap_num = 0;
5897 ioctl_req->action = MLAN_ACT_SET;
5898 roam->enable = priv->phandle->fw_roam_enable;
5899 roam->config_mode = cfg_mode;
5900
5901 if ((roam->config_mode == ROAM_OFFLOAD_ENABLE) && roam_offload_cfg) {
5902 roam->userset_passphrase = roam_offload_cfg->userset_passphrase;
5903 if (roam->userset_passphrase)
5904 roam->enable = 0;
5905 }
5906 if (roam->config_mode == ROAM_OFFLOAD_PARAM_CFG) {
5907 moal_memcpy_ext(priv->phandle, (t_u8 *)&roam->bssid_reconnect,
5908 (t_u8 *)&roam_offload_cfg->bssid,
5909 MLAN_MAC_ADDR_LENGTH,
5910 sizeof(roam->bssid_reconnect));
5911 if (roam_offload_cfg->ssid_list.ssid_num) {
5912 moal_memcpy_ext(priv->phandle, (t_u8 *)&roam->ssid_list,
5913 (t_u8 *)&roam_offload_cfg->ssid_list,
5914 sizeof(mlan_ds_misc_ssid_list),
5915 sizeof(mlan_ds_misc_ssid_list));
5916 }
5917 if (roam_offload_cfg->black_list.ap_num) {
5918 moal_memcpy_ext(
5919 priv->phandle, (t_u8 *)&roam->black_list,
5920 (t_u8 *)&roam_offload_cfg->black_list,
5921 sizeof(mlan_ds_misc_roam_offload_aplist),
5922 sizeof(mlan_ds_misc_roam_offload_aplist));
5923 }
5924 roam->trigger_condition = roam_offload_cfg->trigger_condition;
5925 roam->retry_count = roam_offload_cfg->retry_count;
5926 if (roam_offload_cfg->rssi_param_set_flag) {
5927 roam->para_rssi.set_flag = 1;
5928 roam->para_rssi.max_rssi = roam_offload_cfg->max_rssi;
5929 roam->para_rssi.min_rssi = roam_offload_cfg->min_rssi;
5930 roam->para_rssi.step_rssi = roam_offload_cfg->step_rssi;
5931 }
5932 if (roam_offload_cfg->band_rssi_flag) {
5933 roam->band_rssi_flag = roam_offload_cfg->band_rssi_flag;
5934 moal_memcpy_ext(priv->phandle, (t_u8 *)&roam->band_rssi,
5935 (t_u8 *)&roam_offload_cfg->band_rssi,
5936 sizeof(mlan_ds_misc_band_rssi),
5937 sizeof(mlan_ds_misc_band_rssi));
5938 }
5939 if (roam_offload_cfg->bgscan_set_flag) {
5940 roam->bgscan_set_flag =
5941 roam_offload_cfg->bgscan_set_flag;
5942 moal_memcpy_ext(priv->phandle,
5943 (t_u8 *)&roam->bgscan_cfg,
5944 (t_u8 *)&roam_offload_cfg->bgscan_cfg,
5945 sizeof(mlan_ds_misc_bgscan_cfg),
5946 sizeof(mlan_ds_misc_bgscan_cfg));
5947 }
5948 if (roam_offload_cfg->ees_param_set_flag) {
5949 roam->ees_param_set_flag =
5950 roam_offload_cfg->ees_param_set_flag;
5951 moal_memcpy_ext(priv->phandle, (t_u8 *)&roam->ees_cfg,
5952 (t_u8 *)&roam_offload_cfg->ees_cfg,
5953 sizeof(mlan_ds_misc_ees_cfg),
5954 sizeof(mlan_ds_misc_ees_cfg));
5955 }
5956 roam->bcn_miss_threshold = roam_offload_cfg->bcn_miss_threshold;
5957 roam->pre_bcn_miss_threshold =
5958 roam_offload_cfg->pre_bcn_miss_threshold;
5959 roam->repeat_count = roam_offload_cfg->repeat_count;
5960 }
5961 if (roam->config_mode == ROAM_OFFLOAD_SUSPEND_CFG) {
5962 moal_memcpy_ext(priv->phandle, roam->bssid_reconnect,
5963 priv->phandle->auto_reconnect_bssid,
5964 MLAN_MAC_ADDR_LENGTH,
5965 sizeof(roam->bssid_reconnect));
5966 roam->ssid_list.ssid_num = 1;
5967 moal_memcpy_ext(
5968 priv->phandle, (t_u8 *)&roam->ssid_list.ssids[0].ssid,
5969 (t_u8 *)&priv->phandle->auto_reconnect_ssid.ssid,
5970 priv->phandle->auto_reconnect_ssid.ssid_len,
5971 MLAN_MAX_SSID_LENGTH);
5972 roam->retry_count = priv->phandle->auto_reconnect_retry_count;
5973 }
5974
5975 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
5976 if (status != MLAN_STATUS_SUCCESS) {
5977 ret = -EFAULT;
5978 goto done;
5979 }
5980
5981 done:
5982 if (status != MLAN_STATUS_PENDING)
5983 kfree(ioctl_req);
5984
5985 LEAVE();
5986 return ret;
5987 }
5988
5989 /**
5990 * @brief Request user scan
5991 *
5992 * @param priv A pointer to moal_private structure
5993 * @param wait_option Wait option
5994 * @param scan_cfg A pointer to wlan_bgscan_cfg structure
5995 *
5996 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5997 */
woal_request_bgscan(moal_private * priv,t_u8 wait_option,wlan_bgscan_cfg * scan_cfg)5998 mlan_status woal_request_bgscan(moal_private *priv, t_u8 wait_option,
5999 wlan_bgscan_cfg *scan_cfg)
6000 {
6001 mlan_status ret = MLAN_STATUS_SUCCESS;
6002 mlan_ioctl_req *ioctl_req = NULL;
6003 mlan_ds_scan *scan = NULL;
6004 mlan_status status = MLAN_STATUS_SUCCESS;
6005 ENTER();
6006
6007 /* Allocate an IOCTL request buffer */
6008 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan) +
6009 sizeof(wlan_bgscan_cfg));
6010 if (ioctl_req == NULL) {
6011 ret = MLAN_STATUS_FAILURE;
6012 goto done;
6013 }
6014
6015 scan = (mlan_ds_scan *)ioctl_req->pbuf;
6016 scan->sub_command = MLAN_OID_SCAN_BGSCAN_CONFIG;
6017 ioctl_req->req_id = MLAN_IOCTL_SCAN;
6018 ioctl_req->action = MLAN_ACT_SET;
6019 moal_memcpy_ext(priv->phandle, scan->param.user_scan.scan_cfg_buf,
6020 scan_cfg, sizeof(wlan_bgscan_cfg),
6021 sizeof(wlan_bgscan_cfg));
6022
6023 /* Send IOCTL request to MLAN */
6024 status = woal_request_ioctl(priv, ioctl_req, wait_option);
6025 if (status == MLAN_STATUS_FAILURE) {
6026 ret = MLAN_STATUS_FAILURE;
6027 goto done;
6028 }
6029 done:
6030 if (status != MLAN_STATUS_PENDING)
6031 kfree(ioctl_req);
6032 LEAVE();
6033 return ret;
6034 }
6035
6036 /**
6037 * @brief set bgscan config
6038 *
6039 * @param priv A pointer to moal_private structure
6040 * @param buf A pointer to scan command buf
6041 * @param length buf length
6042 *
6043 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6044 */
woal_set_bg_scan(moal_private * priv,char * buf,int length)6045 mlan_status woal_set_bg_scan(moal_private *priv, char *buf, int length)
6046 {
6047 t_u8 *ptr = buf + strlen("BGSCAN-CONFIG") + 1;
6048 int buf_left = length - (strlen("BGSCAN-CONFIG") + 1);
6049 int band = 0;
6050 int num_ssid = 0;
6051 int ssid_len = 0;
6052 mlan_status ret = MLAN_STATUS_FAILURE;
6053
6054 ENTER();
6055 memset(&priv->scan_cfg, 0, sizeof(priv->scan_cfg));
6056 priv->scan_cfg.report_condition =
6057 BG_SCAN_SSID_MATCH | BG_SCAN_WAIT_ALL_CHAN_DONE;
6058 while (buf_left >= 2) {
6059 switch (*ptr) {
6060 case WEXT_CSCAN_SSID_SECTION:
6061 ssid_len = *(ptr + 1);
6062 if ((buf_left < (ssid_len + 2)) ||
6063 (ssid_len > MLAN_MAX_SSID_LENGTH)) {
6064 PRINTM(MERROR,
6065 "Invalid ssid, buf_left=%d, ssid_len=%d\n",
6066 buf_left, ssid_len);
6067 buf_left = 0;
6068 break;
6069 }
6070 if (ssid_len &&
6071 (num_ssid < (MRVDRV_MAX_SSID_LIST_LENGTH - 1))) {
6072 strncpy(priv->scan_cfg.ssid_list[num_ssid].ssid,
6073 ptr + 2, ssid_len);
6074 priv->scan_cfg.ssid_list[num_ssid].max_len = 0;
6075 PRINTM(MIOCTL, "BG scan: ssid=%s\n",
6076 priv->scan_cfg.ssid_list[num_ssid].ssid);
6077 num_ssid++;
6078 }
6079 buf_left -= ssid_len + 2;
6080 ptr += ssid_len + 2;
6081 break;
6082 case WEXT_BGSCAN_RSSI_SECTION:
6083 priv->scan_cfg.report_condition =
6084 BG_SCAN_SSID_RSSI_MATCH |
6085 BG_SCAN_WAIT_ALL_CHAN_DONE;
6086 priv->scan_cfg.rssi_threshold = ptr[1];
6087 PRINTM(MIOCTL, "BG scan: rssi_threshold=%d\n",
6088 (int)priv->scan_cfg.rssi_threshold);
6089 ptr += 2;
6090 buf_left -= 2;
6091 break;
6092 case WEXT_BGSCAN_REPEAT_SECTION:
6093 priv->scan_cfg.repeat_count = (t_u16)ptr[1];
6094 PRINTM(MIOCTL, "BG scan: repeat_count=%d\n",
6095 (int)priv->scan_cfg.repeat_count);
6096 ptr += 2;
6097 buf_left -= 2;
6098 break;
6099 case WEXT_BGSCAN_INTERVAL_SECTION:
6100 if (buf_left < 3) {
6101 PRINTM(MERROR,
6102 "Invalid scan_interval, buf_left=%d\n",
6103 buf_left);
6104 buf_left = 0;
6105 break;
6106 }
6107 priv->scan_cfg.scan_interval =
6108 (ptr[2] << 8 | ptr[1]) * 1000;
6109 PRINTM(MIOCTL, "BG scan: scan_interval=%d\n",
6110 (int)priv->scan_cfg.scan_interval);
6111 ptr += 3;
6112 buf_left -= 3;
6113 break;
6114 default:
6115 buf_left = 0;
6116 break;
6117 }
6118 }
6119 /** set bgscan when ssid_num > 0 */
6120 if (num_ssid) {
6121 if (MLAN_STATUS_SUCCESS != woal_get_band(priv, &band)) {
6122 ret = MLAN_STATUS_FAILURE;
6123 goto done;
6124 }
6125 switch (band) {
6126 case WIFI_FREQUENCY_BAND_2GHZ:
6127 priv->scan_cfg.chan_list[0].radio_type =
6128 0 | BAND_SPECIFIED;
6129 break;
6130 case WIFI_FREQUENCY_BAND_5GHZ:
6131 priv->scan_cfg.chan_list[0].radio_type =
6132 1 | BAND_SPECIFIED;
6133 break;
6134 default:
6135 break;
6136 }
6137 priv->scan_cfg.bss_type = MLAN_BSS_MODE_INFRA;
6138 priv->scan_cfg.action = BG_SCAN_ACT_SET;
6139 priv->scan_cfg.enable = MTRUE;
6140 moal_memcpy_ext(priv->phandle, priv->scan_cfg.random_mac,
6141 priv->random_mac, ETH_ALEN,
6142 sizeof(priv->scan_cfg.random_mac));
6143 ret = woal_request_bgscan(priv, MOAL_IOCTL_WAIT,
6144 &priv->scan_cfg);
6145 }
6146 done:
6147 LEAVE();
6148 return ret;
6149 }
6150
6151 #ifdef STA_CFG80211
6152 /**
6153 * @brief set bgscan and new rssi_low_threshold
6154 *
6155 * @param priv A pointer to moal_private structure
6156 * @param set_rssi flag for set rssi_low_threshold
6157 *
6158 * @return N/A
6159 */
woal_config_bgscan_and_rssi(moal_private * priv,t_u8 set_rssi)6160 void woal_config_bgscan_and_rssi(moal_private *priv, t_u8 set_rssi)
6161 {
6162 char rssi_low[11];
6163 mlan_bss_info bss_info;
6164 int band = 0;
6165
6166 ENTER();
6167 if (!priv->rssi_low) {
6168 LEAVE();
6169 return;
6170 }
6171 memset(&bss_info, 0, sizeof(bss_info));
6172 woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
6173 if (!bss_info.media_connected) {
6174 PRINTM(MIOCTL, "We already lost connection\n");
6175 LEAVE();
6176 return;
6177 }
6178 memset(&priv->scan_cfg, 0, sizeof(priv->scan_cfg));
6179 strncpy(priv->scan_cfg.ssid_list[0].ssid, bss_info.ssid.ssid,
6180 bss_info.ssid.ssid_len);
6181 priv->scan_cfg.ssid_list[0].max_len = 0;
6182
6183 priv->scan_cfg.report_condition =
6184 BG_SCAN_SSID_RSSI_MATCH | BG_SCAN_WAIT_ALL_CHAN_DONE;
6185 priv->scan_cfg.rssi_threshold = priv->rssi_low - RSSI_HYSTERESIS;
6186 priv->scan_cfg.repeat_count = DEF_REPEAT_COUNT;
6187 priv->scan_cfg.scan_interval = MIN_BGSCAN_INTERVAL;
6188 if (MLAN_STATUS_SUCCESS != woal_get_band(priv, &band)) {
6189 PRINTM(MERROR, "woal get band fail\n");
6190 LEAVE();
6191 return;
6192 }
6193 switch (band) {
6194 case WIFI_FREQUENCY_BAND_2GHZ:
6195 priv->scan_cfg.chan_list[0].radio_type = 0 | BAND_SPECIFIED;
6196 break;
6197 case WIFI_FREQUENCY_BAND_5GHZ:
6198 priv->scan_cfg.chan_list[0].radio_type = 1 | BAND_SPECIFIED;
6199 break;
6200 default:
6201 break;
6202 }
6203 priv->scan_cfg.bss_type = MLAN_BSS_MODE_INFRA;
6204 priv->scan_cfg.action = BG_SCAN_ACT_SET;
6205 priv->scan_cfg.enable = MTRUE;
6206 moal_memcpy_ext(priv->phandle, priv->scan_cfg.random_mac,
6207 priv->random_mac, ETH_ALEN,
6208 sizeof(priv->scan_cfg.random_mac));
6209 if (MLAN_STATUS_FAILURE ==
6210 woal_request_bgscan(priv, MOAL_NO_WAIT, &priv->scan_cfg)) {
6211 PRINTM(MERROR, "request bgscan fail\n");
6212 LEAVE();
6213 return;
6214 }
6215 if (set_rssi &&
6216 ((priv->rssi_low + RSSI_HYSTERESIS) <= LOWEST_RSSI_THRESHOLD)) {
6217 priv->rssi_low += RSSI_HYSTERESIS;
6218 snprintf(rssi_low, sizeof(rssi_low), "%d", priv->rssi_low);
6219 if (MLAN_STATUS_FAILURE ==
6220 woal_set_rssi_low_threshold(priv, rssi_low, MOAL_NO_WAIT))
6221 PRINTM(MERROR, "set_rssi_low_threshold fail\n");
6222 }
6223 LEAVE();
6224 }
6225 #endif
6226
6227 /**
6228 * @brief stop bg scan
6229 *
6230 * @param priv A pointer to moal_private structure
6231 * @param wait_option wait option
6232 *
6233 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6234 */
woal_stop_bg_scan(moal_private * priv,t_u8 wait_option)6235 mlan_status woal_stop_bg_scan(moal_private *priv, t_u8 wait_option)
6236 {
6237 wlan_bgscan_cfg scan_cfg;
6238 mlan_status ret = MLAN_STATUS_SUCCESS;
6239 ENTER();
6240
6241 memset(&scan_cfg, 0, sizeof(scan_cfg));
6242 scan_cfg.action = BG_SCAN_ACT_SET;
6243 scan_cfg.enable = MFALSE;
6244 ret = woal_request_bgscan(priv, wait_option, &scan_cfg);
6245
6246 LEAVE();
6247 return ret;
6248 }
6249
6250 /**
6251 * @brief set bgscan config
6252 *
6253 * @param handle A pointer to moal_handle structure
6254 *
6255 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6256 */
woal_reconfig_bgscan(moal_handle * handle)6257 void woal_reconfig_bgscan(moal_handle *handle)
6258 {
6259 int i;
6260 for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
6261 if (handle->priv[i] &&
6262 (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA)) {
6263 if (handle->priv[i]->bg_scan_start &&
6264 handle->priv[i]->bg_scan_reported) {
6265 PRINTM(MIOCTL, "Reconfig BGSCAN\n");
6266 woal_request_bgscan(handle->priv[i],
6267 MOAL_NO_WAIT,
6268 &handle->priv[i]->scan_cfg);
6269 handle->priv[i]->bg_scan_reported = MFALSE;
6270 }
6271 }
6272 }
6273 }
6274
6275 /**
6276 * @brief set rssi low threshold
6277 *
6278 * @param priv A pointer to moal_private structure
6279 * @param rssi A pointer to low rssi
6280 * @param wait_option Wait option
6281 *
6282 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6283 */
woal_set_rssi_low_threshold(moal_private * priv,char * rssi,t_u8 wait_option)6284 mlan_status woal_set_rssi_low_threshold(moal_private *priv, char *rssi,
6285 t_u8 wait_option)
6286 {
6287 mlan_status ret = MLAN_STATUS_SUCCESS;
6288 mlan_ioctl_req *req = NULL;
6289 mlan_ds_misc_cfg *misc = NULL;
6290 int low_rssi = 0;
6291
6292 ENTER();
6293 if (priv->media_connected == MFALSE)
6294 goto done;
6295
6296 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
6297 if (req == NULL) {
6298 ret = MLAN_STATUS_FAILURE;
6299 goto done;
6300 }
6301 misc = (mlan_ds_misc_cfg *)req->pbuf;
6302 req->req_id = MLAN_IOCTL_MISC_CFG;
6303 misc->sub_command = MLAN_OID_MISC_SUBSCRIBE_EVENT;
6304 req->action = MLAN_ACT_SET;
6305 misc->param.subscribe_event.evt_action = SUBSCRIBE_EVT_ACT_BITWISE_SET;
6306 misc->param.subscribe_event.evt_bitmap = SUBSCRIBE_EVT_RSSI_LOW;
6307 misc->param.subscribe_event.evt_bitmap |= SUBSCRIBE_EVT_PRE_BEACON_LOST;
6308 misc->param.subscribe_event.pre_beacon_miss = DEFAULT_PRE_BEACON_MISS;
6309
6310 if (MLAN_STATUS_SUCCESS != woal_atoi(&low_rssi, rssi)) {
6311 ret = MLAN_STATUS_FAILURE;
6312 goto done;
6313 }
6314 #ifdef STA_CFG80211
6315 priv->mrvl_rssi_low = low_rssi;
6316 #endif
6317 misc->param.subscribe_event.low_rssi = low_rssi;
6318 misc->param.subscribe_event.low_rssi_freq = 0;
6319 ret = woal_request_ioctl(priv, req, wait_option);
6320 if (ret == MLAN_STATUS_FAILURE) {
6321 PRINTM(MERROR, "request set rssi_low_threshold fail!\n");
6322 goto done;
6323 }
6324 done:
6325 if (ret != MLAN_STATUS_PENDING)
6326 kfree(req);
6327 LEAVE();
6328 return ret;
6329 }
6330
6331 #if defined(STA_CFG80211)
6332 /**
6333 * @brief set rssi low threshold
6334 *
6335 * @param priv A pointer to moal_private structure
6336 * @param event_id event id.
6337 * @param wait_option wait option
6338 *
6339 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6340 */
woal_set_rssi_threshold(moal_private * priv,t_u32 event_id,t_u8 wait_option)6341 mlan_status woal_set_rssi_threshold(moal_private *priv, t_u32 event_id,
6342 t_u8 wait_option)
6343 {
6344 mlan_status ret = MLAN_STATUS_SUCCESS;
6345 mlan_ioctl_req *req = NULL;
6346 mlan_ds_misc_cfg *misc = NULL;
6347
6348 ENTER();
6349 if (priv->media_connected == MFALSE)
6350 goto done;
6351 if (priv->mrvl_rssi_low || !priv->cqm_rssi_thold)
6352 goto done;
6353 if (event_id == MLAN_EVENT_ID_FW_BCN_RSSI_LOW) {
6354 if (priv->last_rssi_low < 100)
6355 priv->last_rssi_low += priv->cqm_rssi_hyst;
6356 priv->last_rssi_high = abs(priv->cqm_rssi_high_thold);
6357 } else if (event_id == MLAN_EVENT_ID_FW_BCN_RSSI_HIGH) {
6358 priv->last_rssi_low = abs(priv->cqm_rssi_thold);
6359 if (priv->last_rssi_high > priv->cqm_rssi_hyst)
6360 priv->last_rssi_high -= priv->cqm_rssi_hyst;
6361 } else {
6362 priv->last_rssi_low = abs(priv->cqm_rssi_thold);
6363 priv->last_rssi_high = abs(priv->cqm_rssi_high_thold);
6364 }
6365
6366 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
6367 if (req == NULL) {
6368 ret = -ENOMEM;
6369 goto done;
6370 }
6371 misc = (mlan_ds_misc_cfg *)req->pbuf;
6372 req->req_id = MLAN_IOCTL_MISC_CFG;
6373 misc->sub_command = MLAN_OID_MISC_SUBSCRIBE_EVENT;
6374 req->action = MLAN_ACT_SET;
6375 if (!event_id && !priv->cqm_rssi_thold && !priv->cqm_rssi_hyst)
6376 misc->param.subscribe_event.evt_action =
6377 SUBSCRIBE_EVT_ACT_BITWISE_CLR;
6378 else
6379 misc->param.subscribe_event.evt_action =
6380 SUBSCRIBE_EVT_ACT_BITWISE_SET;
6381 misc->param.subscribe_event.evt_bitmap =
6382 SUBSCRIBE_EVT_RSSI_LOW | SUBSCRIBE_EVT_RSSI_HIGH;
6383 misc->param.subscribe_event.low_rssi_freq = 0;
6384 misc->param.subscribe_event.low_rssi = priv->last_rssi_low;
6385 misc->param.subscribe_event.high_rssi_freq = 0;
6386 misc->param.subscribe_event.high_rssi = priv->last_rssi_high;
6387 PRINTM(MIOCTL, "rssi_low=%d, rssi_high=%d action=%d\n",
6388 (int)priv->last_rssi_low, (int)priv->last_rssi_high,
6389 misc->param.subscribe_event.evt_action);
6390 ret = woal_request_ioctl(priv, req, wait_option);
6391 done:
6392 if (ret != MLAN_STATUS_PENDING)
6393 kfree(req);
6394 LEAVE();
6395 return ret;
6396 }
6397 #endif
6398
6399 /**
6400 * @brief Get power mode
6401 *
6402 * @param priv A pointer to moal_private structure
6403 * @param powermode A pointer to powermode buf
6404 *
6405 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6406 */
woal_get_powermode(moal_private * priv,int * powermode)6407 mlan_status woal_get_powermode(moal_private *priv, int *powermode)
6408 {
6409 mlan_status ret = MLAN_STATUS_SUCCESS;
6410 int ps_mode;
6411
6412 ENTER();
6413
6414 if (MLAN_STATUS_SUCCESS != woal_set_get_power_mgmt(priv, MLAN_ACT_GET,
6415 &ps_mode, 0,
6416 MOAL_IOCTL_WAIT)) {
6417 ret = MLAN_STATUS_FAILURE;
6418 goto done;
6419 }
6420
6421 if (ps_mode)
6422 *powermode = MFALSE;
6423 else
6424 *powermode = MTRUE;
6425
6426 done:
6427 LEAVE();
6428 return ret;
6429 }
6430
6431 /**
6432 * @brief set scan type
6433 *
6434 * @param priv A pointer to moal_private structure
6435 * @param scan_type MLAN_SCAN_TYPE_ACTIVE/MLAN_SCAN_TYPE_PASSIVE
6436 *
6437 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6438 */
woal_set_scan_type(moal_private * priv,t_u32 scan_type)6439 mlan_status woal_set_scan_type(moal_private *priv, t_u32 scan_type)
6440 {
6441 mlan_status ret = MLAN_STATUS_SUCCESS;
6442 mlan_ds_scan *scan = NULL;
6443 mlan_ioctl_req *req = NULL;
6444 mlan_scan_cfg scan_cfg;
6445
6446 ENTER();
6447 memset(&scan_cfg, 0, sizeof(scan_cfg));
6448 if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) {
6449 ret = MLAN_STATUS_FAILURE;
6450 goto done;
6451 }
6452
6453 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
6454 if (req == NULL) {
6455 ret = MLAN_STATUS_FAILURE;
6456 goto done;
6457 }
6458 scan = (mlan_ds_scan *)req->pbuf;
6459 scan->sub_command = MLAN_OID_SCAN_CONFIG;
6460 req->req_id = MLAN_IOCTL_SCAN;
6461 req->action = MLAN_ACT_SET;
6462 memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
6463 scan_cfg.scan_type = scan_type;
6464 PRINTM(MIOCTL, "Set scan_type=%d\n", (int)scan_type);
6465 moal_memcpy_ext(priv->phandle, &scan->param.scan_cfg, &scan_cfg,
6466 sizeof(mlan_scan_cfg), sizeof(mlan_scan_cfg));
6467 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6468
6469 done:
6470 if (ret != MLAN_STATUS_PENDING)
6471 kfree(req);
6472 LEAVE();
6473 return ret;
6474 }
6475
6476 /**
6477 * @brief enable/disable ext_scan
6478 *
6479 * @param priv A pointer to moal_private structure
6480 * @param enable MTRUE -- enable, MFALSE --disable
6481 *
6482 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6483 */
woal_enable_ext_scan(moal_private * priv,t_u8 enable)6484 mlan_status woal_enable_ext_scan(moal_private *priv, t_u8 enable)
6485 {
6486 mlan_status ret = MLAN_STATUS_SUCCESS;
6487 mlan_ds_scan *scan = NULL;
6488 mlan_ioctl_req *req = NULL;
6489 mlan_scan_cfg scan_cfg;
6490
6491 ENTER();
6492 memset(&scan_cfg, 0, sizeof(scan_cfg));
6493 if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) {
6494 ret = MLAN_STATUS_FAILURE;
6495 goto done;
6496 }
6497
6498 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
6499 if (req == NULL) {
6500 ret = MLAN_STATUS_FAILURE;
6501 goto done;
6502 }
6503 scan = (mlan_ds_scan *)req->pbuf;
6504 scan->sub_command = MLAN_OID_SCAN_CONFIG;
6505 req->req_id = MLAN_IOCTL_SCAN;
6506 req->action = MLAN_ACT_SET;
6507 memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
6508 scan_cfg.ext_scan = enable;
6509 PRINTM(MIOCTL, "Set ext_scan=%d\n", (int)enable);
6510 moal_memcpy_ext(priv->phandle, &scan->param.scan_cfg, &scan_cfg,
6511 sizeof(mlan_scan_cfg), sizeof(mlan_scan_cfg));
6512 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6513
6514 done:
6515 if (ret != MLAN_STATUS_PENDING)
6516 kfree(req);
6517 LEAVE();
6518 return ret;
6519 }
6520
6521 /**
6522 * @brief set power mode
6523 *
6524 * @param priv A pointer to moal_private structure
6525 * @param powermode A pointer to powermode string.
6526 *
6527 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6528 */
woal_set_powermode(moal_private * priv,char * powermode)6529 mlan_status woal_set_powermode(moal_private *priv, char *powermode)
6530 {
6531 mlan_status ret = MLAN_STATUS_SUCCESS;
6532 int disabled;
6533
6534 ENTER();
6535
6536 if (*powermode == '1') {
6537 PRINTM(MIOCTL, "Disable power save\n");
6538 disabled = 1;
6539 } else if (*powermode == '0') {
6540 PRINTM(MIOCTL, "Enable power save\n");
6541 disabled = 0;
6542 } else {
6543 PRINTM(MERROR, "unsupported power mode\n");
6544 ret = MLAN_STATUS_FAILURE;
6545 goto done;
6546 }
6547
6548 if (MLAN_STATUS_SUCCESS != woal_set_get_power_mgmt(priv, MLAN_ACT_SET,
6549 &disabled, 0,
6550 MOAL_IOCTL_WAIT))
6551 ret = MLAN_STATUS_FAILURE;
6552
6553 done:
6554 LEAVE();
6555 return ret;
6556 }
6557
6558 /**
6559 * @brief set combo scan
6560 *
6561 * @param priv A pointer to moal_private structure
6562 * @param buf A pointer to scan command buf
6563 * @param length buf length
6564 *
6565 * @return 0 -- success, otherwise fail
6566 */
woal_set_combo_scan(moal_private * priv,char * buf,int length)6567 int woal_set_combo_scan(moal_private *priv, char *buf, int length)
6568 {
6569 int ret = 0;
6570 wlan_user_scan_cfg *scan_cfg;
6571 t_u8 *ptr = buf + WEXT_CSCAN_HEADER_SIZE;
6572 int buf_left = length - WEXT_CSCAN_HEADER_SIZE;
6573 int num_ssid = 0;
6574 int num_chan = 0;
6575 int ssid_len = 0;
6576 int i = 0;
6577 t_u16 passive_scan_time = 0;
6578 t_u16 specific_scan_time = 0;
6579
6580 ENTER();
6581
6582 scan_cfg = (wlan_user_scan_cfg *)kmalloc(sizeof(wlan_user_scan_cfg),
6583 GFP_KERNEL);
6584 if (!scan_cfg) {
6585 PRINTM(MERROR, "Malloc buffer failed\n");
6586 LEAVE();
6587 return -ENOMEM;
6588 }
6589
6590 memset(scan_cfg, 0, sizeof(wlan_user_scan_cfg));
6591 while (buf_left >= 2) {
6592 switch (*ptr) {
6593 case WEXT_CSCAN_SSID_SECTION:
6594 ssid_len = *(ptr + 1);
6595 if ((buf_left < (ssid_len + 2)) ||
6596 (ssid_len > MLAN_MAX_SSID_LENGTH)) {
6597 PRINTM(MERROR,
6598 "Invalid ssid, buf_left=%d, ssid_len=%d\n",
6599 buf_left, ssid_len);
6600 buf_left = 0;
6601 break;
6602 }
6603 if (ssid_len &&
6604 (num_ssid < (MRVDRV_MAX_SSID_LIST_LENGTH - 1))) {
6605 strncpy(scan_cfg->ssid_list[num_ssid].ssid,
6606 ptr + 2, ssid_len);
6607 scan_cfg->ssid_list[num_ssid].max_len = 0;
6608 PRINTM(MIOCTL, "Combo scan: ssid=%s\n",
6609 scan_cfg->ssid_list[num_ssid].ssid);
6610 num_ssid++;
6611 }
6612 buf_left -= ssid_len + 2;
6613 ptr += ssid_len + 2;
6614 break;
6615 case WEXT_CSCAN_CHANNEL_SECTION:
6616 num_chan = ptr[1];
6617 if ((buf_left < (num_chan + 2)) ||
6618 (num_chan > WLAN_USER_SCAN_CHAN_MAX)) {
6619 PRINTM(MERROR,
6620 "Invalid channel list, buf_left=%d, num_chan=%d\n",
6621 buf_left, num_chan);
6622 buf_left = 0;
6623 break;
6624 }
6625 for (i = 0; i < num_chan; i++) {
6626 scan_cfg->chan_list[i].chan_number = ptr[2 + i];
6627 PRINTM(MIOCTL, "Combo scan: chan=%d\n",
6628 scan_cfg->chan_list[i].chan_number);
6629 }
6630 buf_left -= 2 + num_chan;
6631 ptr += 2 + num_chan;
6632 break;
6633 case WEXT_CSCAN_PASV_DWELL_SECTION:
6634 if (buf_left < 3) {
6635 PRINTM(MERROR,
6636 "Invalid PASV_DWELL_SECTION, buf_left=%d\n",
6637 buf_left);
6638 buf_left = 0;
6639 break;
6640 }
6641 passive_scan_time = ptr[2] << 8 | ptr[1];
6642 ptr += 3;
6643 buf_left -= 3;
6644 break;
6645 case WEXT_CSCAN_HOME_DWELL_SECTION:
6646 if (buf_left < 3) {
6647 PRINTM(MERROR,
6648 "Invalid HOME_DWELL_SECTION, buf_left=%d\n",
6649 buf_left);
6650 buf_left = 0;
6651 break;
6652 }
6653 specific_scan_time = ptr[2] << 8 | ptr[1];
6654 ptr += 3;
6655 buf_left -= 3;
6656 break;
6657 default:
6658 buf_left = 0;
6659 break;
6660 }
6661 }
6662 if (passive_scan_time || specific_scan_time) {
6663 PRINTM(MIOCTL,
6664 "Set passive_scan_time=%d specific_scan_time=%d\n",
6665 passive_scan_time, specific_scan_time);
6666 if (MLAN_STATUS_FAILURE ==
6667 woal_set_scan_time(priv, 0, passive_scan_time,
6668 specific_scan_time)) {
6669 ret = -EFAULT;
6670 goto done;
6671 }
6672 }
6673 if (num_ssid || num_chan) {
6674 if (num_ssid) {
6675 /* Add broadcast scan to ssid_list */
6676 scan_cfg->ssid_list[num_ssid].max_len = 0xff;
6677 if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
6678 woal_set_scan_type(priv, MLAN_SCAN_TYPE_ACTIVE);
6679 }
6680 if (MLAN_STATUS_FAILURE == woal_do_scan(priv, scan_cfg))
6681 ret = -EFAULT;
6682 if (num_ssid && (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE))
6683 woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE);
6684 } else {
6685 /* request broadcast scan */
6686 if (MLAN_STATUS_FAILURE == woal_do_scan(priv, NULL))
6687 ret = -EFAULT;
6688 }
6689 done:
6690 kfree(scan_cfg);
6691 LEAVE();
6692 return ret;
6693 }
6694
6695 /**
6696 * @brief Get band
6697 *
6698 * @param priv A pointer to moal_private structure
6699 * @param band A pointer to band buf
6700 *
6701 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6702 */
woal_get_band(moal_private * priv,int * band)6703 mlan_status woal_get_band(moal_private *priv, int *band)
6704 {
6705 mlan_status ret = MLAN_STATUS_SUCCESS;
6706 mlan_ioctl_req *req = NULL;
6707 mlan_ds_radio_cfg *radio_cfg = NULL;
6708 int support_band = 0;
6709
6710 ENTER();
6711
6712 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
6713 if (req == NULL) {
6714 ret = MLAN_STATUS_FAILURE;
6715 goto done;
6716 }
6717 radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
6718 radio_cfg->sub_command = MLAN_OID_BAND_CFG;
6719 req->req_id = MLAN_IOCTL_RADIO_CFG;
6720 /* Get config_bands, adhoc_start_band and adhoc_channel values from MLAN
6721 */
6722 req->action = MLAN_ACT_GET;
6723 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6724 if (ret != MLAN_STATUS_SUCCESS)
6725 goto done;
6726
6727 if (radio_cfg->param.band_cfg.config_bands &
6728 (BAND_B | BAND_G | BAND_GN))
6729 support_band |= WIFI_FREQUENCY_BAND_2GHZ;
6730 if (radio_cfg->param.band_cfg.config_bands & (BAND_A | BAND_AN))
6731 support_band |= WIFI_FREQUENCY_BAND_5GHZ;
6732 *band = support_band;
6733 if (support_band == WIFI_FREQUENCY_ALL_BAND)
6734 *band = WIFI_FREQUENCY_BAND_AUTO;
6735 done:
6736 if (ret != MLAN_STATUS_PENDING)
6737 kfree(req);
6738 LEAVE();
6739 return ret;
6740 }
6741
6742 /**
6743 * @brief set band
6744 *
6745 * @param priv A pointer to moal_private structure
6746 * @param pband A pointer to band string.
6747 *
6748 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6749 */
woal_set_band(moal_private * priv,char * pband)6750 mlan_status woal_set_band(moal_private *priv, char *pband)
6751 {
6752 mlan_status ret = MLAN_STATUS_SUCCESS;
6753 int band = 0;
6754 mlan_ioctl_req *req = NULL;
6755 mlan_ds_radio_cfg *radio_cfg = NULL;
6756 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
6757 int cfg80211_wext = priv->phandle->params.cfg80211_wext;
6758 #endif
6759
6760 ENTER();
6761 if (priv->media_connected == MTRUE) {
6762 PRINTM(MERROR, "Set band is not allowed in connected state\n");
6763 ret = MLAN_STATUS_FAILURE;
6764 goto done;
6765 }
6766 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
6767 if (req == NULL) {
6768 ret = MLAN_STATUS_FAILURE;
6769 goto done;
6770 }
6771 radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
6772 radio_cfg->sub_command = MLAN_OID_BAND_CFG;
6773 req->req_id = MLAN_IOCTL_RADIO_CFG;
6774
6775 /* Get fw supported values from MLAN */
6776 req->action = MLAN_ACT_GET;
6777 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6778 if (ret != MLAN_STATUS_SUCCESS)
6779 goto done;
6780
6781 if (*pband == '0') {
6782 PRINTM(MIOCTL, "Set band to AUTO\n");
6783 band = radio_cfg->param.band_cfg.fw_bands;
6784 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
6785 if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev &&
6786 priv->wdev->wiphy) {
6787 if (radio_cfg->param.band_cfg.fw_bands & BAND_A)
6788 priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ] =
6789 &cfg80211_band_5ghz;
6790 priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ] =
6791 &cfg80211_band_2ghz;
6792 }
6793 #endif
6794 } else if (*pband == '1') {
6795 PRINTM(MIOCTL, "Set band to 5G\n");
6796 if (!(radio_cfg->param.band_cfg.fw_bands & BAND_A)) {
6797 PRINTM(MERROR, "Don't support 5G band\n");
6798 ret = MLAN_STATUS_FAILURE;
6799 goto done;
6800 }
6801 band = BAND_A;
6802 if (radio_cfg->param.band_cfg.fw_bands & BAND_AN)
6803 band |= BAND_AN;
6804 if (radio_cfg->param.band_cfg.fw_bands & BAND_AAC)
6805 band |= BAND_AAC;
6806 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
6807 if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev &&
6808 priv->wdev->wiphy) {
6809 priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ] =
6810 &cfg80211_band_5ghz;
6811 priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
6812 }
6813 #endif
6814 } else if (*pband == '2') {
6815 PRINTM(MIOCTL, "Set band to 2G\n");
6816 band = BAND_B | BAND_G;
6817 band |= BAND_GN;
6818 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
6819 if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev &&
6820 priv->wdev->wiphy) {
6821 priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
6822 priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ] =
6823 &cfg80211_band_2ghz;
6824 }
6825 #endif
6826 } else {
6827 PRINTM(MERROR, "unsupported band\n");
6828 ret = MLAN_STATUS_FAILURE;
6829 goto done;
6830 }
6831 /* Set config_bands to MLAN */
6832 req->action = MLAN_ACT_SET;
6833 memset(&radio_cfg->param.band_cfg, 0, sizeof(mlan_ds_band_cfg));
6834 radio_cfg->param.band_cfg.config_bands = band;
6835 radio_cfg->param.band_cfg.adhoc_start_band = band;
6836 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6837
6838 done:
6839 if (ret != MLAN_STATUS_PENDING)
6840 kfree(req);
6841 LEAVE();
6842 return ret;
6843 }
6844
6845 /**
6846 * @brief Add RX Filter
6847 *
6848 * @param priv A pointer to moal_private structure
6849 * @param rxfilter A pointer to rxfilter string.
6850 *
6851 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6852 */
woal_add_rxfilter(moal_private * priv,char * rxfilter)6853 mlan_status woal_add_rxfilter(moal_private *priv, char *rxfilter)
6854 {
6855 mlan_status ret = MLAN_STATUS_SUCCESS;
6856 ENTER();
6857 /* Android command:
6858 "DRIVER RXFILTER-ADD 0"
6859 "DRIVER RXFILTER-ADD 1"
6860 "DRIVER RXFILTER-ADD 3" */
6861 if (*rxfilter == '0') {
6862 PRINTM(MIOCTL, "Add IPV4 multicast filter\n");
6863 priv->rx_filter |= RX_FILTER_IPV4_MULTICAST;
6864 } else if (*rxfilter == '1') {
6865 PRINTM(MIOCTL, "Add broadcast filter\n");
6866 priv->rx_filter |= RX_FILTER_BROADCAST;
6867 } else if (*rxfilter == '2') {
6868 PRINTM(MIOCTL, "Add unicast filter\n");
6869 priv->rx_filter |= RX_FILTER_UNICAST;
6870 } else if (*rxfilter == '3') {
6871 PRINTM(MIOCTL, "Add IPV6 multicast fitler\n");
6872 priv->rx_filter |= RX_FILTER_IPV6_MULTICAST;
6873 } else {
6874 PRINTM(MERROR, "unsupported rx fitler\n");
6875 ret = MLAN_STATUS_FAILURE;
6876 goto done;
6877 }
6878 done:
6879 LEAVE();
6880 return ret;
6881 }
6882
6883 /**
6884 * @brief Remove RX Filter
6885 *
6886 * @param priv A pointer to moal_private structure
6887 * @param rxfilter A pointer to rxfilter string.
6888 *
6889 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6890 */
woal_remove_rxfilter(moal_private * priv,char * rxfilter)6891 mlan_status woal_remove_rxfilter(moal_private *priv, char *rxfilter)
6892 {
6893 mlan_status ret = MLAN_STATUS_SUCCESS;
6894 ENTER();
6895 if (*rxfilter == '0') {
6896 PRINTM(MIOCTL, "Remove IPV4 multicast filter\n");
6897 priv->rx_filter &= ~RX_FILTER_IPV4_MULTICAST;
6898 } else if (*rxfilter == '1') {
6899 PRINTM(MIOCTL, "Remove broadcast filter\n");
6900 priv->rx_filter &= ~RX_FILTER_BROADCAST;
6901 } else if (*rxfilter == '2') {
6902 PRINTM(MIOCTL, "Remove unicast filter\n");
6903 priv->rx_filter &= ~RX_FILTER_UNICAST;
6904 } else if (*rxfilter == '3') {
6905 PRINTM(MIOCTL, "Remove IPV6 multicast fitler\n");
6906 priv->rx_filter &= ~RX_FILTER_IPV6_MULTICAST;
6907 } else {
6908 PRINTM(MERROR, "unsupported rx fitler\n");
6909 ret = MLAN_STATUS_FAILURE;
6910 goto done;
6911 }
6912 done:
6913 LEAVE();
6914 return ret;
6915 }
6916
6917 /**
6918 * @brief Set/Get WMM IE QoS configuration
6919 *
6920 * @param priv A pointer to moal_private structure
6921 * @param action Action set or get
6922 * @param qos_cfg A pointer to QoS configuration structure
6923 *
6924 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6925 */
woal_priv_qos_cfg(moal_private * priv,t_u32 action,char * qos_cfg)6926 mlan_status woal_priv_qos_cfg(moal_private *priv, t_u32 action, char *qos_cfg)
6927 {
6928 mlan_status ret = MLAN_STATUS_SUCCESS;
6929 mlan_ds_wmm_cfg *cfg = NULL;
6930 mlan_ioctl_req *req = NULL;
6931 int qosinfo = 0;
6932
6933 ENTER();
6934
6935 if (qos_cfg == NULL) {
6936 PRINTM(MERROR, "QOS info buffer is null\n");
6937 return MLAN_STATUS_FAILURE;
6938 }
6939 if ((action == MLAN_ACT_SET) &&
6940 (MLAN_STATUS_SUCCESS != woal_atoi(&qosinfo, qos_cfg))) {
6941 ret = MLAN_STATUS_FAILURE;
6942 goto done;
6943 }
6944 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
6945 if (req == NULL) {
6946 ret = MLAN_STATUS_FAILURE;
6947 goto done;
6948 }
6949 cfg = (mlan_ds_wmm_cfg *)req->pbuf;
6950 cfg->sub_command = MLAN_OID_WMM_CFG_QOS;
6951 req->req_id = MLAN_IOCTL_WMM_CFG;
6952 req->action = action;
6953 if (action == MLAN_ACT_SET) {
6954 cfg->param.qos_cfg = (t_u8)qosinfo;
6955 PRINTM(MIOCTL, "set qosinfo=%d\n", qosinfo);
6956 }
6957 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6958
6959 if (action == MLAN_ACT_GET)
6960 *qos_cfg = cfg->param.qos_cfg;
6961 done:
6962 if (ret != MLAN_STATUS_PENDING)
6963 kfree(req);
6964 LEAVE();
6965 return ret;
6966 }
6967
6968 /**
6969 * @brief Set sleep period
6970 *
6971 * @param priv A pointer to moal_private structure
6972 * @param psleeppd A pointer to sleep period configuration structure
6973 *
6974 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6975 */
woal_set_sleeppd(moal_private * priv,char * psleeppd)6976 mlan_status woal_set_sleeppd(moal_private *priv, char *psleeppd)
6977 {
6978 mlan_status ret = MLAN_STATUS_SUCCESS;
6979 mlan_ds_pm_cfg *pm_cfg = NULL;
6980 mlan_ioctl_req *req = NULL;
6981 int sleeppd = 0;
6982
6983 ENTER();
6984
6985 if (MLAN_STATUS_SUCCESS != woal_atoi(&sleeppd, psleeppd)) {
6986 ret = MLAN_STATUS_FAILURE;
6987 goto done;
6988 }
6989 PRINTM(MIOCTL, "set sleeppd=%d\n", sleeppd);
6990 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
6991 if (req == NULL) {
6992 ret = MLAN_STATUS_FAILURE;
6993 goto done;
6994 }
6995 pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
6996 pm_cfg->sub_command = MLAN_OID_PM_CFG_SLEEP_PD;
6997 req->req_id = MLAN_IOCTL_PM_CFG;
6998 if ((sleeppd <= MAX_SLEEP_PERIOD && sleeppd >= MIN_SLEEP_PERIOD) ||
6999 (sleeppd == 0) || (sleeppd == SLEEP_PERIOD_RESERVED_FF)) {
7000 req->action = MLAN_ACT_SET;
7001 pm_cfg->param.sleep_period = sleeppd;
7002 } else {
7003 ret = MLAN_STATUS_FAILURE;
7004 goto done;
7005 }
7006
7007 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
7008
7009 done:
7010 if (ret != MLAN_STATUS_PENDING)
7011 kfree(req);
7012 LEAVE();
7013 return ret;
7014 }
7015
7016 /**
7017 * @brief Set scan period function
7018 *
7019 * @param priv A pointer to moal_private structure
7020 * @param buf A pointer to scan command buf
7021 * @param length buf length
7022 *
7023 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
7024 */
woal_set_scan_cfg(moal_private * priv,char * buf,int length)7025 int woal_set_scan_cfg(moal_private *priv, char *buf, int length)
7026 {
7027 mlan_status ret = MLAN_STATUS_SUCCESS;
7028 t_u8 *ptr = buf + NL80211_SCANCFG_HEADER_SIZE;
7029 int buf_left = length - NL80211_SCANCFG_HEADER_SIZE;
7030 t_u16 active_scan_time = 0;
7031 t_u16 passive_scan_time = 0;
7032 t_u16 specific_scan_time = 0;
7033
7034 ENTER();
7035 while (buf_left >= 2) {
7036 switch (*ptr) {
7037 case NL80211_SCANCFG_ACTV_DWELL_SECTION:
7038 if (buf_left < 3) {
7039 PRINTM(MERROR,
7040 "Invalid ACTV_DWELL_SECTION, buf_left=%d\n",
7041 buf_left);
7042 buf_left = 0;
7043 break;
7044 }
7045 active_scan_time = ptr[2] << 8 | ptr[1];
7046 ptr += 3;
7047 buf_left -= 3;
7048 break;
7049 case NL80211_SCANCFG_PASV_DWELL_SECTION:
7050 if (buf_left < 3) {
7051 PRINTM(MERROR,
7052 "Invalid PASV_DWELL_SECTION, buf_left=%d\n",
7053 buf_left);
7054 buf_left = 0;
7055 break;
7056 }
7057 passive_scan_time = ptr[2] << 8 | ptr[1];
7058 ptr += 3;
7059 buf_left -= 3;
7060 break;
7061 case NL80211_SCANCFG_SPCF_DWELL_SECTION:
7062 if (buf_left < 3) {
7063 PRINTM(MERROR,
7064 "Invalid SPCF_DWELL_SECTION, buf_left=%d\n",
7065 buf_left);
7066 buf_left = 0;
7067 break;
7068 }
7069 specific_scan_time = ptr[2] << 8 | ptr[1];
7070 ptr += 3;
7071 buf_left -= 3;
7072 break;
7073 default:
7074 buf_left = 0;
7075 break;
7076 }
7077 }
7078
7079 if (active_scan_time || passive_scan_time || specific_scan_time) {
7080 PRINTM(MIOCTL,
7081 "Set active_scan_time= %d passive_scan_time=%d specific_scan_time=%d\n",
7082 active_scan_time, passive_scan_time, specific_scan_time);
7083 if (MLAN_STATUS_FAILURE ==
7084 woal_set_scan_time(priv, active_scan_time,
7085 passive_scan_time, specific_scan_time)) {
7086 ret = -EFAULT;
7087 }
7088 }
7089
7090 LEAVE();
7091 return ret;
7092 }
7093
7094 /**
7095 * @brief Set Radio On/OFF
7096 *
7097 * @param priv A pointer to moal_private structure
7098 * @param option Radio Option
7099 *
7100 * @return 0 --success, otherwise fail
7101 */
woal_set_radio(moal_private * priv,t_u8 option)7102 int woal_set_radio(moal_private *priv, t_u8 option)
7103 {
7104 int ret = 0;
7105 mlan_ds_radio_cfg *radio = NULL;
7106 mlan_ioctl_req *req = NULL;
7107 mlan_status status = MLAN_STATUS_SUCCESS;
7108 ENTER();
7109 if ((option != 0) && (option != 1)) {
7110 ret = -EINVAL;
7111 goto done;
7112 }
7113 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
7114 if (req == NULL) {
7115 ret = -ENOMEM;
7116 goto done;
7117 }
7118 radio = (mlan_ds_radio_cfg *)req->pbuf;
7119 radio->sub_command = MLAN_OID_RADIO_CTRL;
7120 req->req_id = MLAN_IOCTL_RADIO_CFG;
7121 req->action = MLAN_ACT_SET;
7122 radio->param.radio_on_off = option;
7123 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
7124 if (status != MLAN_STATUS_SUCCESS)
7125 ret = -EFAULT;
7126
7127 done:
7128 if (status != MLAN_STATUS_PENDING)
7129 kfree(req);
7130 LEAVE();
7131 return ret;
7132 }
7133
7134 #endif /* STA_SUPPORT */
7135
7136 #ifdef USB
7137 /**
7138 * @brief Initialize USB packet aggregation control
7139 *
7140 * @param handle A pointer to moal_private structure
7141 *
7142 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
7143 */
woal_usb_aggr_init(moal_handle * handle)7144 mlan_status woal_usb_aggr_init(moal_handle *handle)
7145 {
7146 mlan_status ret = MLAN_STATUS_SUCCESS;
7147 moal_private *priv = NULL;
7148 mlan_ioctl_req *req = NULL;
7149 mlan_ds_misc_cfg *pcfg_misc = NULL;
7150 mlan_ds_misc_usb_aggr_ctrl *aggr_param = NULL;
7151 t_u8 usb_aggr_enable;
7152 struct usb_card_rec *cardp = NULL;
7153 int i = 0, resubmit_urbs = 0;
7154
7155 ENTER();
7156
7157 if (!handle) {
7158 PRINTM(MERROR, "Handle is null\n");
7159 LEAVE();
7160 return MLAN_STATUS_FAILURE;
7161 }
7162 priv = woal_get_priv(handle, MLAN_BSS_ROLE_STA);
7163 if (!priv) {
7164 PRINTM(MERROR, "STA priv is null\n");
7165 ret = MLAN_STATUS_FAILURE;
7166 goto done;
7167 }
7168 if (handle->card == NULL) {
7169 PRINTM(MERROR, "Card is null in %s()\n", __func__);
7170 ret = MLAN_STATUS_FAILURE;
7171 goto done;
7172 }
7173 cardp = (struct usb_card_rec *)handle->card;
7174
7175 /* Check module parameter */
7176 if (handle->params.usb_aggr == 0 || handle->params.usb_aggr == 2) {
7177 usb_aggr_enable = MFALSE;
7178 } else if (handle->params.usb_aggr == 1) {
7179 usb_aggr_enable = MTRUE;
7180 } else {
7181 PRINTM(MWARN,
7182 "Invalid module param (usb_aggr) value %d, "
7183 "using MLAN default\n",
7184 handle->params.usb_aggr);
7185 handle->params.usb_aggr = 0;
7186 usb_aggr_enable = MFALSE;
7187 }
7188
7189 /* Allocate an IOCTL request buffer */
7190 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
7191 if (req == NULL) {
7192 ret = MLAN_STATUS_FAILURE;
7193 goto done;
7194 }
7195
7196 /* Fill request buffer */
7197 pcfg_misc = (mlan_ds_misc_cfg *)req->pbuf;
7198 pcfg_misc->sub_command = MLAN_OID_MISC_USB_AGGR_CTRL;
7199 req->req_id = MLAN_IOCTL_MISC_CFG;
7200 req->action = MLAN_ACT_SET;
7201
7202 aggr_param = &pcfg_misc->param.usb_aggr_params;
7203 /* Initialize TX aggr default values */
7204 aggr_param->tx_aggr_ctrl.enable = usb_aggr_enable;
7205 aggr_param->tx_aggr_ctrl.aggr_mode = MLAN_USB_AGGR_MODE_NUM;
7206 aggr_param->tx_aggr_ctrl.aggr_align =
7207 MAX(handle->params.max_tx_buf, MLAN_USB_TX_AGGR_ALIGN);
7208 aggr_param->tx_aggr_ctrl.aggr_max = MLAN_USB_TX_MAX_AGGR_NUM;
7209 aggr_param->tx_aggr_ctrl.aggr_tmo =
7210 MLAN_USB_TX_AGGR_TIMEOUT_MSEC * 1000;
7211
7212 /* Initialize RX deaggr default values */
7213 aggr_param->rx_deaggr_ctrl.enable = usb_aggr_enable;
7214 aggr_param->rx_deaggr_ctrl.aggr_mode = MLAN_USB_AGGR_MODE_NUM;
7215 aggr_param->rx_deaggr_ctrl.aggr_align = MLAN_USB_RX_ALIGN_SIZE;
7216 aggr_param->rx_deaggr_ctrl.aggr_max = MLAN_USB_RX_MAX_AGGR_NUM;
7217 aggr_param->rx_deaggr_ctrl.aggr_tmo = MLAN_USB_RX_DEAGGR_TIMEOUT_USEC;
7218
7219 /* Do not fail driver init due to command failure */
7220 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
7221 /* Disable the feature if FW return failure/unsupported */
7222 if (req->status_code)
7223 cardp->tx_aggr_ctrl.enable = MFALSE;
7224 else
7225 moal_memcpy_ext(handle, &cardp->tx_aggr_ctrl,
7226 &aggr_param->tx_aggr_ctrl,
7227 sizeof(usb_aggr_ctrl_cfg),
7228 sizeof(usb_aggr_ctrl_cfg));
7229
7230 if (req->status_code) {
7231 /* Disable the feature if FW return failure/unsupported */
7232 cardp->rx_deaggr_ctrl.enable = MFALSE;
7233 } else {
7234 /* Default is disable, resubmit URBs only for enable */
7235 if (cardp->rx_deaggr_ctrl.enable != usb_aggr_enable)
7236 resubmit_urbs = 1;
7237 }
7238 if (resubmit_urbs) {
7239 /* Indicate resubmition from here */
7240 cardp->resubmit_urbs = 1;
7241 /* Rx SG feature is disabled due to FW failure/unsupported,
7242 * kill the URBs, they will be resubmitted after saving the
7243 * parameters to USB card */
7244 if (atomic_read(&cardp->rx_data_urb_pending)) {
7245 for (i = 0; i < MVUSB_RX_DATA_URB; i++) {
7246 if (cardp->rx_data_list[i].urb) {
7247 usb_kill_urb(
7248 cardp->rx_data_list[i].urb);
7249 usb_init_urb(
7250 cardp->rx_data_list[i].urb);
7251 }
7252 }
7253 }
7254
7255 /* Default is disable, update only for enable case */
7256 moal_memcpy_ext(handle, &cardp->rx_deaggr_ctrl,
7257 &aggr_param->rx_deaggr_ctrl,
7258 sizeof(usb_aggr_ctrl_cfg),
7259 sizeof(usb_aggr_ctrl_cfg));
7260
7261 /* Ensure the next data URBs will use the modified parameters */
7262 if (!atomic_read(&cardp->rx_data_urb_pending)) {
7263 /* Submit multiple Rx data URBs */
7264 woal_usb_submit_rx_data_urbs(handle);
7265 }
7266 cardp->resubmit_urbs = 0;
7267 }
7268
7269 done:
7270 if (ret != MLAN_STATUS_PENDING)
7271 kfree(req);
7272 LEAVE();
7273 return ret;
7274 }
7275 #endif
7276
7277 /**
7278 * @brief Set hotspot configuration value to mlan layer
7279 *
7280 * @param priv A pointer to moal_private structure
7281 * @param wait_option wait option
7282 * @param hotspotcfg Hotspot configuration value
7283 *
7284 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
7285 * otherwise fail
7286 */
woal_set_hotspotcfg(moal_private * priv,t_u8 wait_option,t_u32 hotspotcfg)7287 mlan_status woal_set_hotspotcfg(moal_private *priv, t_u8 wait_option,
7288 t_u32 hotspotcfg)
7289 {
7290 mlan_status ret = MLAN_STATUS_SUCCESS;
7291 mlan_ioctl_req *req = NULL;
7292 mlan_ds_misc_cfg *cfg = NULL;
7293
7294 ENTER();
7295
7296 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
7297 if (req == NULL) {
7298 ret = MLAN_STATUS_FAILURE;
7299 goto done;
7300 }
7301
7302 cfg = (mlan_ds_misc_cfg *)req->pbuf;
7303 cfg->param.hotspot_cfg = hotspotcfg;
7304 req->action = MLAN_ACT_SET;
7305
7306 cfg->sub_command = MLAN_OID_MISC_HOTSPOT_CFG;
7307 req->req_id = MLAN_IOCTL_MISC_CFG;
7308
7309 ret = woal_request_ioctl(priv, req, wait_option);
7310 if (ret != MLAN_STATUS_SUCCESS)
7311 goto done;
7312
7313 done:
7314 if (ret != MLAN_STATUS_PENDING)
7315 kfree(req);
7316 LEAVE();
7317 return ret;
7318 }
7319
7320 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
7321 /**
7322 * @brief Set/Get network monitor configurations
7323 *
7324 * @param priv Pointer to moal_private structure
7325 * @param wait_option wait option
7326 * @param enable Enable/Disable
7327 * @param filter Filter flag - Management/Control/Data
7328 * @param band_chan_cfg Network monitor band channel config
7329 *
7330 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
7331 */
woal_set_net_monitor(moal_private * priv,t_u8 wait_option,t_u8 enable,t_u8 filter,netmon_band_chan_cfg * band_chan_cfg)7332 mlan_status woal_set_net_monitor(moal_private *priv, t_u8 wait_option,
7333 t_u8 enable, t_u8 filter,
7334 netmon_band_chan_cfg *band_chan_cfg)
7335 {
7336 mlan_status ret = MLAN_STATUS_SUCCESS;
7337 mlan_ioctl_req *req = NULL;
7338 mlan_ds_misc_cfg *misc = NULL;
7339 mlan_ds_misc_net_monitor *net_mon = NULL;
7340 mlan_status status = MLAN_STATUS_SUCCESS;
7341
7342 ENTER();
7343
7344 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
7345 if (req == NULL) {
7346 ret = MLAN_STATUS_FAILURE;
7347 goto done;
7348 }
7349 misc = (mlan_ds_misc_cfg *)req->pbuf;
7350 net_mon = (mlan_ds_misc_net_monitor *)&misc->param.net_mon;
7351 misc->sub_command = MLAN_OID_MISC_NET_MONITOR;
7352 req->req_id = MLAN_IOCTL_MISC_CFG;
7353 req->action = MLAN_ACT_SET;
7354 net_mon->enable_net_mon = enable;
7355 if (net_mon->enable_net_mon) {
7356 net_mon->filter_flag = filter;
7357 if (net_mon->enable_net_mon == CHANNEL_SPEC_SNIFFER_MODE) {
7358 net_mon->band = band_chan_cfg->band;
7359 net_mon->channel = band_chan_cfg->channel;
7360 net_mon->chan_bandwidth = band_chan_cfg->chan_bandwidth;
7361 }
7362 }
7363
7364 status = woal_request_ioctl(priv, req, wait_option);
7365 if (status != MLAN_STATUS_SUCCESS) {
7366 ret = MLAN_STATUS_FAILURE;
7367 goto done;
7368 }
7369
7370 done:
7371 if (status != MLAN_STATUS_PENDING)
7372 kfree(req);
7373
7374 LEAVE();
7375 return ret;
7376 }
7377 #endif
7378
7379 /**
7380 * @brief Send delelte all BA command to MLAN
7381 *
7382 * @param priv A pointer to moal_private structure
7383 * @param wait_option Wait option
7384 *
7385 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
7386 * otherwise fail
7387 */
woal_delba_all(moal_private * priv,t_u8 wait_option)7388 mlan_status woal_delba_all(moal_private *priv, t_u8 wait_option)
7389 {
7390 mlan_ioctl_req *req = NULL;
7391 mlan_ds_11n_cfg *cfg_11n = NULL;
7392 mlan_ds_11n_delba *del_ba = NULL;
7393 t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0};
7394 mlan_status status = MLAN_STATUS_SUCCESS;
7395 int ret = 0;
7396
7397 req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(
7398 sizeof(mlan_ds_11n_cfg));
7399 if (req == NULL) {
7400 ret = -ENOMEM;
7401 goto done;
7402 }
7403 cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
7404 req->req_id = MLAN_IOCTL_11N_CFG;
7405 cfg_11n->sub_command = MLAN_OID_11N_CFG_DELBA;
7406
7407 del_ba = &cfg_11n->param.del_ba;
7408 memset(del_ba, 0, sizeof(mlan_ds_11n_delba));
7409 del_ba->direction = DELBA_RX | DELBA_TX;
7410 del_ba->tid = DELBA_ALL_TIDS;
7411 moal_memcpy_ext(priv->phandle, del_ba->peer_mac_addr, zero_mac,
7412 ETH_ALEN, sizeof(del_ba->peer_mac_addr));
7413
7414 status = woal_request_ioctl(priv, req, wait_option);
7415
7416 if (status != MLAN_STATUS_SUCCESS) {
7417 ret = -EFAULT;
7418 goto done;
7419 }
7420
7421 done:
7422 if (status != MLAN_STATUS_PENDING)
7423 kfree(req);
7424 LEAVE();
7425 return ret;
7426 }
7427
7428 /**
7429 * @brief Send 11d enable/disable command to firmware.
7430 *
7431 * @param priv A pointer to moal_private structure
7432 * @param wait_option Wait option
7433 * @param enable Enable/Disable 11d
7434 *
7435 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
7436 * otherwise fail
7437 */
woal_set_11d(moal_private * priv,t_u8 wait_option,t_u8 enable)7438 mlan_status woal_set_11d(moal_private *priv, t_u8 wait_option, t_u8 enable)
7439 {
7440 mlan_ioctl_req *req = NULL;
7441 mlan_ds_snmp_mib *snmp = NULL;
7442 mlan_status ret = MLAN_STATUS_SUCCESS;
7443
7444 ENTER();
7445
7446 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
7447 if (req == NULL) {
7448 LEAVE();
7449 return -ENOMEM;
7450 }
7451
7452 req->action = MLAN_ACT_SET;
7453 req->req_id = MLAN_IOCTL_SNMP_MIB;
7454
7455 snmp = (mlan_ds_snmp_mib *)req->pbuf;
7456 snmp->sub_command = MLAN_OID_SNMP_MIB_DOT11D;
7457 snmp->param.oid_value = enable;
7458
7459 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
7460 if (ret != MLAN_STATUS_PENDING)
7461 kfree(req);
7462
7463 LEAVE();
7464 return ret;
7465 }
7466
7467 /**
7468 * @brief Handle miscellaneous ioctls for asynchronous command response
7469 *
7470 * @param priv Pointer to moal_private structure
7471 * @param info Pointer to mlan_ds_misc_cfg structure
7472 *
7473 * @return N/A
7474 */
woal_ioctl_get_misc_conf(moal_private * priv,mlan_ds_misc_cfg * info)7475 void woal_ioctl_get_misc_conf(moal_private *priv, mlan_ds_misc_cfg *info)
7476 {
7477 ENTER();
7478 switch (info->sub_command) {
7479 default:
7480 break;
7481 }
7482 }
7483
7484 #ifdef CONFIG_PROC_FS
7485 #define RADIO_MODE_STR_LEN 20
7486 #define TX_PWR_STR_LEN 20
7487 #define TX_CONT_STR_LEN 50
7488 #define TX_FRAME_STR_LEN 200
7489 #define HE_TB_TX_STR_LEN 30
7490
7491 /*
7492 * @brief Parse mfg cmd radio mode string
7493 *
7494 * @param s A pointer to user buffer
7495 * @param len Length of user buffer
7496 * @param d A pointer to mfg_cmd_generic_cfg struct
7497 * @return 0 on success, -EINVAL otherwise
7498 */
parse_radio_mode_string(const char * s,size_t len,struct mfg_cmd_generic_cfg * d)7499 static int parse_radio_mode_string(const char *s, size_t len,
7500 struct mfg_cmd_generic_cfg *d)
7501 {
7502 int ret = MLAN_STATUS_SUCCESS;
7503 char *string = NULL;
7504 char *tmp = NULL;
7505 char *pos = NULL;
7506 gfp_t flag;
7507
7508 ENTER();
7509 if (!s || !d) {
7510 LEAVE();
7511 return -EINVAL;
7512 }
7513 flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
7514 string = kzalloc(RADIO_MODE_STR_LEN, flag);
7515 if (string == NULL) {
7516 LEAVE();
7517 return -ENOMEM;
7518 }
7519
7520 moal_memcpy_ext(NULL, string, s + strlen("radio_mode="),
7521 len - strlen("radio_mode="), RADIO_MODE_STR_LEN - 1);
7522
7523 tmp = string;
7524 string = strstrip(string);
7525
7526 /* radio mode index 0 */
7527 pos = strsep(&string, " \t");
7528 if (pos)
7529 d->data1 = (t_u32)woal_string_to_number(pos);
7530
7531 /* radio mode index 1 */
7532 pos = strsep(&string, " \t");
7533 if (pos)
7534 d->data2 = (t_u32)woal_string_to_number(pos);
7535
7536 if ((d->data1 > 14) || (d->data2 > 14))
7537 ret = -EINVAL;
7538
7539 kfree(tmp);
7540 LEAVE();
7541 return ret;
7542 }
7543
7544 /*
7545 * @brief PoweLevelToDUT11Bits
7546 *
7547 * @param Pwr A user txpwr values of type int
7548 * @param PowerLevel A Pointer of uint32 type for converted txpwr vals
7549 * @return nothing just exit
7550 */
7551
PoweLevelToDUT11Bits(int Pwr,t_u32 * PowerLevel)7552 static void PoweLevelToDUT11Bits(int Pwr, t_u32 *PowerLevel)
7553 {
7554 int Z = 0;
7555
7556 if ((Pwr > 64) || (Pwr < -64))
7557 return;
7558
7559 Z = (int)(Pwr * 16);
7560 if (Z < 0) {
7561 Z = Z + (1 << 11);
7562 }
7563 (*PowerLevel) = (t_u32)Z;
7564
7565 return;
7566 }
7567
7568 /*
7569 * @brief Parse mfg cmd tx pwr string
7570 *
7571 * @param handle A pointer to moal_handle structure
7572 * @param s A pointer to user buffer
7573 * @param len Length of user buffer
7574 * @param d A pointer to mfg_cmd_generic_cfg struct
7575 * @return 0 on success, -EINVAL otherwise
7576 */
7577
parse_tx_pwr_string(moal_handle * handle,const char * s,size_t len,struct mfg_cmd_generic_cfg * d)7578 static int parse_tx_pwr_string(moal_handle *handle, const char *s, size_t len,
7579 struct mfg_cmd_generic_cfg *d)
7580 {
7581 int ret = MLAN_STATUS_SUCCESS;
7582 char *string = NULL;
7583 char *tmp = NULL;
7584 char *pos = NULL;
7585 gfp_t flag;
7586 t_u32 tx_pwr_converted = 0xffffffff;
7587 int tx_pwr_local = 0;
7588 t_u8 fc_card = MFALSE;
7589
7590 ENTER();
7591 if (!s || !d) {
7592 LEAVE();
7593 return -EINVAL;
7594 }
7595 #ifdef SD9177
7596 if (IS_SD9177(handle->card_type))
7597 fc_card = MTRUE;
7598 #endif
7599 flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
7600 string = kzalloc(TX_PWR_STR_LEN, flag);
7601 if (string == NULL) {
7602 LEAVE();
7603 return -ENOMEM;
7604 }
7605
7606 moal_memcpy_ext(NULL, string, s + strlen("tx_power="),
7607 len - strlen("tx_power="), TX_PWR_STR_LEN - 1);
7608
7609 tmp = string;
7610 string = strstrip(string);
7611
7612 /* tx power value */
7613 pos = strsep(&string, " \t");
7614 if (fc_card && pos) {
7615 /* for sd9177 we need to convert user power vals including -ve
7616 * vals as per labtool */
7617 tx_pwr_local = woal_string_to_number(pos);
7618 PoweLevelToDUT11Bits(tx_pwr_local, &tx_pwr_converted);
7619 d->data1 = tx_pwr_converted;
7620 } else if (pos) {
7621 d->data1 = (t_u32)woal_string_to_number(pos);
7622 }
7623 /* modulation */
7624 pos = strsep(&string, " \t");
7625 if (pos)
7626 d->data2 = (t_u32)woal_string_to_number(pos);
7627
7628 /* path id */
7629 pos = strsep(&string, " \t");
7630 if (pos)
7631 d->data3 = (t_u32)woal_string_to_number(pos);
7632
7633 if (((!fc_card) && (d->data1 > 24)) || (d->data2 > 2))
7634 ret = -EINVAL;
7635
7636 kfree(tmp);
7637 LEAVE();
7638 return ret;
7639 }
7640 /*
7641 * @brief Parse mfg cmd tx cont string
7642 *
7643 * @param s A pointer to user buffer
7644 * @param len Length of user buffer
7645 * @param d A pointer to mfg_cmd_tx_cont struct
7646 * @return 0 on success, -EINVAL otherwise
7647 */
parse_tx_cont_string(const char * s,size_t len,struct mfg_cmd_tx_cont * d)7648 static int parse_tx_cont_string(const char *s, size_t len,
7649 struct mfg_cmd_tx_cont *d)
7650 {
7651 int ret = MLAN_STATUS_SUCCESS;
7652 char *string = NULL;
7653 char *tmp = NULL;
7654 char *pos = NULL;
7655 gfp_t flag;
7656
7657 ENTER();
7658 if (!s || !d) {
7659 LEAVE();
7660 return -EINVAL;
7661 }
7662 flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
7663 string = kzalloc(TX_CONT_STR_LEN, flag);
7664 if (string == NULL) {
7665 LEAVE();
7666 return -ENOMEM;
7667 }
7668
7669 moal_memcpy_ext(NULL, string, s + strlen("tx_continuous="),
7670 len - strlen("tx_continuous="), TX_CONT_STR_LEN - 1);
7671
7672 tmp = string;
7673 string = strstrip(string);
7674
7675 pos = strsep(&string, " \t");
7676 if (pos)
7677 d->enable_tx = (t_u32)woal_string_to_number(pos);
7678
7679 pos = strsep(&string, " \t");
7680 if (pos)
7681 d->cw_mode = (t_u32)woal_string_to_number(pos);
7682
7683 if (d->enable_tx == MFALSE)
7684 goto done;
7685
7686 pos = strsep(&string, " \t");
7687 if (pos)
7688 d->payload_pattern = (t_u32)woal_string_to_number(pos);
7689
7690 pos = strsep(&string, " \t");
7691 if (pos)
7692 d->cs_mode = (t_u32)woal_string_to_number(pos);
7693
7694 pos = strsep(&string, " \t");
7695 if (pos)
7696 d->act_sub_ch = (t_u32)woal_string_to_number(pos);
7697
7698 pos = strsep(&string, " \t");
7699 if (pos)
7700 d->tx_rate = (t_u32)woal_string_to_number(pos);
7701
7702 if ((d->enable_tx > 1) || (d->cw_mode > 1) || (d->cs_mode > 1) ||
7703 (d->act_sub_ch == 2 || d->act_sub_ch > 3))
7704 ret = -EINVAL;
7705 done:
7706 kfree(tmp);
7707 LEAVE();
7708 return ret;
7709 }
7710
7711 /*
7712 * @brief Parse mfg cmd tx frame string
7713 *
7714 * @param s A pointer to user buffer
7715 * @param len Length of user buffer
7716 * @param d A pointer to mfg_cmd_tx_frame2 struct
7717 * @return 0 on success, -EINVAL otherwise
7718 */
parse_tx_frame_string(const char * s,size_t len,struct mfg_cmd_tx_frame2 * d)7719 static int parse_tx_frame_string(const char *s, size_t len,
7720 struct mfg_cmd_tx_frame2 *d)
7721 {
7722 int ret = MLAN_STATUS_SUCCESS;
7723 char *string = NULL;
7724 char *tmp = NULL;
7725 char *pos = NULL;
7726 int i;
7727 gfp_t flag;
7728
7729 ENTER();
7730 if (!s || !d) {
7731 LEAVE();
7732 return -EINVAL;
7733 }
7734 flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
7735 string = kzalloc(TX_FRAME_STR_LEN, flag);
7736 if (string == NULL)
7737 return -ENOMEM;
7738
7739 moal_memcpy_ext(NULL, string, s + strlen("tx_frame="),
7740 len - strlen("tx_frame="), TX_FRAME_STR_LEN - 1);
7741
7742 tmp = string;
7743 string = strstrip(string);
7744
7745 pos = strsep(&string, " \t");
7746 if (pos)
7747 d->enable = (t_u32)woal_string_to_number(pos);
7748
7749 if (d->enable == MFALSE)
7750 goto done;
7751
7752 pos = strsep(&string, " \t");
7753 if (pos)
7754 d->data_rate = (t_u32)woal_string_to_number(pos);
7755
7756 pos = strsep(&string, " \t");
7757 if (pos)
7758 d->frame_pattern = (t_u32)woal_string_to_number(pos);
7759
7760 pos = strsep(&string, " \t");
7761 if (pos)
7762 d->frame_length = (t_u32)woal_string_to_number(pos);
7763
7764 pos = strsep(&string, " \t");
7765 if (pos)
7766 d->adjust_burst_sifs = (t_u16)woal_string_to_number(pos);
7767
7768 pos = strsep(&string, " \t");
7769 if (pos)
7770 d->burst_sifs_in_us = (t_u32)woal_string_to_number(pos);
7771
7772 pos = strsep(&string, " \t");
7773 if (pos)
7774 d->short_preamble = (t_u32)woal_string_to_number(pos);
7775
7776 pos = strsep(&string, " \t");
7777 if (pos)
7778 d->act_sub_ch = (t_u32)woal_string_to_number(pos);
7779
7780 pos = strsep(&string, " \t");
7781 if (pos)
7782 d->short_gi = (t_u32)woal_string_to_number(pos);
7783
7784 pos = strsep(&string, " \t");
7785 if (pos)
7786 d->adv_coding = (t_u32)woal_string_to_number(pos);
7787
7788 pos = strsep(&string, " \t");
7789 if (pos)
7790 d->tx_bf = (t_u32)woal_string_to_number(pos);
7791
7792 pos = strsep(&string, " \t");
7793 if (pos)
7794 d->gf_mode = (t_u32)woal_string_to_number(pos);
7795
7796 pos = strsep(&string, " \t");
7797 if (pos)
7798 d->stbc = (t_u32)woal_string_to_number(pos);
7799
7800 pos = strsep(&string, " \t");
7801 if (pos)
7802 d->NumPkt = (t_u32)woal_string_to_number(pos);
7803
7804 pos = strsep(&string, " \t");
7805 if (pos)
7806 d->MaxPE = (t_u32)woal_string_to_number(pos);
7807
7808 pos = strsep(&string, " \t");
7809 if (pos)
7810 d->BeamChange = (t_u32)woal_string_to_number(pos);
7811
7812 pos = strsep(&string, " \t");
7813 if (pos)
7814 d->Dcm = (t_u32)woal_string_to_number(pos);
7815
7816 pos = strsep(&string, " \t");
7817 if (pos)
7818 d->Doppler = (t_u32)woal_string_to_number(pos);
7819
7820 pos = strsep(&string, " \t");
7821 if (pos)
7822 d->MidP = (t_u32)woal_string_to_number(pos);
7823
7824 pos = strsep(&string, " \t");
7825 if (pos)
7826 d->QNum = (t_u32)woal_string_to_number(pos);
7827
7828 pos = strsep(&string, " \t");
7829 if (pos) {
7830 for (i = 0; i < ETH_ALEN; i++) {
7831 pos = strsep(&string, ":");
7832 if (pos)
7833 d->bssid[i] = woal_atox(pos);
7834 }
7835 }
7836
7837 if ((d->enable > 1) || (d->frame_length == 0) ||
7838 (d->adjust_burst_sifs > 1) || (d->burst_sifs_in_us > 255) ||
7839 (d->short_preamble > 1) ||
7840 (d->act_sub_ch == 2 || d->act_sub_ch > 3) || (d->short_gi > 1) ||
7841 (d->adv_coding > 1) || (d->tx_bf > 1) || (d->gf_mode > 1) ||
7842 (d->stbc > 1))
7843 ret = -EINVAL;
7844 done:
7845 kfree(tmp);
7846 LEAVE();
7847 return ret;
7848 }
7849
7850 /*
7851 * @brief Parse mfg cmd HE TB Tx string
7852 *
7853 * @param s A pointer to user buffer
7854 * @param len Length of user buffer
7855 * @param d A pointer to mfg_Cmd_HE_TBTx_t struct
7856 * @return 0 on success, -EINVAL otherwise
7857 */
parse_he_tb_tx_string(const char * s,size_t len,struct mfg_Cmd_HE_TBTx_t * d)7858 static int parse_he_tb_tx_string(const char *s, size_t len,
7859 struct mfg_Cmd_HE_TBTx_t *d)
7860 {
7861 int ret = MLAN_STATUS_SUCCESS;
7862 char *string = NULL;
7863 char *pos = NULL;
7864 gfp_t flag;
7865
7866 ENTER();
7867 if (!s || !d) {
7868 LEAVE();
7869 return -EINVAL;
7870 }
7871 flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
7872 string = kzalloc(HE_TB_TX_STR_LEN, flag);
7873 if (string == NULL)
7874 return -ENOMEM;
7875
7876 moal_memcpy_ext(NULL, string, s + strlen("he_tb_tx="),
7877 len - strlen("he_tb_tx="), HE_TB_TX_STR_LEN - 1);
7878
7879 pos = strsep(&string, " \t");
7880 if (pos)
7881 d->enable = (t_u32)woal_string_to_number(pos);
7882
7883 if (d->enable == MFALSE)
7884 goto done;
7885 pos = strsep(&string, " \t");
7886 if (pos)
7887 d->qnum = (t_u32)woal_string_to_number(pos);
7888
7889 pos = strsep(&string, " \t");
7890 if (pos)
7891 d->aid = (t_u32)woal_string_to_number(pos);
7892
7893 pos = strsep(&string, " \t");
7894 if (pos)
7895 d->axq_mu_timer = (t_u32)woal_string_to_number(pos);
7896
7897 pos = strsep(&string, " \t");
7898 if (pos)
7899 d->tx_power = (t_u16)woal_string_to_number(pos);
7900
7901 if (d->enable > 1)
7902 ret = -EINVAL;
7903
7904 done:
7905 kfree(string);
7906 LEAVE();
7907 return ret;
7908 }
7909 /*
7910 * @brief This function enables/disables RF test mode in firmware
7911 *
7912 * @param handle A pointer to moal_handle structure
7913 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING on success,
7914 * otherwise failure code
7915 */
woal_process_rf_test_mode(moal_handle * handle,t_u32 mode)7916 mlan_status woal_process_rf_test_mode(moal_handle *handle, t_u32 mode)
7917 {
7918 mlan_status ret = MLAN_STATUS_FAILURE;
7919 mlan_ioctl_req *req = NULL;
7920 mlan_ds_misc_cfg *misc = NULL;
7921 t_u32 flag = 0;
7922
7923 ENTER();
7924 #ifdef MFG_CMD_SUPPORT
7925 if (mfg_mode) {
7926 LEAVE();
7927 return ret;
7928 }
7929 #endif
7930 if (mode != MFG_CMD_SET_TEST_MODE && mode != MFG_CMD_UNSET_TEST_MODE) {
7931 LEAVE();
7932 return ret;
7933 }
7934
7935 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
7936 if (req) {
7937 misc = (mlan_ds_misc_cfg *)req->pbuf;
7938 misc->sub_command = MLAN_OID_MISC_RF_TEST_GENERIC;
7939 req->req_id = MLAN_IOCTL_MISC_CFG;
7940 req->action = MLAN_ACT_SET;
7941 if (mode == MFG_CMD_SET_TEST_MODE)
7942 misc->param.mfg_generic_cfg.mfg_cmd =
7943 MFG_CMD_SET_TEST_MODE;
7944 ret = woal_request_ioctl(woal_get_priv(handle,
7945 MLAN_BSS_ROLE_ANY),
7946 req, MOAL_IOCTL_WAIT);
7947 }
7948
7949 if (ret == MLAN_STATUS_SUCCESS && mode == MFG_CMD_SET_TEST_MODE &&
7950 handle->rf_data == NULL) {
7951 flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC :
7952 GFP_KERNEL;
7953 /* Allocate memory to hold RF test mode data */
7954 handle->rf_data =
7955 kzalloc(sizeof(struct rf_test_mode_data), flag);
7956 if (!handle->rf_data)
7957 PRINTM(MERROR,
7958 "Couldn't allocate memory for RF test mode\n");
7959 handle->rf_test_mode = MTRUE;
7960 if (handle->rf_data) {
7961 /* antenna is set to 1 by default */
7962 handle->rf_data->tx_antenna = 1;
7963 handle->rf_data->rx_antenna = 1;
7964 }
7965 } else if (mode == MFG_CMD_UNSET_TEST_MODE) {
7966 if (handle->rf_data) {
7967 /* Free RF test mode data memory */
7968 kfree(handle->rf_data);
7969 handle->rf_data = NULL;
7970 }
7971 handle->rf_test_mode = MFALSE;
7972 }
7973 if (ret != MLAN_STATUS_PENDING)
7974 kfree(req);
7975 LEAVE();
7976 return ret;
7977 }
7978
7979 /**
7980 * @brief This function sends RF test mode command in firmware
7981 *
7982 * @param handle A pointer to moal_handle structure
7983 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING on success,
7984 * otherwise failure code
7985 */
woal_process_rf_test_mode_cmd(moal_handle * handle,t_u32 cmd,const char * buffer,size_t len,t_u32 action,t_u32 val)7986 mlan_status woal_process_rf_test_mode_cmd(moal_handle *handle, t_u32 cmd,
7987 const char *buffer, size_t len,
7988 t_u32 action, t_u32 val)
7989 {
7990 mlan_status ret = MLAN_STATUS_FAILURE;
7991 mlan_ioctl_req *req = NULL;
7992 mlan_ds_misc_cfg *misc = NULL;
7993 int err = MFALSE;
7994 int i;
7995
7996 ENTER();
7997
7998 if (!handle->rf_test_mode || !handle->rf_data)
7999 goto done;
8000
8001 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
8002 if (!req)
8003 goto done;
8004
8005 misc = (mlan_ds_misc_cfg *)req->pbuf;
8006 req->req_id = MLAN_IOCTL_MISC_CFG;
8007 misc->sub_command = MLAN_OID_MISC_RF_TEST_GENERIC;
8008 req->action = action;
8009
8010 switch (cmd) {
8011 case MFG_CMD_TX_ANT:
8012 if (val != 1 && val != 2 && val != 3)
8013 err = MTRUE;
8014 break;
8015 case MFG_CMD_RX_ANT:
8016 if (val != 1 && val != 2 && val != 3)
8017 err = MTRUE;
8018 break;
8019 case MFG_CMD_RF_BAND_AG:
8020 if (val != 0 && val != 1)
8021 err = MTRUE;
8022 break;
8023 case MFG_CMD_RF_CHANNELBW:
8024 if (val != 0 && val != 1 &&
8025 (val != 4 ||
8026 (val == 4 && handle->rf_data->band == BAND_2GHZ)))
8027 err = MTRUE;
8028 break;
8029 case MFG_CMD_RF_CHAN:
8030 break;
8031 case MFG_CMD_CLR_RX_ERR:
8032 break;
8033 case MFG_CMD_RADIO_MODE_CFG:
8034 if (parse_radio_mode_string(buffer, len,
8035 &misc->param.mfg_generic_cfg))
8036 err = MTRUE;
8037 break;
8038 case MFG_CMD_RFPWR:
8039 if (parse_tx_pwr_string(handle, buffer, len,
8040 &misc->param.mfg_generic_cfg))
8041 err = MTRUE;
8042 break;
8043 case MFG_CMD_TX_CONT:
8044 misc->sub_command = MLAN_OID_MISC_RF_TEST_TX_CONT;
8045 if (parse_tx_cont_string(buffer, len, &misc->param.mfg_tx_cont))
8046 err = MTRUE;
8047 break;
8048 case MFG_CMD_TX_FRAME:
8049 misc->sub_command = MLAN_OID_MISC_RF_TEST_TX_FRAME;
8050 if (parse_tx_frame_string(buffer, len,
8051 &misc->param.mfg_tx_frame2))
8052 err = MTRUE;
8053 break;
8054 case MFG_CMD_CONFIG_MAC_HE_TB_TX:
8055 misc->sub_command = MLAN_OID_MISC_RF_TEST_HE_POWER;
8056 if (parse_he_tb_tx_string(buffer, len,
8057 &misc->param.mfg_he_power))
8058 err = MTRUE;
8059 break;
8060 default:
8061 err = MTRUE;
8062 }
8063
8064 if (!err) {
8065 misc->param.mfg_generic_cfg.mfg_cmd = (t_u32)cmd;
8066 if (cmd != MFG_CMD_RFPWR &&
8067 misc->sub_command == MLAN_OID_MISC_RF_TEST_GENERIC)
8068 misc->param.mfg_generic_cfg.data1 = val;
8069
8070 ret = woal_request_ioctl(woal_get_priv(handle,
8071 MLAN_BSS_ROLE_ANY),
8072 req, MOAL_IOCTL_WAIT);
8073 }
8074 if (ret != MLAN_STATUS_SUCCESS)
8075 goto done;
8076
8077 switch (cmd) {
8078 case MFG_CMD_TX_ANT:
8079 handle->rf_data->tx_antenna = misc->param.mfg_generic_cfg.data1;
8080 break;
8081 case MFG_CMD_RX_ANT:
8082 handle->rf_data->rx_antenna = misc->param.mfg_generic_cfg.data1;
8083 break;
8084 case MFG_CMD_RADIO_MODE_CFG:
8085 handle->rf_data->radio_mode[0] =
8086 misc->param.mfg_generic_cfg.data1;
8087 handle->rf_data->radio_mode[1] =
8088 misc->param.mfg_generic_cfg.data2;
8089 break;
8090 case MFG_CMD_RF_BAND_AG:
8091 handle->rf_data->band = misc->param.mfg_generic_cfg.data1;
8092 /* set fw default bw and channel config on band change */
8093 handle->rf_data->bandwidth = CHANNEL_BW_20MHZ;
8094 if (handle->rf_data->band == BAND_2GHZ)
8095 handle->rf_data->channel = 6;
8096 else if (handle->rf_data->band == BAND_5GHZ)
8097 handle->rf_data->channel = 36;
8098 break;
8099 case MFG_CMD_RF_CHANNELBW:
8100 handle->rf_data->bandwidth = misc->param.mfg_generic_cfg.data1;
8101 break;
8102 case MFG_CMD_RF_CHAN:
8103 handle->rf_data->channel = misc->param.mfg_generic_cfg.data1;
8104 break;
8105 case MFG_CMD_CLR_RX_ERR:
8106 handle->rf_data->rx_tot_pkt_count =
8107 misc->param.mfg_generic_cfg.data1;
8108 handle->rf_data->rx_mcast_bcast_pkt_count =
8109 misc->param.mfg_generic_cfg.data2;
8110 handle->rf_data->rx_pkt_fcs_err_count =
8111 misc->param.mfg_generic_cfg.data3;
8112 break;
8113 case MFG_CMD_RFPWR:
8114 handle->rf_data->tx_power_data[0] =
8115 misc->param.mfg_generic_cfg.data1;
8116 handle->rf_data->tx_power_data[1] =
8117 misc->param.mfg_generic_cfg.data2;
8118 handle->rf_data->tx_power_data[2] =
8119 misc->param.mfg_generic_cfg.data3;
8120 break;
8121 case MFG_CMD_TX_CONT:
8122 handle->rf_data->tx_cont_data[0] =
8123 misc->param.mfg_tx_cont.enable_tx;
8124 handle->rf_data->tx_cont_data[1] =
8125 misc->param.mfg_tx_cont.cw_mode;
8126 handle->rf_data->tx_cont_data[2] =
8127 misc->param.mfg_tx_cont.payload_pattern;
8128 handle->rf_data->tx_cont_data[3] =
8129 misc->param.mfg_tx_cont.cs_mode;
8130 handle->rf_data->tx_cont_data[4] =
8131 misc->param.mfg_tx_cont.act_sub_ch;
8132 handle->rf_data->tx_cont_data[5] =
8133 misc->param.mfg_tx_cont.tx_rate;
8134 break;
8135 case MFG_CMD_TX_FRAME:
8136 handle->rf_data->tx_frame_data[0] =
8137 misc->param.mfg_tx_frame2.enable;
8138 handle->rf_data->tx_frame_data[1] =
8139 misc->param.mfg_tx_frame2.data_rate;
8140 handle->rf_data->tx_frame_data[2] =
8141 misc->param.mfg_tx_frame2.frame_pattern;
8142 handle->rf_data->tx_frame_data[3] =
8143 misc->param.mfg_tx_frame2.frame_length;
8144 handle->rf_data->tx_frame_data[4] =
8145 misc->param.mfg_tx_frame2.adjust_burst_sifs;
8146 handle->rf_data->tx_frame_data[5] =
8147 misc->param.mfg_tx_frame2.burst_sifs_in_us;
8148 handle->rf_data->tx_frame_data[6] =
8149 misc->param.mfg_tx_frame2.short_preamble;
8150 handle->rf_data->tx_frame_data[7] =
8151 misc->param.mfg_tx_frame2.act_sub_ch;
8152 handle->rf_data->tx_frame_data[8] =
8153 misc->param.mfg_tx_frame2.short_gi;
8154 handle->rf_data->tx_frame_data[9] =
8155 misc->param.mfg_tx_frame2.adv_coding;
8156 handle->rf_data->tx_frame_data[10] =
8157 misc->param.mfg_tx_frame2.tx_bf;
8158 handle->rf_data->tx_frame_data[11] =
8159 misc->param.mfg_tx_frame2.gf_mode;
8160 handle->rf_data->tx_frame_data[12] =
8161 misc->param.mfg_tx_frame2.stbc;
8162 handle->rf_data->tx_frame_data[13] =
8163 misc->param.mfg_tx_frame2.NumPkt;
8164 handle->rf_data->tx_frame_data[14] =
8165 misc->param.mfg_tx_frame2.MaxPE;
8166 handle->rf_data->tx_frame_data[15] =
8167 misc->param.mfg_tx_frame2.BeamChange;
8168 handle->rf_data->tx_frame_data[16] =
8169 misc->param.mfg_tx_frame2.Dcm;
8170 handle->rf_data->tx_frame_data[17] =
8171 misc->param.mfg_tx_frame2.Doppler;
8172 handle->rf_data->tx_frame_data[18] =
8173 misc->param.mfg_tx_frame2.MidP;
8174 handle->rf_data->tx_frame_data[19] =
8175 misc->param.mfg_tx_frame2.QNum;
8176 for (i = 0; i < ETH_ALEN; i++) {
8177 handle->rf_data->bssid[i] =
8178 misc->param.mfg_tx_frame2.bssid[i];
8179 }
8180 break;
8181 case MFG_CMD_CONFIG_MAC_HE_TB_TX:
8182 handle->rf_data->he_tb_tx[0] = misc->param.mfg_he_power.enable;
8183 handle->rf_data->he_tb_tx[1] = misc->param.mfg_he_power.qnum;
8184 handle->rf_data->he_tb_tx[2] = misc->param.mfg_he_power.aid;
8185 handle->rf_data->he_tb_tx[3] =
8186 misc->param.mfg_he_power.axq_mu_timer;
8187 handle->rf_data->he_tb_tx[4] =
8188 misc->param.mfg_he_power.tx_power;
8189 break;
8190 }
8191 done:
8192 if (err || ret != MLAN_STATUS_PENDING)
8193 kfree(req);
8194
8195 LEAVE();
8196 return ret;
8197 }
8198 #endif /* RF_TEST_MODE */
8199