1 /** @file moal_ioctl.c
2 *
3 * @brief This file contains ioctl function to MLAN
4 *
5 * Copyright (C) 2008-2017, Marvell International Ltd.
6 *
7 * This software file (the "File") is distributed by Marvell International
8 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
9 * (the "License"). You may use, redistribute and/or modify this File in
10 * accordance with the terms and conditions of the License, a copy of which
11 * is available by writing to the Free Software Foundation, Inc.,
12 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
13 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
14 *
15 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
17 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
18 * this warranty disclaimer.
19 *
20 */
21
22 /********************************************************
23 Change log:
24 10/21/2008: initial version
25 ********************************************************/
26
27 #include "moal_main.h"
28 #include "moal_eth_ioctl.h"
29 #include "moal_sdio.h"
30 #ifdef UAP_SUPPORT
31 #include "moal_uap.h"
32 #endif
33
34 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
35 #include "moal_cfg80211.h"
36 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
37 #include "moal_cfgvendor.h"
38 #endif
39 #endif
40
41 /********************************************************
42 Local Variables
43 ********************************************************/
44 #define MRVL_TLV_HEADER_SIZE 4
45 /* Marvell Channel config TLV ID */
46 #define MRVL_CHANNELCONFIG_TLV_ID (0x0100 + 0x2a) /* 0x012a */
47
48 typedef struct _hostcmd_header {
49 /** Command Header : Command */
50 t_u16 command;
51 /** Command Header : Size */
52 t_u16 size;
53 /** Command Header : Sequence number */
54 t_u16 seq_num;
55 /** Command Header : Result */
56 t_u16 result;
57 /** Command action */
58 t_u16 action;
59 } hostcmd_header, *phostcmd_header;
60
61 /** Region code mapping */
62 typedef struct _region_code_mapping_t {
63 /** Region */
64 t_u8 region[COUNTRY_CODE_LEN];
65 /** Code */
66 t_u8 code;
67 } region_code_mapping_t;
68
69 #define EU_REGION_CODE 0x30
70
71 /** Region code mapping table */
72 static region_code_mapping_t region_code_mapping[] = {
73 {"US ", 0x10}, /* US FCC */
74 {"CA ", 0x20}, /* IC Canada */
75 {"SG ", 0x10}, /* Singapore */
76 {"EU ", 0x30}, /* ETSI */
77 {"AU ", 0x30}, /* Australia */
78 {"KR ", 0x30}, /* Republic Of Korea */
79 {"CN ", 0x50}, /* China */
80 {"JP ", 0xFF}, /* Japan special */
81 };
82
83 /** EEPROM Region code mapping table */
84 static region_code_mapping_t hw_region_code_mapping[] = {
85 {"US ", 0x10}, /* US FCC */
86 {"CA ", 0x20}, /* IC Canada */
87 {"KR ", 0x30}, /* Korea */
88 {"CN ", 0x50}, /* China */
89 {"ES ", 0x31}, /* Spain */
90 {"FR ", 0x32}, /* France */
91 {"JP ", 0x40}, /* Japan */
92 {"JP ", 0x41}, /* Japan */
93 };
94
95 /** Country code for ETSI */
96 static t_u8 eu_country_code_table[][COUNTRY_CODE_LEN] = {
97 "AL", "AD", "AT", "AU", "BY", "BE", "BA", "BG", "HR", "CY",
98 "CZ", "DK", "EE", "FI", "FR", "MK", "DE", "GR", "HU", "IS",
99 "IE", "IT", "KR", "LV", "LI", "LT", "LU", "MT", "MD", "MC",
100 "ME", "NL", "NO", "PL", "RO", "RU", "SM", "RS", "SI", "SK",
101 "ES", "SE", "CH", "TR", "UA", "UK", "GB"
102 };
103
104 /********************************************************
105 Global Variables
106 ********************************************************/
107
108 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
109 #ifdef UAP_SUPPORT
110 /** Network device handlers for uAP */
111 extern const struct net_device_ops woal_uap_netdev_ops;
112 #endif
113 #ifdef STA_SUPPORT
114 /** Network device handlers for STA */
115 extern const struct net_device_ops woal_netdev_ops;
116 #endif
117 #endif
118 extern int cfg80211_wext;
119 int disconnect_on_suspend;
120
121 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
122 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
123 extern int dfs_offload;
124 #endif
125 #endif
126
127 extern int roamoffload_in_hs;
128
129 /** gtk rekey offload mode */
130 extern int gtk_rekey_offload;
131
132 /********************************************************
133 Local Functions
134 ********************************************************/
135 /**
136 * @brief This function converts region string to region code
137 *
138 * @param region_string Region string
139 *
140 * @return Region code
141 */
142 t_u8
region_string_2_region_code(char * region_string)143 region_string_2_region_code(char *region_string)
144 {
145 t_u8 i;
146
147 ENTER();
148 for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
149 if (!memcmp(region_string,
150 region_code_mapping[i].region,
151 strlen(region_string))) {
152 LEAVE();
153 return region_code_mapping[i].code;
154 }
155 }
156
157 /* If still not found, look for code in EU country code table */
158 for (i = 0; i < ARRAY_SIZE(eu_country_code_table); i++) {
159 if (!memcmp(region_string, eu_country_code_table[i],
160 COUNTRY_CODE_LEN - 1)) {
161 PRINTM(MIOCTL, "found region code=%d in EU table\n",
162 EU_REGION_CODE);
163 LEAVE();
164 return EU_REGION_CODE;
165 }
166 }
167
168 /* Default is US */
169 LEAVE();
170 return region_code_mapping[0].code;
171 }
172
173 /**
174 * @brief This function converts region string to region code
175 *
176 * @param country_code Region string
177 *
178 * @return Region code
179 */
180 t_bool
woal_is_etsi_country(t_u8 * country_code)181 woal_is_etsi_country(t_u8 *country_code)
182 {
183
184 t_u8 i;
185 ENTER();
186
187 for (i = 0; i < ARRAY_SIZE(eu_country_code_table); i++) {
188 if (!memcmp(country_code, eu_country_code_table[i],
189 COUNTRY_CODE_LEN - 1)) {
190 PRINTM(MIOCTL, "found region code=%d in EU table\n",
191 EU_REGION_CODE);
192 LEAVE();
193 return MTRUE;
194 }
195 }
196
197 LEAVE();
198 return MFALSE;
199 }
200
201 /**
202 * @brief This function converts region string to region code
203 *
204 * @param region_code region code
205 *
206 * @return Region string or NULL
207 */
208 char *
region_code_2_string(t_u8 region_code)209 region_code_2_string(t_u8 region_code)
210 {
211 t_u8 i;
212
213 ENTER();
214 for (i = 0; i < ARRAY_SIZE(hw_region_code_mapping); i++) {
215 if (hw_region_code_mapping[i].code == region_code) {
216 LEAVE();
217 return hw_region_code_mapping[i].region;
218 }
219 }
220 LEAVE();
221 return NULL;
222 }
223
224 t_u8
woal_is_valid_alpha2(char * alpha2)225 woal_is_valid_alpha2(char *alpha2)
226 {
227 if (!alpha2 || strlen(alpha2) < 2)
228 return MFALSE;
229 if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
230 return MTRUE;
231 return MFALSE;
232 }
233
234 /**
235 * @brief Copy mc address to the mlist
236 *
237 * @param mlist A pointer to mlan_multicast_list structure
238 * @param mac mc address
239 *
240 * @return N/A
241 */
242 static inline void
woal_copy_mc_addr(mlan_multicast_list * mlist,mlan_802_11_mac_addr mac)243 woal_copy_mc_addr(mlan_multicast_list *mlist, mlan_802_11_mac_addr mac)
244 {
245 int i = 0;
246 for (i = 0; i < mlist->num_multicast_addr; i++) {
247 if (!memcmp(&mlist->mac_list[i], mac, ETH_ALEN))
248 return;
249 }
250 if (mlist->num_multicast_addr < MLAN_MAX_MULTICAST_LIST_SIZE)
251 memcpy(&mlist->mac_list[mlist->num_multicast_addr], mac,
252 ETH_ALEN);
253 mlist->num_multicast_addr++;
254 return;
255 }
256
257 /**
258 * @brief Copy multicast table
259 *
260 * @param mlist A pointer to mlan_multicast_list structure
261 * @param dev A pointer to net_device structure
262 *
263 * @return Number of multicast addresses
264 */
265 static inline int
woal_copy_mcast_addr(mlan_multicast_list * mlist,struct net_device * dev)266 woal_copy_mcast_addr(mlan_multicast_list *mlist, struct net_device *dev)
267 {
268 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
269 struct dev_mc_list *mcptr = dev->mc_list;
270 int i = 0;
271 #else
272 struct netdev_hw_addr *mcptr = NULL;
273 #endif /* < 2.6.35 */
274
275 ENTER();
276 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
277 for (i = 0; i < dev->mc_count && mcptr; i++) {
278 woal_copy_mc_addr(mlist, mcptr->dmi_addr);
279 mcptr = mcptr->next;
280 }
281 #else
282 netdev_for_each_mc_addr(mcptr, dev)
283 woal_copy_mc_addr(mlist, mcptr->addr);
284 #endif /* < 2.6.35 */
285 LEAVE();
286 return mlist->num_multicast_addr;
287 }
288
289 /**
290 * @brief copy mc list from all the active interface
291 *
292 * @param handle A pointer to moal_handle
293 * @param mlist A pointer to multicast list
294 *
295 * @return total_mc_count
296 */
297 static int
woal_copy_all_mc_list(moal_handle * handle,mlan_multicast_list * mlist)298 woal_copy_all_mc_list(moal_handle *handle, mlan_multicast_list *mlist)
299 {
300 int i;
301 moal_private *priv = NULL;
302 #ifdef STA_SUPPORT
303 int mc_count = 0;
304 #endif
305 ENTER();
306 for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) {
307 #ifdef STA_SUPPORT
308 if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA) {
309 if (handle->priv[i]->media_connected == MTRUE) {
310 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
311 mc_count = priv->netdev->mc_count;
312 #else
313 mc_count = netdev_mc_count(priv->netdev);
314 #endif
315 if (mc_count)
316 woal_copy_mcast_addr(mlist,
317 priv->netdev);
318 }
319 }
320 #endif
321 }
322 PRINTM(MIOCTL, "total mc_count=%d\n", mlist->num_multicast_addr);
323 LEAVE();
324 return mlist->num_multicast_addr;
325 }
326
327 /**
328 * @brief Fill in wait queue
329 *
330 * @param priv A pointer to moal_private structure
331 * @param wait A pointer to wait_queue structure
332 * @param wait_option Wait option
333 *
334 * @return N/A
335 */
336 static inline void
woal_fill_wait_queue(moal_private * priv,wait_queue * wait,t_u8 wait_option)337 woal_fill_wait_queue(moal_private *priv, wait_queue *wait, t_u8 wait_option)
338 {
339 ENTER();
340 wait->start_time = jiffies;
341 wait->condition = MFALSE;
342 wait->wait_timeout = MFALSE;
343 switch (wait_option) {
344 case MOAL_NO_WAIT:
345 break;
346 case MOAL_IOCTL_WAIT:
347 init_waitqueue_head(&wait->wait);
348 break;
349 case MOAL_IOCTL_WAIT_TIMEOUT:
350 init_waitqueue_head(&wait->wait);
351 wait->wait_timeout = MTRUE;
352 break;
353 }
354 LEAVE();
355 return;
356 }
357
358 /**
359 * @brief Wait mlan ioctl complete
360 *
361 * @param priv A pointer to moal_private structure
362 * @param req A pointer to mlan_ioctl_req structure
363 * @param wait_option Wait option
364 *
365 * @return N/A
366 */
367 static inline mlan_status
woal_wait_ioctl_complete(moal_private * priv,mlan_ioctl_req * req,t_u8 wait_option)368 woal_wait_ioctl_complete(moal_private *priv, mlan_ioctl_req *req,
369 t_u8 wait_option)
370 {
371 mlan_status status;
372 wait_queue *wait = (wait_queue *)req->reserved_1;
373 unsigned long flags;
374
375 ENTER();
376
377 priv->phandle->ioctl_timeout = MFALSE;
378
379 switch (wait_option) {
380 case MOAL_NO_WAIT:
381 break;
382 case MOAL_IOCTL_WAIT:
383 while (wait_event_interruptible_exclusive
384 (wait->wait, wait->condition)
385 == -ERESTARTSYS && wait->retry < MAX_RETRY_CNT) {
386 wait->retry++;
387 }
388 break;
389 case MOAL_IOCTL_WAIT_TIMEOUT:
390 wait_event_timeout(wait->wait, wait->condition,
391 MOAL_IOCTL_TIMEOUT);
392 break;
393 }
394 spin_lock_irqsave(&priv->phandle->driver_lock, flags);
395 if (wait->condition == MFALSE) {
396 if (wait_option == MOAL_IOCTL_WAIT_TIMEOUT) {
397 priv->phandle->ioctl_timeout = MTRUE;
398 PRINTM(MMSG,
399 "wlan: IOCTL timeout %p id=0x%x, sub_id=0x%x, wait_option=%d, action=%d\n",
400 req, req->req_id, (*(t_u32 *)req->pbuf),
401 wait_option, (int)req->action);
402 } else {
403 PRINTM(MMSG,
404 "wlan: IOCTL by signal %p id=0x%x, sub_id=0x%x, wait_option=%d, action=%d\n",
405 req, req->req_id, (*(t_u32 *)req->pbuf),
406 wait_option, (int)req->action);
407 }
408 req->reserved_1 = 0;
409 status = MLAN_STATUS_PENDING;
410 } else {
411 status = wait->status;
412 }
413 spin_unlock_irqrestore(&priv->phandle->driver_lock, flags);
414
415 LEAVE();
416 return status;
417 }
418
419 /**
420 * @brief CAC period block cmd handler
421 *
422 * @param priv A pointer to moal_private structure
423 * @param req A pointer to mlan_ioctl_req buffer
424 *
425 * @return MTRUE/MFALSE
426 */
427 static inline t_bool
woal_cac_period_block_cmd(moal_private * priv,pmlan_ioctl_req req)428 woal_cac_period_block_cmd(moal_private *priv, pmlan_ioctl_req req)
429 {
430 mlan_status ret = MFALSE;
431 t_u32 sub_command;
432
433 ENTER();
434 if (req == NULL || req->pbuf == NULL)
435 goto done;
436
437 sub_command = *(t_u32 *)req->pbuf;
438
439 switch (req->req_id) {
440 case MLAN_IOCTL_SCAN:
441 if (sub_command == MLAN_OID_SCAN_NORMAL ||
442 sub_command == MLAN_OID_SCAN_SPECIFIC_SSID ||
443 sub_command == MLAN_OID_SCAN_USER_CONFIG)
444 ret = MTRUE;
445 break;
446 case MLAN_IOCTL_BSS:
447 if (sub_command == MLAN_OID_BSS_STOP ||
448 sub_command == MLAN_OID_BSS_CHANNEL
449 /* sub_command == MLAN_OID_BSS_ROLE */ )
450 ret = MTRUE;
451 #ifdef UAP_SUPPORT
452 else if (sub_command == MLAN_OID_UAP_BSS_CONFIG) {
453 mlan_ds_bss *bss = (mlan_ds_bss *)req->pbuf;
454 if (bss->param.bss_config.channel)
455 ret = MTRUE;
456 else
457 ret = MFALSE;
458 }
459 #endif
460 break;
461 case MLAN_IOCTL_RADIO_CFG:
462 if (sub_command == MLAN_OID_BAND_CFG)
463 ret = MTRUE;
464 break;
465 case MLAN_IOCTL_SNMP_MIB:
466 if (sub_command == MLAN_OID_SNMP_MIB_DOT11D)
467 ret = MTRUE;
468 #if defined(UAP_SUPPORT)
469 if (sub_command == MLAN_OID_SNMP_MIB_DOT11H)
470 ret = MTRUE;
471 #endif
472 break;
473 case MLAN_IOCTL_11D_CFG:
474 #ifdef STA_SUPPORT
475 if (sub_command == MLAN_OID_11D_CFG_ENABLE)
476 ret = MTRUE;
477 #endif
478 if (sub_command == MLAN_OID_11D_DOMAIN_INFO)
479 ret = MTRUE;
480 break;
481 case MLAN_IOCTL_MISC_CFG:
482 if (sub_command == MLAN_OID_MISC_REGION)
483 ret = MTRUE;
484 if (sub_command == MLAN_OID_MISC_HOST_CMD) {
485 phostcmd_header phostcmd;
486 t_u8 *ptlv_buf;
487 t_u16 tag, length;
488
489 phostcmd =
490 (phostcmd_header)((pmlan_ds_misc_cfg)req->
491 pbuf)->param.hostcmd.cmd;
492 ptlv_buf = (t_u8 *)phostcmd + sizeof(hostcmd_header);
493 if (phostcmd->action == MLAN_ACT_SET) {
494 while (ptlv_buf <
495 (t_u8 *)phostcmd + phostcmd->size) {
496 tag = *(t_u16 *)ptlv_buf;
497 length = *(t_u16 *)(ptlv_buf + 2);
498 /* Check Blocking TLV here, should add more... */
499 if (tag == MRVL_CHANNELCONFIG_TLV_ID) {
500 ret = MTRUE;
501 break;
502 }
503 ptlv_buf +=
504 (length + MRVL_TLV_HEADER_SIZE);
505 }
506 }
507 }
508 break;
509 case MLAN_IOCTL_11H_CFG:
510 /* Prevent execute more than once */
511 if (sub_command == MLAN_OID_11H_CHANNEL_CHECK)
512 ret = MTRUE;
513 break;
514 default:
515 ret = MFALSE;
516 break;
517 }
518
519 done:
520 LEAVE();
521 return ret;
522 }
523
524 /********************************************************
525 Global Functions
526 ********************************************************/
527
528 /**
529 * @brief Send ioctl request to MLAN
530 *
531 * @param priv A pointer to moal_private structure
532 * @param req A pointer to mlan_ioctl_req buffer
533 * @param wait_option Wait option (MOAL_IOCTL_WAIT or MOAL_NO_WAIT)
534 *
535 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
536 * -- success, otherwise fail
537 */
538 mlan_status
woal_request_ioctl(moal_private * priv,mlan_ioctl_req * req,t_u8 wait_option)539 woal_request_ioctl(moal_private *priv, mlan_ioctl_req *req, t_u8 wait_option)
540 {
541 wait_queue *wait = NULL;
542 mlan_status status;
543 unsigned long flags;
544 t_u32 sub_command = *(t_u32 *)req->pbuf;
545
546 ENTER();
547
548 if (!priv) {
549 LEAVE();
550 return MLAN_STATUS_FAILURE;
551 }
552 if (sub_command != MLAN_OID_GET_DEBUG_INFO) {
553 if (priv->phandle->surprise_removed == MTRUE ||
554 priv->phandle->driver_state) {
555 PRINTM(MERROR,
556 "IOCTL is not allowed while the device is not present or hang\n");
557 LEAVE();
558 return MLAN_STATUS_FAILURE;
559 }
560 #if defined(SDIO_SUSPEND_RESUME)
561 if (priv->phandle->is_suspended == MTRUE) {
562 PRINTM(MERROR,
563 "IOCTL is not allowed while suspended\n");
564 LEAVE();
565 return MLAN_STATUS_FAILURE;
566 }
567 #endif
568 }
569 /* For MLAN_OID_MISC_HOST_CMD, action is 0, "action set" is checked later */
570 if ((req->action == MLAN_ACT_SET || req->action == 0) &&
571 priv->phandle->cac_period == MTRUE) {
572
573 /* CAC checking period left to complete jiffies */
574 long cac_left_jiffies;
575
576 /* cac_left_jiffies will be negative if and only if
577 * event MLAN_EVENT_ID_DRV_MEAS_REPORT recieved from FW
578 * after CAC measure period ends,
579 * usually this could be considered as a FW bug
580 */
581 cac_left_jiffies = priv->phandle->cac_timer_jiffies -
582 (jiffies - priv->phandle->meas_start_jiffies);
583 #ifdef DFS_TESTING_SUPPORT
584 if (priv->phandle->cac_period_jiffies) {
585 cac_left_jiffies = priv->phandle->cac_period_jiffies -
586 (jiffies - priv->phandle->meas_start_jiffies);
587 }
588 #endif
589 if (cac_left_jiffies < 0) {
590 /* Avoid driver hang in FW died during CAC measure period */
591 priv->phandle->cac_period = MFALSE;
592 PRINTM(MERROR,
593 "CAC measure period spends longer than scheduled time "
594 "or meas done event never received\n");
595 status = MLAN_STATUS_FAILURE;
596 #ifdef UAP_SUPPORT
597 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
598 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
599 if (priv->uap_host_based && dfs_offload)
600 woal_cfg80211_dfs_vendor_event(priv,
601 event_dfs_cac_aborted,
602 &priv->chan);
603 #endif
604 #endif
605 #endif
606
607 goto done;
608 }
609
610 /* Check BSS START first */
611 if (sub_command == MLAN_OID_BSS_START) {
612 mlan_ds_bss *bss;
613 bss = (mlan_ds_bss *)req->pbuf;
614 /*
615 * Bss delay start after channel report received,
616 * not block the driver by delay executing. This is
617 * because a BSS_START cmd is always executed right
618 * after channel check issued.
619 */
620 if (priv->phandle->delay_bss_start == MFALSE) {
621 PRINTM(MMSG,
622 "Received BSS Start command during CAC period, delay executing %ld seconds\n",
623 cac_left_jiffies / HZ);
624 priv->phandle->delay_bss_start = MTRUE;
625 memcpy(&priv->phandle->delay_ssid_bssid,
626 &bss->param.ssid_bssid,
627 sizeof(mlan_ssid_bssid));
628 /* TODO: return success to allow the half below of routines
629 * of which calling BSS start to execute
630 */
631 status = MLAN_STATUS_SUCCESS;
632 goto done;
633 } else {
634 /* TODO: not blocking it, just return failure */
635 PRINTM(MMSG,
636 "Only one BSS Start command allowed for delay executing!\n");
637 status = MLAN_STATUS_FAILURE;
638 goto done;
639 }
640 }
641 if (woal_cac_period_block_cmd(priv, req)) {
642 priv->phandle->meas_wait_q_woken = MFALSE;
643 PRINTM(MMSG,
644 "CAC check is on going... Blocking Command %ld seconds\n",
645 cac_left_jiffies / HZ);
646 /* blocking timeout set to 1.5 * CAC checking period left time */
647 wait_event_interruptible_timeout(priv->phandle->
648 meas_wait_q,
649 priv->phandle->
650 meas_wait_q_woken,
651 cac_left_jiffies * 3 /
652 2);
653 }
654 }
655 #ifdef UAP_CFG80211
656 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
657 else if (priv->phandle->is_cac_timer_set &&
658 (req->action == MLAN_ACT_SET || req->action == 0)) {
659 if (woal_cac_period_block_cmd(priv, req)) {
660 PRINTM(MMSG,
661 "CAC check is on going... Blocking Command\n");
662 status = MLAN_STATUS_FAILURE;
663 goto done;
664 }
665 }
666 #endif
667 #endif
668 else if (priv->phandle->cac_period) {
669 PRINTM(MINFO, "Operation during CAC check period.\n");
670 }
671 wait = (wait_queue *)req->reserved_1;
672 req->bss_index = priv->bss_index;
673 if (wait_option)
674 woal_fill_wait_queue(priv, wait, wait_option);
675 else
676 req->reserved_1 = 0;
677
678 /* Call MLAN ioctl handle */
679 atomic_inc(&priv->phandle->ioctl_pending);
680 spin_lock_irqsave(&priv->phandle->ioctl_lock, flags);
681 status = mlan_ioctl(priv->phandle->pmlan_adapter, req);
682 spin_unlock_irqrestore(&priv->phandle->ioctl_lock, flags);
683 switch (status) {
684 case MLAN_STATUS_PENDING:
685 if (wait_option == MOAL_NO_WAIT)
686 PRINTM(MIOCTL, "IOCTL MOAL_NO_WAIT: %p\n", req);
687 else
688 PRINTM(MIOCTL,
689 "IOCTL pending: %p id=0x%x, sub_id=0x%x wait_option=%d, action=%d\n",
690 req, req->req_id, (*(t_u32 *)req->pbuf),
691 wait_option, (int)req->action);
692 /* Status pending, wake up main process */
693 queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
694
695 /* Wait for completion */
696 if (wait_option)
697 status = woal_wait_ioctl_complete(priv, req,
698 wait_option);
699 break;
700 case MLAN_STATUS_SUCCESS:
701 case MLAN_STATUS_FAILURE:
702 case MLAN_STATUS_RESOURCE:
703 PRINTM(MIOCTL,
704 "IOCTL: %p id=0x%x, sub_id=0x%x wait_option=%d, action=%d status=%d\n",
705 req, req->req_id, (*(t_u32 *)req->pbuf), wait_option,
706 (int)req->action, status);
707 atomic_dec(&priv->phandle->ioctl_pending);
708 break;
709 default:
710 atomic_dec(&priv->phandle->ioctl_pending);
711 break;
712 }
713
714 done:
715 LEAVE();
716 return status;
717 }
718
719 /**
720 * @brief Send set MAC address request to MLAN
721 *
722 * @param priv A pointer to moal_private structure
723 *
724 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
725 * -- success, otherwise fail
726 */
727 mlan_status
woal_request_set_mac_address(moal_private * priv)728 woal_request_set_mac_address(moal_private *priv)
729 {
730 mlan_ioctl_req *req = NULL;
731 mlan_ds_bss *bss = NULL;
732 mlan_status status;
733 ENTER();
734
735 /* Allocate an IOCTL request buffer */
736 req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
737 if (req == NULL) {
738 status = MLAN_STATUS_FAILURE;
739 goto done;
740 }
741
742 /* Fill request buffer */
743 bss = (mlan_ds_bss *)req->pbuf;
744 bss->sub_command = MLAN_OID_BSS_MAC_ADDR;
745 memcpy(&bss->param.mac_addr, priv->current_addr,
746 sizeof(mlan_802_11_mac_addr));
747 req->req_id = MLAN_IOCTL_BSS;
748 req->action = MLAN_ACT_SET;
749
750 /* Send IOCTL request to MLAN */
751 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
752 if (status == MLAN_STATUS_SUCCESS) {
753 memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN);
754 HEXDUMP("priv->MacAddr:", priv->current_addr, ETH_ALEN);
755 } else {
756 PRINTM(MERROR,
757 "set mac address failed! status=%d, error_code=0x%x\n",
758 status, req->status_code);
759 }
760 done:
761 if (status != MLAN_STATUS_PENDING)
762 kfree(req);
763 LEAVE();
764 return status;
765 }
766
767 /**
768 * @brief Send multicast list request to MLAN
769 *
770 * @param priv A pointer to moal_private structure
771 * @param dev A pointer to net_device structure
772 *
773 * @return N/A
774 */
775 void
woal_request_set_multicast_list(moal_private * priv,struct net_device * dev)776 woal_request_set_multicast_list(moal_private *priv, struct net_device *dev)
777 {
778 mlan_ioctl_req *req = NULL;
779 mlan_ds_bss *bss = NULL;
780 mlan_status status;
781 int mc_count = 0;
782
783 ENTER();
784
785 /* Allocate an IOCTL request buffer */
786 req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
787 if (req == NULL) {
788 PRINTM(MERROR, "%s:Fail to allocate ioctl req buffer\n",
789 __func__);
790 goto done;
791 }
792
793 /* Fill request buffer */
794 bss = (mlan_ds_bss *)req->pbuf;
795 bss->sub_command = MLAN_OID_BSS_MULTICAST_LIST;
796 req->req_id = MLAN_IOCTL_BSS;
797 req->action = MLAN_ACT_SET;
798 if (dev->flags & IFF_PROMISC) {
799 bss->param.multicast_list.mode = MLAN_PROMISC_MODE;
800 } else if (dev->flags & IFF_ALLMULTI) {
801 bss->param.multicast_list.mode = MLAN_ALL_MULTI_MODE;
802 } else {
803 bss->param.multicast_list.mode = MLAN_MULTICAST_MODE;
804 mc_count =
805 woal_copy_all_mc_list(priv->phandle,
806 &bss->param.multicast_list);
807 if (mc_count > MLAN_MAX_MULTICAST_LIST_SIZE)
808 bss->param.multicast_list.mode = MLAN_ALL_MULTI_MODE;
809 }
810
811 /* Send IOCTL request to MLAN */
812 status = woal_request_ioctl(priv, req, MOAL_NO_WAIT);
813 if (status != MLAN_STATUS_PENDING)
814 kfree(req);
815 done:
816 LEAVE();
817 return;
818 }
819
820 /**
821 * @brief Send deauth command to MLAN
822 *
823 * @param priv A pointer to moal_private structure
824 * @param wait_option Wait option
825 * @param mac MAC address to deauthenticate
826 * @param reason_code reason code to deauthenticate
827 *
828 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
829 */
830 mlan_status
woal_disconnect(moal_private * priv,t_u8 wait_option,t_u8 * mac,t_u16 reason_code)831 woal_disconnect(moal_private *priv, t_u8 wait_option, t_u8 *mac,
832 t_u16 reason_code)
833 {
834 mlan_ioctl_req *req = NULL;
835 mlan_ds_bss *bss = NULL;
836 mlan_status status;
837
838 ENTER();
839
840 /* Allocate an IOCTL request buffer */
841 req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
842 if (req == NULL) {
843 status = MLAN_STATUS_FAILURE;
844 goto done;
845 }
846
847 /* Fill request buffer */
848 bss = (mlan_ds_bss *)req->pbuf;
849 bss->sub_command = MLAN_OID_BSS_STOP;
850 if (mac)
851 memcpy(&bss->param.deauth_param.mac_addr, mac,
852 sizeof(mlan_802_11_mac_addr));
853 bss->param.deauth_param.reason_code = reason_code;
854 req->req_id = MLAN_IOCTL_BSS;
855 req->action = MLAN_ACT_SET;
856
857 /* Send IOCTL request to MLAN */
858 status = woal_request_ioctl(priv, req, wait_option);
859
860 done:
861 if (status != MLAN_STATUS_PENDING)
862 kfree(req);
863 #ifdef REASSOCIATION
864 priv->reassoc_required = MFALSE;
865 #endif /* REASSOCIATION */
866 LEAVE();
867 return status;
868 }
869
870 /**
871 * @brief Send bss_start command to MLAN
872 *
873 * @param priv A pointer to moal_private structure
874 * @param wait_option Wait option
875 * @param ssid_bssid A point to mlan_ssid_bssid structure
876 *
877 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
878 */
879 mlan_status
woal_bss_start(moal_private * priv,t_u8 wait_option,mlan_ssid_bssid * ssid_bssid)880 woal_bss_start(moal_private *priv, t_u8 wait_option,
881 mlan_ssid_bssid *ssid_bssid)
882 {
883 mlan_ioctl_req *req = NULL;
884 mlan_ds_bss *bss = NULL;
885 mlan_status status;
886
887 ENTER();
888
889 /* Stop the O.S. TX queue When we are roaming */
890 woal_stop_queue(priv->netdev);
891 if (priv->media_connected == MFALSE) {
892 if (netif_carrier_ok(priv->netdev))
893 netif_carrier_off(priv->netdev);
894 }
895
896 /* Allocate an IOCTL request buffer */
897 req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
898 if (req == NULL) {
899 status = MLAN_STATUS_FAILURE;
900 goto done;
901 }
902
903 /* Fill request buffer */
904 bss = (mlan_ds_bss *)req->pbuf;
905 bss->sub_command = MLAN_OID_BSS_START;
906 if (ssid_bssid)
907 memcpy(&bss->param.ssid_bssid, ssid_bssid,
908 sizeof(mlan_ssid_bssid));
909 req->req_id = MLAN_IOCTL_BSS;
910 req->action = MLAN_ACT_SET;
911
912 /* Send IOCTL request to MLAN */
913 status = woal_request_ioctl(priv, req, wait_option);
914 #ifdef STA_CFG80211
915 #ifdef STA_SUPPORT
916 priv->assoc_status = req->status_code;
917 #endif
918 #endif
919 done:
920 if (status != MLAN_STATUS_PENDING)
921 kfree(req);
922 LEAVE();
923 return status;
924 }
925
926 /**
927 * @brief Get BSS info
928 *
929 * @param priv A pointer to moal_private structure
930 * @param wait_option Wait option
931 * @param bss_info A pointer to mlan_bss_info structure
932 *
933 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
934 */
935 mlan_status
woal_get_bss_info(moal_private * priv,t_u8 wait_option,mlan_bss_info * bss_info)936 woal_get_bss_info(moal_private *priv, t_u8 wait_option, mlan_bss_info *bss_info)
937 {
938 mlan_ioctl_req *req = NULL;
939 mlan_ds_get_info *info = NULL;
940 mlan_status status = MLAN_STATUS_SUCCESS;
941 ENTER();
942
943 /* Allocate an IOCTL request buffer */
944 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
945 if (req == NULL) {
946 PRINTM(MERROR,
947 "Fail to allocate the buffer for get bss_info\n");
948 status = MLAN_STATUS_FAILURE;
949 goto done;
950 }
951
952 /* Fill request buffer */
953 info = (mlan_ds_get_info *)req->pbuf;
954 info->sub_command = MLAN_OID_GET_BSS_INFO;
955 req->req_id = MLAN_IOCTL_GET_INFO;
956 req->action = MLAN_ACT_GET;
957
958 /* Send IOCTL request to MLAN */
959 status = woal_request_ioctl(priv, req, wait_option);
960 if (status == MLAN_STATUS_SUCCESS) {
961 if (bss_info)
962 memcpy(bss_info, &info->param.bss_info,
963 sizeof(mlan_bss_info));
964 }
965 done:
966 if (status != MLAN_STATUS_PENDING)
967 kfree(req);
968 LEAVE();
969 return status;
970 }
971
972 /**
973 * @brief Set/Get generic IE
974 *
975 * @param priv A pointer to moal_private structure
976 * @param action Action set or get
977 * @param ie Information element
978 * @param ie_len Length of the IE
979 * @param wait_option wait option
980 *
981 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
982 */
983 mlan_status
woal_set_get_gen_ie(moal_private * priv,t_u32 action,t_u8 * ie,int * ie_len,t_u8 wait_option)984 woal_set_get_gen_ie(moal_private *priv, t_u32 action,
985 t_u8 *ie, int *ie_len, t_u8 wait_option)
986 {
987 mlan_status ret = MLAN_STATUS_SUCCESS;
988 mlan_ds_misc_cfg *misc = NULL;
989 mlan_ioctl_req *req = NULL;
990
991 ENTER();
992
993 if ((action == MLAN_ACT_GET) && (ie == NULL || ie_len == NULL)) {
994 ret = MLAN_STATUS_FAILURE;
995 goto done;
996 }
997
998 if (action == MLAN_ACT_SET && *ie_len > MAX_IE_SIZE) {
999 ret = MLAN_STATUS_FAILURE;
1000 goto done;
1001 }
1002
1003 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1004 if (req == NULL) {
1005 ret = MLAN_STATUS_FAILURE;
1006 goto done;
1007 }
1008
1009 misc = (mlan_ds_misc_cfg *)req->pbuf;
1010 misc->sub_command = MLAN_OID_MISC_GEN_IE;
1011 req->req_id = MLAN_IOCTL_MISC_CFG;
1012 req->action = action;
1013 misc->param.gen_ie.type = MLAN_IE_TYPE_GEN_IE;
1014
1015 if (action == MLAN_ACT_SET) {
1016 misc->param.gen_ie.len = *ie_len;
1017 if (*ie_len)
1018 memcpy(misc->param.gen_ie.ie_data, ie, *ie_len);
1019 }
1020
1021 ret = woal_request_ioctl(priv, req, wait_option);
1022 if (ret != MLAN_STATUS_SUCCESS)
1023 goto done;
1024
1025 if (action == MLAN_ACT_GET) {
1026 *ie_len = misc->param.gen_ie.len;
1027 if (*ie_len)
1028 memcpy(ie, misc->param.gen_ie.ie_data, *ie_len);
1029 }
1030
1031 done:
1032 if (ret != MLAN_STATUS_PENDING)
1033 kfree(req);
1034 LEAVE();
1035 return ret;
1036 }
1037
1038 #ifdef STA_SUPPORT
1039 /**
1040 * @brief Set/Get retry count
1041 *
1042 * @param priv A pointer to moal_private structure
1043 * @param action Action set or get
1044 * @param wait_option Wait option
1045 * @param value Retry value
1046 *
1047 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
1048 */
1049 mlan_status
woal_set_get_retry(moal_private * priv,t_u32 action,t_u8 wait_option,int * value)1050 woal_set_get_retry(moal_private *priv, t_u32 action,
1051 t_u8 wait_option, int *value)
1052 {
1053 mlan_ioctl_req *req = NULL;
1054 mlan_ds_snmp_mib *mib = NULL;
1055 mlan_status ret = MLAN_STATUS_SUCCESS;
1056 ENTER();
1057
1058 /* Allocate an IOCTL request buffer */
1059 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
1060 if (req == NULL) {
1061 ret = MLAN_STATUS_FAILURE;
1062 goto done;
1063 }
1064
1065 /* Fill request buffer */
1066 mib = (mlan_ds_snmp_mib *)req->pbuf;
1067 mib->sub_command = MLAN_OID_SNMP_MIB_RETRY_COUNT;
1068 req->req_id = MLAN_IOCTL_SNMP_MIB;
1069 req->action = action;
1070
1071 if (action == MLAN_ACT_SET) {
1072 if (*value < MLAN_TX_RETRY_MIN || *value > MLAN_TX_RETRY_MAX) {
1073 ret = MLAN_STATUS_FAILURE;
1074 goto done;
1075 }
1076 mib->param.retry_count = *value;
1077 }
1078
1079 /* Send IOCTL request to MLAN */
1080 ret = woal_request_ioctl(priv, req, wait_option);
1081 if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
1082 *value = mib->param.retry_count;
1083 #ifdef STA_CFG80211
1084 /* If set is invoked from other than iw i.e iwconfig,
1085 * wiphy retry count should be updated as well */
1086 if (IS_STA_CFG80211(cfg80211_wext) && priv->wdev && priv->wdev->wiphy &&
1087 (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1088 (action == MLAN_ACT_SET)) {
1089 priv->wdev->wiphy->retry_long = (t_u8)*value;
1090 priv->wdev->wiphy->retry_short = (t_u8)*value;
1091 }
1092 #endif
1093
1094 done:
1095 if (ret != MLAN_STATUS_PENDING)
1096 kfree(req);
1097 LEAVE();
1098 return ret;
1099 }
1100
1101 /**
1102 * @brief Set/Get RTS threshold
1103 *
1104 * @param priv A pointer to moal_private structure
1105 * @param action Action set or get
1106 * @param wait_option Wait option
1107 * @param value RTS threshold value
1108 *
1109 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
1110 */
1111 mlan_status
woal_set_get_rts(moal_private * priv,t_u32 action,t_u8 wait_option,int * value)1112 woal_set_get_rts(moal_private *priv, t_u32 action, t_u8 wait_option, int *value)
1113 {
1114 mlan_ioctl_req *req = NULL;
1115 mlan_ds_snmp_mib *mib = NULL;
1116 mlan_status ret = MLAN_STATUS_SUCCESS;
1117 ENTER();
1118
1119 /* Allocate an IOCTL request buffer */
1120 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
1121 if (req == NULL) {
1122 ret = MLAN_STATUS_FAILURE;
1123 goto done;
1124 }
1125
1126 /* Fill request buffer */
1127 mib = (mlan_ds_snmp_mib *)req->pbuf;
1128 mib->sub_command = MLAN_OID_SNMP_MIB_RTS_THRESHOLD;
1129 req->req_id = MLAN_IOCTL_SNMP_MIB;
1130 req->action = action;
1131
1132 if (action == MLAN_ACT_SET) {
1133 if (*value < MLAN_RTS_MIN_VALUE || *value > MLAN_RTS_MAX_VALUE) {
1134 ret = MLAN_STATUS_FAILURE;
1135 goto done;
1136 }
1137 mib->param.rts_threshold = *value;
1138 }
1139
1140 /* Send IOCTL request to MLAN */
1141 ret = woal_request_ioctl(priv, req, wait_option);
1142 if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
1143 *value = mib->param.rts_threshold;
1144 #ifdef STA_CFG80211
1145 /* If set is invoked from other than iw i.e iwconfig,
1146 * wiphy RTS threshold should be updated as well */
1147 if (IS_STA_CFG80211(cfg80211_wext) && priv->wdev && priv->wdev->wiphy &&
1148 (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1149 (action == MLAN_ACT_SET))
1150 priv->wdev->wiphy->rts_threshold = *value;
1151 #endif
1152
1153 done:
1154 if (ret != MLAN_STATUS_PENDING)
1155 kfree(req);
1156 LEAVE();
1157 return ret;
1158 }
1159
1160 /**
1161 * @brief Set/Get Fragment threshold
1162 *
1163 * @param priv A pointer to moal_private structure
1164 * @param action Action set or get
1165 * @param wait_option Wait option
1166 * @param value Fragment threshold value
1167 *
1168 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
1169 */
1170 mlan_status
woal_set_get_frag(moal_private * priv,t_u32 action,t_u8 wait_option,int * value)1171 woal_set_get_frag(moal_private *priv, t_u32 action,
1172 t_u8 wait_option, int *value)
1173 {
1174 mlan_ioctl_req *req = NULL;
1175 mlan_ds_snmp_mib *mib = NULL;
1176 mlan_status ret = MLAN_STATUS_SUCCESS;
1177 ENTER();
1178
1179 /* Allocate an IOCTL request buffer */
1180 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
1181 if (req == NULL) {
1182 ret = MLAN_STATUS_FAILURE;
1183 goto done;
1184 }
1185
1186 /* Fill request buffer */
1187 mib = (mlan_ds_snmp_mib *)req->pbuf;
1188 mib->sub_command = MLAN_OID_SNMP_MIB_FRAG_THRESHOLD;
1189 req->req_id = MLAN_IOCTL_SNMP_MIB;
1190 req->action = action;
1191
1192 if (action == MLAN_ACT_SET) {
1193 if (*value < MLAN_FRAG_MIN_VALUE ||
1194 *value > MLAN_FRAG_MAX_VALUE) {
1195 ret = MLAN_STATUS_FAILURE;
1196 goto done;
1197 }
1198 mib->param.frag_threshold = *value;
1199 }
1200
1201 /* Send IOCTL request to MLAN */
1202 ret = woal_request_ioctl(priv, req, wait_option);
1203 if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
1204 *value = mib->param.frag_threshold;
1205 #ifdef STA_CFG80211
1206 /* If set is invoked from other than iw i.e iwconfig,
1207 * wiphy fragment threshold should be updated as well */
1208 if (IS_STA_CFG80211(cfg80211_wext) && priv->wdev && priv->wdev->wiphy &&
1209 (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1210 (action == MLAN_ACT_SET))
1211 priv->wdev->wiphy->frag_threshold = *value;
1212 #endif
1213
1214 done:
1215 if (ret != MLAN_STATUS_PENDING)
1216 kfree(req);
1217 LEAVE();
1218 return ret;
1219 }
1220
1221 /**
1222 * @brief Set/Get TX power
1223 *
1224 * @param priv A pointer to moal_private structure
1225 * @param action Action set or get
1226 * @param power_cfg A pinter to mlan_power_cfg_t structure
1227 *
1228 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
1229 */
1230 mlan_status
woal_set_get_tx_power(moal_private * priv,t_u32 action,mlan_power_cfg_t * power_cfg)1231 woal_set_get_tx_power(moal_private *priv,
1232 t_u32 action, mlan_power_cfg_t *power_cfg)
1233 {
1234 mlan_ds_power_cfg *pcfg = NULL;
1235 mlan_ioctl_req *req = NULL;
1236 mlan_status ret = MLAN_STATUS_SUCCESS;
1237 ENTER();
1238
1239 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_power_cfg));
1240 if (req == NULL) {
1241 ret = MLAN_STATUS_FAILURE;
1242 goto done;
1243 }
1244 pcfg = (mlan_ds_power_cfg *)req->pbuf;
1245 pcfg->sub_command = MLAN_OID_POWER_CFG;
1246 req->req_id = MLAN_IOCTL_POWER_CFG;
1247 req->action = action;
1248 if (action == MLAN_ACT_SET && power_cfg)
1249 memcpy(&pcfg->param.power_cfg, power_cfg,
1250 sizeof(mlan_power_cfg_t));
1251
1252 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1253 if (ret != MLAN_STATUS_SUCCESS)
1254 goto done;
1255
1256 if (ret == MLAN_STATUS_SUCCESS && power_cfg)
1257 memcpy(power_cfg, &pcfg->param.power_cfg,
1258 sizeof(mlan_power_cfg_t));
1259
1260 done:
1261 if (ret != MLAN_STATUS_PENDING)
1262 kfree(req);
1263 LEAVE();
1264 return ret;
1265 }
1266
1267 /**
1268 * @brief Set/Get IEEE power management
1269 *
1270 * @param priv A pointer to moal_private structure
1271 * @param action Action set or get
1272 * @param disabled A pointer to disabled flag
1273 * @param power_type IEEE power type
1274 * @param wait_option wait option
1275 *
1276 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
1277 */
1278 mlan_status
woal_set_get_power_mgmt(moal_private * priv,t_u32 action,int * disabled,int power_type,t_u8 wait_option)1279 woal_set_get_power_mgmt(moal_private *priv,
1280 t_u32 action, int *disabled, int power_type,
1281 t_u8 wait_option)
1282 {
1283 mlan_status ret = MLAN_STATUS_SUCCESS;
1284 mlan_ioctl_req *req = NULL;
1285 mlan_ds_pm_cfg *pm_cfg = NULL;
1286
1287 ENTER();
1288
1289 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
1290 if (req == NULL) {
1291 ret = MLAN_STATUS_FAILURE;
1292 goto done;
1293 }
1294 pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
1295 pm_cfg->sub_command = MLAN_OID_PM_CFG_IEEE_PS;
1296 req->req_id = MLAN_IOCTL_PM_CFG;
1297 req->action = action;
1298
1299 if (action == MLAN_ACT_SET) {
1300 PRINTM(MINFO, "PS_MODE set power disabled=%d power type=%#x\n",
1301 *disabled, power_type);
1302 if (*disabled)
1303 pm_cfg->param.ps_mode = 0;
1304 else {
1305 /* Check not support case only (vwrq->disabled == FALSE) */
1306 if ((power_type & MW_POWER_TYPE) == MW_POWER_TIMEOUT) {
1307 PRINTM(MERROR,
1308 "Setting power timeout is not supported\n");
1309 ret = MLAN_STATUS_FAILURE;
1310 goto done;
1311 } else if ((power_type & MW_POWER_TYPE) ==
1312 MW_POWER_PERIOD) {
1313 PRINTM(MERROR,
1314 "Setting power period is not supported\n");
1315 ret = MLAN_STATUS_FAILURE;
1316 goto done;
1317 }
1318 pm_cfg->param.ps_mode = 1;
1319 }
1320 }
1321
1322 ret = woal_request_ioctl(priv, req, wait_option);
1323 if (ret != MLAN_STATUS_SUCCESS)
1324 goto done;
1325
1326 if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
1327 *disabled = pm_cfg->param.ps_mode;
1328
1329 #ifdef STA_CFG80211
1330 /* If set is invoked from other than iw i.e iwconfig,
1331 * wiphy IEEE power save mode should be updated */
1332 if (IS_STA_CFG80211(cfg80211_wext) && priv->wdev &&
1333 (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1334 (action == MLAN_ACT_SET)) {
1335 if (*disabled)
1336 priv->wdev->ps = MFALSE;
1337 else
1338 priv->wdev->ps = MTRUE;
1339 }
1340 #endif
1341
1342 done:
1343 if (ret != MLAN_STATUS_PENDING)
1344 kfree(req);
1345 LEAVE();
1346 return ret;
1347 }
1348
1349 /**
1350 * @brief Set region code
1351 *
1352 * @param priv A pointer to moal_private structure
1353 * @param region A pointer to region string
1354 *
1355 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
1356 */
1357 mlan_status
woal_set_region_code(moal_private * priv,char * region)1358 woal_set_region_code(moal_private *priv, char *region)
1359 {
1360 mlan_status ret = MLAN_STATUS_SUCCESS;
1361 mlan_ds_misc_cfg *cfg = NULL;
1362 mlan_ioctl_req *req = NULL;
1363
1364 ENTER();
1365 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1366 if (req == NULL) {
1367 ret = MLAN_STATUS_FAILURE;
1368 goto done;
1369 }
1370 cfg = (mlan_ds_misc_cfg *)req->pbuf;
1371 cfg->sub_command = MLAN_OID_MISC_REGION;
1372 req->req_id = MLAN_IOCTL_MISC_CFG;
1373 req->action = MLAN_ACT_SET;
1374 cfg->param.region_code = region_string_2_region_code(region);
1375 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1376
1377 done:
1378 if (ret != MLAN_STATUS_PENDING)
1379 kfree(req);
1380 LEAVE();
1381 return ret;
1382 }
1383
1384 /**
1385 * @brief Set/Get data rate
1386 *
1387 * @param priv A pointer to moal_private structure
1388 * @param action Action set or get
1389 * @param datarate A pointer to mlan_rate_cfg_t structure
1390 *
1391 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
1392 */
1393 mlan_status
woal_set_get_data_rate(moal_private * priv,t_u8 action,mlan_rate_cfg_t * datarate)1394 woal_set_get_data_rate(moal_private *priv,
1395 t_u8 action, mlan_rate_cfg_t *datarate)
1396 {
1397 mlan_status ret = MLAN_STATUS_SUCCESS;
1398 mlan_ds_rate *rate = NULL;
1399 mlan_ioctl_req *req = NULL;
1400
1401 ENTER();
1402
1403 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
1404 if (req == NULL) {
1405 ret = MLAN_STATUS_FAILURE;
1406 goto done;
1407 }
1408
1409 rate = (mlan_ds_rate *)req->pbuf;
1410 rate->param.rate_cfg.rate_type = MLAN_RATE_VALUE;
1411 rate->sub_command = MLAN_OID_RATE_CFG;
1412 req->req_id = MLAN_IOCTL_RATE;
1413 req->action = action;
1414
1415 if (datarate && (action == MLAN_ACT_SET))
1416 memcpy(&rate->param.rate_cfg, datarate,
1417 sizeof(mlan_rate_cfg_t));
1418
1419 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1420 if (ret == MLAN_STATUS_SUCCESS && datarate && action == MLAN_ACT_GET)
1421 memcpy(datarate, &rate->param.rate_cfg,
1422 sizeof(mlan_rate_cfg_t));
1423
1424 done:
1425 if (ret != MLAN_STATUS_PENDING)
1426 kfree(req);
1427 LEAVE();
1428 return ret;
1429 }
1430
1431 /**
1432 * @brief Get assoc_resp buffer
1433 *
1434 * @param priv A pointer to moal_private structure
1435 * @param assoc_rsp A pointer to mlan_ds_misc_assoc_rsp structure
1436 * @param wait_option wait option
1437 *
1438 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
1439 */
1440 mlan_status
woal_get_assoc_rsp(moal_private * priv,mlan_ds_misc_assoc_rsp * assoc_rsp,t_u8 wait_option)1441 woal_get_assoc_rsp(moal_private *priv, mlan_ds_misc_assoc_rsp *assoc_rsp,
1442 t_u8 wait_option)
1443 {
1444 mlan_status ret = MLAN_STATUS_SUCCESS;
1445 mlan_ds_misc_cfg *misc = NULL;
1446 mlan_ioctl_req *req = NULL;
1447
1448 ENTER();
1449
1450 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1451 if (req == NULL) {
1452 PRINTM(MERROR, "Fail to allocate buffer for get assoc resp\n");
1453 ret = MLAN_STATUS_FAILURE;
1454 goto done;
1455 }
1456
1457 req->req_id = MLAN_IOCTL_MISC_CFG;
1458 misc = (pmlan_ds_misc_cfg)req->pbuf;
1459 misc->sub_command = MLAN_OID_MISC_ASSOC_RSP;
1460 req->action = MLAN_ACT_GET;
1461
1462 ret = woal_request_ioctl(priv, req, wait_option);
1463 if (ret == MLAN_STATUS_SUCCESS && assoc_rsp)
1464 memcpy(assoc_rsp, &misc->param.assoc_resp,
1465 sizeof(mlan_ds_misc_assoc_rsp));
1466
1467 done:
1468 if (ret != MLAN_STATUS_PENDING)
1469 kfree(req);
1470 LEAVE();
1471 return ret;
1472 }
1473 #endif
1474
1475 /**
1476 * @brief Send get FW info request to MLAN
1477 *
1478 * @param priv A pointer to moal_private structure
1479 * @param wait_option Wait option
1480 * @param fw_info FW information
1481 *
1482 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
1483 */
1484 mlan_status
woal_request_get_fw_info(moal_private * priv,t_u8 wait_option,mlan_fw_info * fw_info)1485 woal_request_get_fw_info(moal_private *priv, t_u8 wait_option,
1486 mlan_fw_info *fw_info)
1487 {
1488 mlan_ioctl_req *req = NULL;
1489 mlan_ds_get_info *info;
1490 mlan_status status;
1491 ENTER();
1492 memset(priv->current_addr, 0xff, ETH_ALEN);
1493
1494 /* Allocate an IOCTL request buffer */
1495 req = (mlan_ioctl_req *)
1496 woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
1497 if (req == NULL) {
1498 status = MLAN_STATUS_FAILURE;
1499 goto done;
1500 }
1501
1502 /* Fill request buffer */
1503 info = (mlan_ds_get_info *)req->pbuf;
1504 req->req_id = MLAN_IOCTL_GET_INFO;
1505 req->action = MLAN_ACT_GET;
1506 info->sub_command = MLAN_OID_GET_FW_INFO;
1507
1508 /* Send IOCTL request to MLAN */
1509 status = woal_request_ioctl(priv, req, wait_option);
1510 if (status == MLAN_STATUS_SUCCESS) {
1511 priv->phandle->fw_release_number = info->param.fw_info.fw_ver;
1512 priv->phandle->fw_ecsa_enable = info->param.fw_info.ecsa_enable;
1513 priv->phandle->fw_getlog_enable =
1514 info->param.fw_info.getlog_enable;
1515 priv->phandle->fw_roaming_support =
1516 info->param.fw_info.fw_roaming_support;
1517 if (priv->current_addr[0] == 0xff)
1518 memcpy(priv->current_addr,
1519 &info->param.fw_info.mac_addr,
1520 sizeof(mlan_802_11_mac_addr));
1521 memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN);
1522 if (fw_info)
1523 memcpy(fw_info, &info->param.fw_info,
1524 sizeof(mlan_fw_info));
1525 DBG_HEXDUMP(MCMD_D, "mac", priv->current_addr, 6);
1526 } else
1527 PRINTM(MERROR,
1528 "get fw info failed! status=%d, error_code=0x%x\n",
1529 status, req->status_code);
1530 done:
1531 if (status != MLAN_STATUS_PENDING)
1532 kfree(req);
1533 LEAVE();
1534 return status;
1535 }
1536
1537 #ifdef STA_SUPPORT
1538 /**
1539 * @brief Send get ext cap info request to MLAN
1540 *
1541 * @param priv A pointer to moal_private structure
1542 * @param buf data buffer
1543 * @param len data buffer length
1544 *
1545 * @return number of bytes of extended capability -- success, otherwise error
1546 */
1547 int
woal_request_extcap(moal_private * priv,t_u8 * buf,t_u8 len)1548 woal_request_extcap(moal_private *priv, t_u8 *buf, t_u8 len)
1549 {
1550 int ret = 0;
1551 mlan_ioctl_req *req = NULL;
1552 mlan_ds_misc_cfg *cfg = NULL;
1553 mlan_status status = MLAN_STATUS_SUCCESS;
1554
1555 ENTER();
1556 if (buf == NULL || len <= 0 || len < sizeof(ExtCap_t)) {
1557 ret = -EINVAL;
1558 goto out;
1559 }
1560 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1561 if (req == NULL) {
1562 ret = -ENOMEM;
1563 goto out;
1564 }
1565 cfg = (mlan_ds_misc_cfg *)req->pbuf;
1566 cfg->sub_command = MLAN_OID_MISC_EXT_CAP_CFG;
1567 req->req_id = MLAN_IOCTL_MISC_CFG;
1568 req->action = MLAN_ACT_GET;
1569 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1570 if (status != MLAN_STATUS_SUCCESS) {
1571 ret = -EFAULT;
1572 goto out;
1573 }
1574 memset(buf, 0, len);
1575 memcpy(buf, &cfg->param.ext_cap, sizeof(ExtCap_t));
1576 ret = sizeof(ExtCap_t);
1577 out:
1578 if (status != MLAN_STATUS_PENDING)
1579 kfree(req);
1580 LEAVE();
1581 return ret;
1582 }
1583 #endif
1584
1585 #ifdef PROC_DEBUG
1586 /**
1587 * @brief Get debug info
1588 *
1589 * @param priv A pointer to moal_private structure
1590 * @param wait_option Wait option
1591 * @param debug_info A pointer to mlan_debug_info structure
1592 *
1593 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
1594 */
1595 mlan_status
woal_get_debug_info(moal_private * priv,t_u8 wait_option,mlan_debug_info * debug_info)1596 woal_get_debug_info(moal_private *priv, t_u8 wait_option,
1597 mlan_debug_info *debug_info)
1598 {
1599 int ret = 0;
1600 mlan_ioctl_req *req = NULL;
1601 mlan_ds_get_info *info = NULL;
1602 mlan_status status = MLAN_STATUS_SUCCESS;
1603 ENTER();
1604
1605 /* Allocate an IOCTL request buffer */
1606 req = woal_alloc_mlan_ioctl_req(sizeof(t_u32) +
1607 sizeof(mlan_debug_info));
1608 if (req == NULL) {
1609 ret = -ENOMEM;
1610 goto done;
1611 }
1612
1613 /* Fill request buffer */
1614 info = (mlan_ds_get_info *)req->pbuf;
1615 info->sub_command = MLAN_OID_GET_DEBUG_INFO;
1616 req->req_id = MLAN_IOCTL_GET_INFO;
1617 req->action = MLAN_ACT_GET;
1618
1619 /* Send IOCTL request to MLAN */
1620 status = woal_request_ioctl(priv, req, wait_option);
1621 if (status == MLAN_STATUS_SUCCESS) {
1622 if (debug_info) {
1623 memcpy(debug_info, &info->param.debug_info,
1624 sizeof(mlan_debug_info));
1625 }
1626 }
1627 done:
1628 if (status != MLAN_STATUS_PENDING)
1629 kfree(req);
1630 LEAVE();
1631 return status;
1632 }
1633 #endif /* PROC_DEBUG */
1634
1635 #if defined(STA_WEXT) || defined(UAP_WEXT)
1636 /**
1637 * @brief host command ioctl function
1638 *
1639 * @param priv A pointer to moal_private structure
1640 * @param wrq A pointer to iwreq structure
1641 * @return 0 --success, otherwise fail
1642 */
1643 int
woal_host_command(moal_private * priv,struct iwreq * wrq)1644 woal_host_command(moal_private *priv, struct iwreq *wrq)
1645 {
1646 HostCmd_Header cmd_header;
1647 int ret = 0;
1648 mlan_ds_misc_cfg *misc = NULL;
1649 mlan_ioctl_req *req = NULL;
1650 mlan_status status = MLAN_STATUS_SUCCESS;
1651
1652 ENTER();
1653
1654 /* Sanity check */
1655 if (wrq->u.data.pointer == NULL) {
1656 PRINTM(MERROR, "hostcmd IOCTL corrupt data\n");
1657 ret = -EINVAL;
1658 goto done;
1659 }
1660 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1661 if (req == NULL) {
1662 ret = -ENOMEM;
1663 goto done;
1664 }
1665 misc = (mlan_ds_misc_cfg *)req->pbuf;
1666 memset(&cmd_header, 0, sizeof(cmd_header));
1667
1668 /* get command header */
1669 if (copy_from_user
1670 (&cmd_header, wrq->u.data.pointer, sizeof(HostCmd_Header))) {
1671 PRINTM(MERROR, "copy from user failed: Host command header\n");
1672 ret = -EFAULT;
1673 goto done;
1674 }
1675 misc->param.hostcmd.len = woal_le16_to_cpu(cmd_header.size);
1676
1677 PRINTM(MINFO, "Host command len = %u\n", misc->param.hostcmd.len);
1678
1679 if (!misc->param.hostcmd.len ||
1680 misc->param.hostcmd.len > MLAN_SIZE_OF_CMD_BUFFER) {
1681 PRINTM(MERROR, "Invalid data buffer length\n");
1682 ret = -EINVAL;
1683 goto done;
1684 }
1685
1686 /* get the whole command from user */
1687 if (copy_from_user
1688 (misc->param.hostcmd.cmd, wrq->u.data.pointer,
1689 woal_le16_to_cpu(cmd_header.size))) {
1690 PRINTM(MERROR, "copy from user failed\n");
1691 ret = -EFAULT;
1692 goto done;
1693 }
1694 misc->sub_command = MLAN_OID_MISC_HOST_CMD;
1695 req->req_id = MLAN_IOCTL_MISC_CFG;
1696
1697 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1698 if (status != MLAN_STATUS_SUCCESS) {
1699 ret = -EFAULT;
1700 goto done;
1701 }
1702 if (copy_to_user
1703 (wrq->u.data.pointer, (t_u8 *)misc->param.hostcmd.cmd,
1704 misc->param.hostcmd.len)) {
1705 ret = -EFAULT;
1706 goto done;
1707 }
1708 wrq->u.data.length = misc->param.hostcmd.len;
1709 done:
1710 if (status != MLAN_STATUS_PENDING)
1711 kfree(req);
1712 LEAVE();
1713 return ret;
1714 }
1715 #endif
1716
1717 #if defined(WIFI_DIRECT_SUPPORT) || defined(UAP_SUPPORT)
1718 /**
1719 * @brief host command ioctl function
1720 *
1721 * @param dev A pointer to net_device structure
1722 * @param req A pointer to ifreq structure
1723 * @return 0 --success, otherwise fail
1724 */
1725 /********* format of ifr_data *************/
1726 /* buf_len + Hostcmd_body */
1727 /* buf_len: 4 bytes */
1728 /* the length of the buf which */
1729 /* can be used to return data */
1730 /* to application */
1731 /* Hostcmd_body */
1732 /*******************************************/
1733 int
woal_hostcmd_ioctl(struct net_device * dev,struct ifreq * req)1734 woal_hostcmd_ioctl(struct net_device *dev, struct ifreq *req)
1735 {
1736 moal_private *priv = (moal_private *)netdev_priv(dev);
1737 t_u32 buf_len = 0;
1738 HostCmd_Header cmd_header;
1739 int ret = 0;
1740 mlan_ds_misc_cfg *misc = NULL;
1741 mlan_ioctl_req *ioctl_req = NULL;
1742 mlan_status status = MLAN_STATUS_SUCCESS;
1743
1744 ENTER();
1745
1746 /* Sanity check */
1747 if (req->ifr_data == NULL) {
1748 PRINTM(MERROR, "uap_hostcmd_ioctl() corrupt data\n");
1749 ret = -EFAULT;
1750 goto done;
1751 }
1752
1753 if (copy_from_user(&buf_len, req->ifr_data, sizeof(buf_len))) {
1754 PRINTM(MERROR, "Copy from user failed\n");
1755 ret = -EFAULT;
1756 goto done;
1757 }
1758
1759 memset(&cmd_header, 0, sizeof(cmd_header));
1760
1761 /* get command header */
1762 if (copy_from_user
1763 (&cmd_header, req->ifr_data + sizeof(buf_len),
1764 sizeof(HostCmd_Header))) {
1765 PRINTM(MERROR, "Copy from user failed\n");
1766 ret = -EFAULT;
1767 goto done;
1768 }
1769
1770 PRINTM(MINFO, "Host command len = %d\n",
1771 woal_le16_to_cpu(cmd_header.size));
1772
1773 if (woal_le16_to_cpu(cmd_header.size) > MLAN_SIZE_OF_CMD_BUFFER) {
1774 ret = -EINVAL;
1775 goto done;
1776 }
1777
1778 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1779 if (ioctl_req == NULL) {
1780 ret = -ENOMEM;
1781 goto done;
1782 }
1783 misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
1784
1785 misc->param.hostcmd.len = woal_le16_to_cpu(cmd_header.size);
1786
1787 /* get the whole command from user */
1788 if (copy_from_user
1789 (misc->param.hostcmd.cmd, req->ifr_data + sizeof(buf_len),
1790 misc->param.hostcmd.len)) {
1791 PRINTM(MERROR, "copy from user failed\n");
1792 ret = -EFAULT;
1793 goto done;
1794 }
1795 misc->sub_command = MLAN_OID_MISC_HOST_CMD;
1796 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
1797
1798 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1799 if (status != MLAN_STATUS_SUCCESS) {
1800 ret = -EFAULT;
1801 goto done;
1802 }
1803 if (misc->param.hostcmd.len > buf_len) {
1804 PRINTM(MERROR,
1805 "buf_len is too small, resp_len=%d, buf_len=%d\n",
1806 (int)misc->param.hostcmd.len, (int)buf_len);
1807 ret = -EFAULT;
1808 goto done;
1809 }
1810 if (copy_to_user
1811 (req->ifr_data + sizeof(buf_len), (t_u8 *)misc->param.hostcmd.cmd,
1812 misc->param.hostcmd.len)) {
1813 ret = -EFAULT;
1814 goto done;
1815 }
1816 done:
1817 if (status != MLAN_STATUS_PENDING)
1818 kfree(ioctl_req);
1819 LEAVE();
1820 return ret;
1821 }
1822 #endif
1823
1824 /**
1825 * @brief CUSTOM_IE ioctl handler
1826 *
1827 * @param dev A pointer to net_device structure
1828 * @param req A pointer to ifreq structure
1829 * @return 0 --success, otherwise fail
1830 */
1831 int
woal_custom_ie_ioctl(struct net_device * dev,struct ifreq * req)1832 woal_custom_ie_ioctl(struct net_device *dev, struct ifreq *req)
1833 {
1834 moal_private *priv = (moal_private *)netdev_priv(dev);
1835 mlan_ioctl_req *ioctl_req = NULL;
1836 mlan_ds_misc_cfg *misc = NULL;
1837 mlan_ds_misc_custom_ie *custom_ie = NULL;
1838 int ret = 0;
1839 mlan_status status = MLAN_STATUS_SUCCESS;
1840 gfp_t flag;
1841
1842 ENTER();
1843
1844 /* Sanity check */
1845 if (req->ifr_data == NULL) {
1846 PRINTM(MERROR, "woal_custom_ie_ioctl() corrupt data\n");
1847 ret = -EFAULT;
1848 goto done;
1849 }
1850
1851 flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
1852 custom_ie = kzalloc(sizeof(mlan_ds_misc_custom_ie), flag);
1853 if (!custom_ie) {
1854 ret = -ENOMEM;
1855 goto done;
1856 }
1857
1858 if (copy_from_user
1859 (custom_ie, req->ifr_data, sizeof(mlan_ds_misc_custom_ie))) {
1860 PRINTM(MERROR, "Copy from user failed\n");
1861 ret = -EFAULT;
1862 goto done;
1863 }
1864
1865 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1866 if (ioctl_req == NULL) {
1867 ret = -ENOMEM;
1868 goto done;
1869 }
1870
1871 misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
1872 misc->sub_command = MLAN_OID_MISC_CUSTOM_IE;
1873 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
1874 if ((custom_ie->len == 0)||(custom_ie->len ==
1875 sizeof(custom_ie->ie_data_list[0].
1876 ie_index)))
1877 ioctl_req->action = MLAN_ACT_GET;
1878 else
1879 ioctl_req->action = MLAN_ACT_SET;
1880
1881 memcpy(&misc->param.cust_ie, custom_ie, sizeof(mlan_ds_misc_custom_ie));
1882
1883 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1884 if (status != MLAN_STATUS_SUCCESS) {
1885 ret = -EFAULT;
1886 goto done;
1887 }
1888
1889 if (ioctl_req->action == MLAN_ACT_GET) {
1890 if (copy_to_user
1891 (req->ifr_data, &misc->param.cust_ie,
1892 sizeof(mlan_ds_misc_custom_ie))) {
1893 PRINTM(MERROR, "Copy to user failed!\n");
1894 ret = -EFAULT;
1895 goto done;
1896 }
1897 } else if (ioctl_req->status_code == MLAN_ERROR_IOCTL_FAIL) {
1898 /* send a separate error code to indicate error from driver */
1899 ret = EFAULT;
1900 }
1901
1902 done:
1903 if (status != MLAN_STATUS_PENDING)
1904 kfree(ioctl_req);
1905 kfree(custom_ie);
1906 LEAVE();
1907 return ret;
1908 }
1909
1910 /**
1911 * @brief send raw data packet ioctl function
1912 *
1913 * @param dev A pointer to net_device structure
1914 * @param req A pointer to ifreq structure
1915 * @return 0 --success, otherwise fail
1916 */
1917 int
woal_send_host_packet(struct net_device * dev,struct ifreq * req)1918 woal_send_host_packet(struct net_device *dev, struct ifreq *req)
1919 {
1920 moal_private *priv = (moal_private *)netdev_priv(dev);
1921 t_u32 packet_len = 0;
1922 int ret = 0;
1923 pmlan_buffer pmbuf = NULL;
1924 mlan_status status;
1925 IEEEtypes_ActionCategory_e *action_cat;
1926 t_u8 *action;
1927 struct tx_status_info *tx_info = NULL;
1928 struct sk_buff *skb = NULL;
1929 unsigned long flags;
1930 struct ieee80211_mgmt *mgmt_frame;
1931
1932 ENTER();
1933
1934 if (!priv || !priv->phandle) {
1935 PRINTM(MERROR, "priv or handle is NULL\n");
1936 ret = -EFAULT;
1937 goto done;
1938 }
1939
1940 /* Sanity check */
1941 if (req->ifr_data == NULL) {
1942 PRINTM(MERROR, "woal_send_host_packet() corrupt data\n");
1943 ret = -EFAULT;
1944 goto done;
1945 }
1946
1947 if (copy_from_user(&packet_len, req->ifr_data, sizeof(packet_len))) {
1948 PRINTM(MERROR, "Copy from user failed\n");
1949 ret = -EFAULT;
1950 goto done;
1951 }
1952 #define PACKET_HEADER_LEN 8
1953 #define MV_ETH_FRAME_LEN 1514
1954 if (packet_len > MV_ETH_FRAME_LEN) {
1955 PRINTM(MERROR, "Invalid packet length %d\n", packet_len);
1956 ret = -EFAULT;
1957 goto done;
1958 }
1959 pmbuf = woal_alloc_mlan_buffer(priv->phandle,
1960 (int)(MLAN_MIN_DATA_HEADER_LEN +
1961 (int)packet_len +
1962 PACKET_HEADER_LEN));
1963 if (!pmbuf) {
1964 PRINTM(MERROR, "Fail to allocate mlan_buffer\n");
1965 ret = -ENOMEM;
1966 goto done;
1967 }
1968 pmbuf->data_offset = MLAN_MIN_DATA_HEADER_LEN;
1969
1970 /* get whole packet and header */
1971 if (copy_from_user
1972 (pmbuf->pbuf + pmbuf->data_offset,
1973 req->ifr_data + sizeof(packet_len),
1974 PACKET_HEADER_LEN + packet_len)) {
1975 PRINTM(MERROR, "Copy from user failed\n");
1976 ret = -EFAULT;
1977 woal_free_mlan_buffer(priv->phandle, pmbuf);
1978 goto done;
1979 }
1980 pmbuf->data_len = PACKET_HEADER_LEN + packet_len;
1981 pmbuf->buf_type = MLAN_BUF_TYPE_RAW_DATA;
1982 pmbuf->bss_index = priv->bss_index;
1983 action_cat =
1984 (IEEEtypes_ActionCategory_e *)&pmbuf->pbuf[pmbuf->data_offset +
1985 MLAN_ACTION_FRAME_CATEGORY_OFFSET];
1986 action = &pmbuf->pbuf[pmbuf->data_offset +
1987 MLAN_ACTION_FRAME_ACTION_OFFSET];
1988
1989 if (*action_cat == IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM &&
1990 *action == 0x1) {
1991 pmbuf->flags |= MLAN_BUF_FLAG_TX_STATUS;
1992 if (!priv->tx_seq_num)
1993 priv->tx_seq_num++;
1994 pmbuf->tx_seq_num = priv->tx_seq_num++;
1995 tx_info = kzalloc(sizeof(struct tx_status_info), GFP_ATOMIC);
1996 if (tx_info) {
1997 skb = alloc_skb(pmbuf->data_len, GFP_ATOMIC);
1998 if (skb) {
1999 mgmt_frame = (struct ieee80211_mgmt *)skb->data;
2000 //Copy DA,SA and BSSID feilds.
2001 memcpy(mgmt_frame->da,
2002 &pmbuf->pbuf[pmbuf->data_offset + 14],
2003 3 * MLAN_MAC_ADDR_LENGTH);
2004 //Copy packet data starting from category feild
2005 memcpy(&mgmt_frame->u.action.category,
2006 action_cat,
2007 packet_len -
2008 MLAN_ACTION_FRAME_CATEGORY_OFFSET);
2009 /* frame_ctrl+duration+DA+SA+BSSID+seq_ctrl = 24 Bytes */
2010 /*category+action+dt+status = 4Bytes */
2011 skb_put(skb,
2012 24 + 4 + packet_len -
2013 MLAN_ACTION_FRAME_CATEGORY_OFFSET);
2014 spin_lock_irqsave(&priv->tx_stat_lock, flags);
2015 tx_info->tx_skb = skb;
2016 tx_info->tx_seq_num = pmbuf->tx_seq_num;
2017 tx_info->tx_cookie = 0;
2018 INIT_LIST_HEAD(&tx_info->link);
2019 list_add_tail(&tx_info->link,
2020 &priv->tx_stat_queue);
2021 spin_unlock_irqrestore(&priv->tx_stat_lock,
2022 flags);
2023 } else {
2024 kfree(tx_info);
2025 tx_info = NULL;
2026 }
2027 }
2028 }
2029
2030 status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf);
2031 switch (status) {
2032 case MLAN_STATUS_PENDING:
2033 atomic_inc(&priv->phandle->tx_pending);
2034 queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
2035 break;
2036 case MLAN_STATUS_SUCCESS:
2037 woal_free_mlan_buffer(priv->phandle, pmbuf);
2038 break;
2039 case MLAN_STATUS_FAILURE:
2040 default:
2041 woal_free_mlan_buffer(priv->phandle, pmbuf);
2042 ret = -EFAULT;
2043 break;
2044 }
2045 done:
2046 LEAVE();
2047 return ret;
2048 }
2049
2050 #if defined(UAP_WEXT)
2051 /**
2052 * @brief Set/Get CUSTOM_IE ioctl handler
2053 *
2054 * @param priv A pointer to moal_private structure
2055 * @param mask Mask to set or clear from caller
2056 * @param ie IE buffer to set for beacon
2057 * @param ie_len Length of the IE
2058 *
2059 * @return 0 --success, otherwise fail
2060 */
2061 int
woal_set_get_custom_ie(moal_private * priv,t_u16 mask,t_u8 * ie,int ie_len)2062 woal_set_get_custom_ie(moal_private *priv, t_u16 mask, t_u8 *ie, int ie_len)
2063 {
2064 mlan_ioctl_req *ioctl_req = NULL;
2065 mlan_ds_misc_cfg *misc = NULL;
2066 mlan_ds_misc_custom_ie *misc_ie = NULL;
2067 int ret = 0;
2068 custom_ie *pcust_bcn_ie = NULL;
2069 mlan_status status = MLAN_STATUS_SUCCESS;
2070
2071 ENTER();
2072
2073 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2074 if (ioctl_req == NULL) {
2075 LEAVE();
2076 return -ENOMEM;
2077 }
2078
2079 misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
2080 misc->sub_command = MLAN_OID_MISC_CUSTOM_IE;
2081 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
2082 ioctl_req->action = MLAN_ACT_SET;
2083 misc_ie = &misc->param.cust_ie;
2084
2085 misc_ie->type = TLV_TYPE_MGMT_IE;
2086 misc_ie->len = (sizeof(custom_ie) - MAX_IE_SIZE) + ie_len;
2087 pcust_bcn_ie = misc_ie->ie_data_list;
2088 pcust_bcn_ie->ie_index = 0xffff;
2089 pcust_bcn_ie->mgmt_subtype_mask = mask;
2090 pcust_bcn_ie->ie_length = ie_len;
2091 memcpy(pcust_bcn_ie->ie_buffer, ie, ie_len);
2092
2093 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2094 if (status != MLAN_STATUS_SUCCESS)
2095 ret = -EFAULT;
2096
2097 if (status != MLAN_STATUS_PENDING)
2098 kfree(ioctl_req);
2099 LEAVE();
2100 return ret;
2101 }
2102 #endif /* defined(HOST_TXRX_MGMT_FRAME) && defined(UAP_WEXT) */
2103
2104 /**
2105 * @brief TDLS configuration ioctl handler
2106 *
2107 * @param dev A pointer to net_device structure
2108 * @param req A pointer to ifreq structure
2109 * @return 0 --success, otherwise fail
2110 */
2111 int
woal_tdls_config_ioctl(struct net_device * dev,struct ifreq * req)2112 woal_tdls_config_ioctl(struct net_device *dev, struct ifreq *req)
2113 {
2114 moal_private *priv = (moal_private *)netdev_priv(dev);
2115 mlan_ioctl_req *ioctl_req = NULL;
2116 mlan_ds_misc_cfg *misc = NULL;
2117 mlan_ds_misc_tdls_config *tdls_data = NULL;
2118 int ret = 0;
2119 mlan_status status = MLAN_STATUS_SUCCESS;
2120 gfp_t flag;
2121
2122 ENTER();
2123
2124 /* Sanity check */
2125 if (req->ifr_data == NULL) {
2126 PRINTM(MERROR, "woal_tdls_config_ioctl() corrupt data\n");
2127 ret = -EFAULT;
2128 goto done;
2129 }
2130 flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
2131 tdls_data = kzalloc(sizeof(mlan_ds_misc_tdls_config), flag);
2132 if (!tdls_data) {
2133 ret = -ENOMEM;
2134 goto done;
2135 }
2136
2137 if (copy_from_user
2138 (tdls_data, req->ifr_data, sizeof(mlan_ds_misc_tdls_config))) {
2139 PRINTM(MERROR, "Copy from user failed\n");
2140 ret = -EFAULT;
2141 goto done;
2142 }
2143
2144 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2145 if (ioctl_req == NULL) {
2146 ret = -ENOMEM;
2147 goto done;
2148 }
2149
2150 misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
2151 misc->sub_command = MLAN_OID_MISC_TDLS_CONFIG;
2152 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
2153 if (tdls_data->tdls_action == WLAN_TDLS_DISCOVERY_REQ
2154 || tdls_data->tdls_action == WLAN_TDLS_LINK_STATUS)
2155 ioctl_req->action = MLAN_ACT_GET;
2156 else
2157 ioctl_req->action = MLAN_ACT_SET;
2158
2159 memcpy(&misc->param.tdls_config, tdls_data,
2160 sizeof(mlan_ds_misc_tdls_config));
2161
2162 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2163 if (status != MLAN_STATUS_SUCCESS) {
2164 ret = -EFAULT;
2165 goto done;
2166 }
2167
2168 if (tdls_data->tdls_action == WLAN_TDLS_DISCOVERY_REQ
2169 || tdls_data->tdls_action == WLAN_TDLS_LINK_STATUS) {
2170 if (copy_to_user(req->ifr_data, &misc->param.tdls_config,
2171 sizeof(mlan_ds_misc_tdls_config))) {
2172 PRINTM(MERROR, "Copy to user failed!\n");
2173 ret = -EFAULT;
2174 goto done;
2175 }
2176 }
2177
2178 done:
2179 if (status != MLAN_STATUS_PENDING)
2180 kfree(ioctl_req);
2181 kfree(tdls_data);
2182 LEAVE();
2183 return ret;
2184 }
2185
2186 /**
2187 * @brief ioctl function get BSS type
2188 *
2189 * @param dev A pointer to net_device structure
2190 * @param req A pointer to ifreq structure
2191 * @return 0 --success, otherwise fail
2192 */
2193 int
woal_get_bss_type(struct net_device * dev,struct ifreq * req)2194 woal_get_bss_type(struct net_device *dev, struct ifreq *req)
2195 {
2196 int ret = 0;
2197 moal_private *priv = (moal_private *)netdev_priv(dev);
2198 int bss_type;
2199
2200 ENTER();
2201
2202 bss_type = (int)priv->bss_type;
2203 if (copy_to_user(req->ifr_data, &bss_type, sizeof(int))) {
2204 PRINTM(MINFO, "Copy to user failed!\n");
2205 ret = -EFAULT;
2206 }
2207
2208 LEAVE();
2209 return ret;
2210 }
2211
2212 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
2213 /**
2214 * @brief Swithces BSS role of interface
2215 *
2216 * @param priv A pointer to moal_private structure
2217 * @param action Action: set or get
2218 * @param wait_option Wait option (MOAL_IOCTL_WAIT or MOAL_NO_WAIT)
2219 * @param bss_role A pointer to bss role
2220 *
2221 * @return 0 --success, otherwise fail
2222 */
2223 mlan_status
woal_bss_role_cfg(moal_private * priv,t_u8 action,t_u8 wait_option,t_u8 * bss_role)2224 woal_bss_role_cfg(moal_private *priv, t_u8 action,
2225 t_u8 wait_option, t_u8 *bss_role)
2226 {
2227 int ret = 0;
2228 mlan_ds_bss *bss = NULL;
2229 mlan_ioctl_req *req = NULL;
2230 struct net_device *dev = priv->netdev;
2231 mlan_status status = MLAN_STATUS_SUCCESS;
2232
2233 ENTER();
2234
2235 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
2236 if (req == NULL) {
2237 ret = -ENOMEM;
2238 goto done;
2239 }
2240 bss = (mlan_ds_bss *)req->pbuf;
2241 bss->sub_command = MLAN_OID_BSS_ROLE;
2242 req->req_id = MLAN_IOCTL_BSS;
2243 req->action = action;
2244 if (action == MLAN_ACT_SET) {
2245 if (priv->bss_role == *bss_role) {
2246 PRINTM(MWARN, "BSS is in desired role already\n");
2247 goto done;
2248 } else {
2249 bss->param.bss_role = *bss_role;
2250 }
2251 }
2252 status = woal_request_ioctl(priv, req, wait_option);
2253 if (status != MLAN_STATUS_SUCCESS) {
2254 ret = -EFAULT;
2255 goto done;
2256 }
2257
2258 if (action == MLAN_ACT_GET) {
2259 *bss_role = bss->param.bss_role;
2260 } else {
2261 /* Update moal_private */
2262 priv->bss_role = *bss_role;
2263 if (priv->bss_type == MLAN_BSS_TYPE_UAP)
2264 priv->bss_type = MLAN_BSS_TYPE_STA;
2265 else if (priv->bss_type == MLAN_BSS_TYPE_STA)
2266 priv->bss_type = MLAN_BSS_TYPE_UAP;
2267
2268 if (*bss_role == MLAN_BSS_ROLE_UAP) {
2269 /* Switch: STA -> uAP */
2270 /* Setup the OS Interface to our functions */
2271 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
2272 dev->do_ioctl = woal_uap_do_ioctl;
2273 dev->set_multicast_list = woal_uap_set_multicast_list;
2274 #else
2275 dev->netdev_ops = &woal_uap_netdev_ops;
2276 #endif
2277 #ifdef UAP_WEXT
2278 if (IS_UAP_WEXT(cfg80211_wext)) {
2279 #if WIRELESS_EXT < 21
2280 dev->get_wireless_stats =
2281 woal_get_uap_wireless_stats;
2282 #endif
2283 dev->wireless_handlers =
2284 (struct iw_handler_def *)
2285 &woal_uap_handler_def;
2286 }
2287 #endif /* UAP_WEXT */
2288 } else if (*bss_role == MLAN_BSS_ROLE_STA) {
2289 /* Switch: uAP -> STA */
2290 /* Setup the OS Interface to our functions */
2291 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
2292 dev->do_ioctl = woal_do_ioctl;
2293 dev->set_multicast_list = woal_set_multicast_list;
2294 #else
2295 dev->netdev_ops = &woal_netdev_ops;
2296 #endif
2297 #ifdef STA_WEXT
2298 if (IS_STA_WEXT(cfg80211_wext)) {
2299 #if WIRELESS_EXT < 21
2300 dev->get_wireless_stats =
2301 woal_get_wireless_stats;
2302 #endif
2303 dev->wireless_handlers =
2304 (struct iw_handler_def *)
2305 &woal_handler_def;
2306 }
2307 #endif /* STA_WEXT */
2308 }
2309 }
2310
2311 done:
2312 if (status != MLAN_STATUS_PENDING)
2313 kfree(req);
2314 LEAVE();
2315 return ret;
2316 }
2317
2318 #if defined(STA_WEXT) || defined(UAP_WEXT)
2319 /**
2320 * @brief Set/Get BSS role
2321 *
2322 * @param priv A pointer to moal_private structure
2323 * @param wrq A pointer to iwreq structure
2324 *
2325 * @return 0 --success, otherwise fail
2326 */
2327 int
woal_set_get_bss_role(moal_private * priv,struct iwreq * wrq)2328 woal_set_get_bss_role(moal_private *priv, struct iwreq *wrq)
2329 {
2330 int ret = 0;
2331 int bss_role = 0;
2332 t_u8 action = MLAN_ACT_GET;
2333
2334 ENTER();
2335
2336 if (wrq->u.data.length) {
2337 if (copy_from_user(&bss_role, wrq->u.data.pointer, sizeof(int))) {
2338 PRINTM(MERROR, "Copy from user failed\n");
2339 ret = -EFAULT;
2340 goto done;
2341 }
2342 if ((bss_role != MLAN_BSS_ROLE_STA &&
2343 bss_role != MLAN_BSS_ROLE_UAP)
2344 #if defined(WIFI_DIRECT_SUPPORT)
2345 || (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT)
2346 #endif
2347 ) {
2348 PRINTM(MWARN, "Invalid BSS role\n");
2349 ret = -EINVAL;
2350 goto done;
2351 }
2352 if (bss_role == GET_BSS_ROLE(priv)) {
2353 PRINTM(MWARN, "Already BSS is in desired role\n");
2354 ret = -EINVAL;
2355 goto done;
2356 }
2357 action = MLAN_ACT_SET;
2358 /* Reset interface */
2359 woal_reset_intf(priv, MOAL_IOCTL_WAIT, MFALSE);
2360 }
2361
2362 if (MLAN_STATUS_SUCCESS != woal_bss_role_cfg(priv,
2363 action, MOAL_IOCTL_WAIT,
2364 (t_u8 *)&bss_role)) {
2365 ret = -EFAULT;
2366 goto done;
2367 }
2368
2369 if (!wrq->u.data.length) {
2370 if (copy_to_user(wrq->u.data.pointer, &bss_role, sizeof(int))) {
2371 ret = -EFAULT;
2372 goto done;
2373 }
2374 wrq->u.data.length = 1;
2375 } else {
2376 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
2377 if (IS_STA_OR_UAP_CFG80211(cfg80211_wext))
2378 woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_WAIT);
2379 #endif
2380 /* Initialize private structures */
2381 woal_init_priv(priv, MOAL_IOCTL_WAIT);
2382
2383 /* Enable interfaces */
2384 netif_device_attach(priv->netdev);
2385 woal_start_queue(priv->netdev);
2386 }
2387
2388 done:
2389 LEAVE();
2390 return ret;
2391 }
2392 #endif /* STA_WEXT || UAP_WEXT */
2393 #endif /* STA_SUPPORT && UAP_SUPPORT */
2394
2395 #if defined(SDIO_SUSPEND_RESUME)
2396 /**
2397 * @brief Set auto arp resp
2398 *
2399 * @param handle A pointer to moal_handle structure
2400 * @param enable enable/disable
2401 *
2402 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
2403 */
2404 static mlan_status
woal_set_auto_arp(moal_handle * handle,t_u8 enable)2405 woal_set_auto_arp(moal_handle *handle, t_u8 enable)
2406 {
2407 mlan_status ret = MLAN_STATUS_SUCCESS;
2408 int i = 0;
2409 moal_private *priv = NULL;
2410 mlan_ds_misc_cfg *misc = NULL;
2411 mlan_ioctl_req *req = NULL;
2412 mlan_ds_misc_ipaddr_cfg ipaddr_cfg;
2413
2414 ENTER();
2415
2416 memset(&ipaddr_cfg, 0, sizeof(ipaddr_cfg));
2417 for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) {
2418 if (priv && priv->ip_addr_type != IPADDR_TYPE_NONE) {
2419 memcpy(ipaddr_cfg.ip_addr[ipaddr_cfg.ip_addr_num],
2420 priv->ip_addr, IPADDR_LEN);
2421 ipaddr_cfg.ip_addr_num++;
2422 }
2423 }
2424 if (ipaddr_cfg.ip_addr_num == 0) {
2425 PRINTM(MIOCTL, "No IP addr configured.\n");
2426 goto done;
2427 }
2428
2429 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2430 if (req == NULL) {
2431 PRINTM(MIOCTL, "IOCTL req allocated failed!\n");
2432 ret = MLAN_STATUS_FAILURE;
2433 goto done;
2434 }
2435 misc = (mlan_ds_misc_cfg *)req->pbuf;
2436 misc->sub_command = MLAN_OID_MISC_IP_ADDR;
2437 req->req_id = MLAN_IOCTL_MISC_CFG;
2438 req->action = MLAN_ACT_SET;
2439 memcpy(&misc->param.ipaddr_cfg, &ipaddr_cfg, sizeof(ipaddr_cfg));
2440 if (enable) {
2441 misc->param.ipaddr_cfg.op_code = MLAN_IPADDR_OP_ARP_FILTER |
2442 MLAN_IPADDR_OP_AUTO_ARP_RESP;
2443 misc->param.ipaddr_cfg.ip_addr_type = IPADDR_TYPE_IPV4;
2444 } else {
2445 /** remove ip */
2446 misc->param.ipaddr_cfg.op_code = MLAN_IPADDR_OP_IP_REMOVE;
2447 }
2448 ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), req,
2449 MOAL_NO_WAIT);
2450 if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
2451 PRINTM(MIOCTL, "Set auto arp IOCTL failed!\n");
2452 done:
2453 if (ret != MLAN_STATUS_PENDING)
2454 kfree(req);
2455 LEAVE();
2456 return ret;
2457 }
2458
2459 #endif
2460
2461 /**
2462 * @brief Set/Get DTIM period
2463 *
2464 * @param priv A pointer to moal_private structure
2465 * @param action Action set or get
2466 * @param wait_option Wait option
2467 * @param value DTIM period
2468 *
2469 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
2470 */
2471 mlan_status
woal_set_get_dtim_period(moal_private * priv,t_u32 action,t_u8 wait_option,t_u8 * value)2472 woal_set_get_dtim_period(moal_private *priv,
2473 t_u32 action, t_u8 wait_option, t_u8 *value)
2474 {
2475 mlan_ioctl_req *req = NULL;
2476 mlan_ds_snmp_mib *mib = NULL;
2477 mlan_status ret = MLAN_STATUS_SUCCESS;
2478
2479 ENTER();
2480
2481 /* Allocate an IOCTL request buffer */
2482 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
2483 if (req == NULL) {
2484 ret = MLAN_STATUS_FAILURE;
2485 goto done;
2486 }
2487
2488 /* Fill request buffer */
2489 mib = (mlan_ds_snmp_mib *)req->pbuf;
2490 mib->sub_command = MLAN_OID_SNMP_MIB_DTIM_PERIOD;
2491 req->req_id = MLAN_IOCTL_SNMP_MIB;
2492 req->action = action;
2493
2494 if (action == MLAN_ACT_SET)
2495 mib->param.dtim_period = *value;
2496
2497 /* Send IOCTL request to MLAN */
2498 ret = woal_request_ioctl(priv, req, wait_option);
2499 if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
2500 *value = (t_u8)mib->param.dtim_period;
2501
2502 done:
2503 if (ret != MLAN_STATUS_PENDING)
2504 kfree(req);
2505 LEAVE();
2506 return ret;
2507 }
2508
2509 /**
2510 * @brief Get Host Sleep parameters
2511 *
2512 * @param priv A pointer to moal_private structure
2513 * @param action Action: set or get
2514 * @param wait_option Wait option (MOAL_IOCTL_WAIT or MOAL_NO_WAIT)
2515 * @param hscfg A pointer to mlan_ds_hs_cfg structure
2516 *
2517 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
2518 */
2519 mlan_status
woal_set_get_hs_params(moal_private * priv,t_u16 action,t_u8 wait_option,mlan_ds_hs_cfg * hscfg)2520 woal_set_get_hs_params(moal_private *priv, t_u16 action, t_u8 wait_option,
2521 mlan_ds_hs_cfg *hscfg)
2522 {
2523 mlan_status ret = MLAN_STATUS_SUCCESS;
2524 mlan_ds_pm_cfg *pmcfg = NULL;
2525 mlan_ioctl_req *req = NULL;
2526
2527 ENTER();
2528
2529 /* Allocate an IOCTL request buffer */
2530 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
2531 if (req == NULL) {
2532 ret = -ENOMEM;
2533 goto done;
2534 }
2535
2536 /* Fill request buffer */
2537 pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
2538 pmcfg->sub_command = MLAN_OID_PM_CFG_HS_CFG;
2539 req->req_id = MLAN_IOCTL_PM_CFG;
2540 req->action = action;
2541 if (action == MLAN_ACT_SET)
2542 memcpy(&pmcfg->param.hs_cfg, hscfg, sizeof(mlan_ds_hs_cfg));
2543
2544 /* Send IOCTL request to MLAN */
2545 ret = woal_request_ioctl(priv, req, wait_option);
2546 if (ret == MLAN_STATUS_SUCCESS) {
2547 if (hscfg && action == MLAN_ACT_GET) {
2548 memcpy(hscfg, &pmcfg->param.hs_cfg,
2549 sizeof(mlan_ds_hs_cfg));
2550 }
2551 }
2552 done:
2553 if (ret != MLAN_STATUS_PENDING)
2554 kfree(req);
2555 LEAVE();
2556 return ret;
2557 }
2558
2559 /**
2560 * @brief Get wakeup reason
2561 *
2562 * @param priv A pointer to moal_private structure
2563 * @param wakeup_reason A pointer to mlan_ds_hs_wakeup_reason structure
2564 *
2565 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
2566 */
2567 mlan_status
woal_get_wakeup_reason(moal_private * priv,mlan_ds_hs_wakeup_reason * wakeup_reason)2568 woal_get_wakeup_reason(moal_private *priv,
2569 mlan_ds_hs_wakeup_reason *wakeup_reason)
2570 {
2571 mlan_status ret = MLAN_STATUS_SUCCESS;
2572 mlan_ds_pm_cfg *pmcfg = NULL;
2573 mlan_ioctl_req *req = NULL;
2574
2575 ENTER();
2576
2577 /* Allocate an IOCTL request buffer */
2578 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
2579 if (req == NULL) {
2580 ret = -ENOMEM;
2581 goto done;
2582 }
2583
2584 /* Fill request buffer */
2585 pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
2586 pmcfg->sub_command = MLAN_OID_PM_HS_WAKEUP_REASON;
2587 req->req_id = MLAN_IOCTL_PM_CFG;
2588 req->action = MLAN_ACT_GET;
2589
2590 /* Send IOCTL request to MLAN */
2591 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2592 if (ret == MLAN_STATUS_SUCCESS) {
2593 wakeup_reason->hs_wakeup_reason =
2594 pmcfg->param.wakeup_reason.hs_wakeup_reason;
2595 }
2596 done:
2597 if (ret != MLAN_STATUS_PENDING)
2598 kfree(req);
2599 LEAVE();
2600 return ret;
2601 }
2602
2603 /**
2604 * @brief Cancel Host Sleep configuration
2605 *
2606 * @param priv A pointer to moal_private structure
2607 * @param wait_option wait option
2608 *
2609 * @return MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING,
2610 * or MLAN_STATUS_FAILURE
2611 */
2612 mlan_status
woal_cancel_hs(moal_private * priv,t_u8 wait_option)2613 woal_cancel_hs(moal_private *priv, t_u8 wait_option)
2614 {
2615 moal_handle *handle = NULL;
2616 mlan_status ret = MLAN_STATUS_SUCCESS;
2617 mlan_ds_hs_cfg hscfg;
2618 int i;
2619 ENTER();
2620
2621 if (!priv) {
2622 LEAVE();
2623 return MLAN_STATUS_FAILURE;
2624 }
2625 handle = priv->phandle;
2626 /* Cancel Host Sleep */
2627
2628 hscfg.conditions = HOST_SLEEP_CFG_CANCEL;
2629 hscfg.is_invoke_hostcmd = MTRUE;
2630 ret = woal_set_get_hs_params(priv, MLAN_ACT_SET, wait_option, &hscfg);
2631
2632 if (roamoffload_in_hs) {
2633 /*Disable firmware roaming */
2634 woal_enable_fw_roaming(priv, 0);
2635 }
2636 if (handle->fw_roam_enable == ROAM_OFFLOAD_WITH_BSSID ||
2637 handle->fw_roam_enable == ROAM_OFFLOAD_WITH_SSID ||
2638 handle->fw_roam_enable == AUTO_RECONNECT)
2639 woal_config_fw_roaming(priv, ROAM_OFFLOAD_RESUME_CFG, NULL);
2640 if (handle->fw_roam_enable == AUTO_RECONNECT)
2641 woal_set_clear_pmk(priv, MLAN_ACT_CLEAR);
2642
2643 #if defined(SDIO_SUSPEND_RESUME)
2644 if (priv->phandle->hs_auto_arp) {
2645 PRINTM(MIOCTL, "Cancel Host Sleep... remove FW auto arp\n");
2646 /* remove auto arp from FW */
2647 woal_set_auto_arp(priv->phandle, MFALSE);
2648 }
2649 #endif
2650
2651 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
2652 if (GTK_REKEY_OFFLOAD_SUSPEND == gtk_rekey_offload) {
2653 PRINTM(MIOCTL,
2654 "Cancel Host Sleep... clear gtk rekey offload of FW\n");
2655 for (i = 0; i < handle->priv_num; i++) {
2656 if (handle->priv[i] && handle->priv[i]->gtk_data_ready) {
2657 PRINTM(MCMND, "clear GTK in resume\n");
2658 woal_set_rekey_data(handle->priv[i], NULL,
2659 MLAN_ACT_CLEAR);
2660 }
2661 }
2662 }
2663 #endif
2664
2665 LEAVE();
2666 return ret;
2667 }
2668
2669 /** @brief This function config fw roaming parameters
2670 *
2671 * @param priv A Pointer to the moal_private structure
2672 * @return MTRUE or MFALSE
2673 */
2674 int
woal_set_fw_roaming_params(moal_private * priv)2675 woal_set_fw_roaming_params(moal_private *priv)
2676 {
2677 int ret = 0;
2678 mlan_status status = MLAN_STATUS_SUCCESS;
2679 mlan_ioctl_req *req = NULL;
2680 mlan_ds_sec_cfg *sec = NULL;
2681 woal_roam_offload_cfg roam_offload_cfg;
2682 t_u8 zero[MLAN_MAX_KEY_LENGTH] = { 0 };
2683
2684 /*Enable fw roaming */
2685 woal_config_fw_roaming(priv, ROAM_OFFLOAD_ENABLE, NULL);
2686 /*Download fw roaming parameters */
2687 woal_config_fw_roaming(priv, ROAM_OFFLOAD_PARAM_CFG,
2688 &priv->phandle->fw_roam_params);
2689
2690 /*Download userset passphrase key and current connection's PMK */
2691 if (!priv->phandle->fw_roam_params.userset_passphrase) {
2692 woal_set_clear_pmk(priv, MLAN_ACT_SET);
2693 goto done;
2694 }
2695
2696 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
2697 if (req == NULL) {
2698 ret = -ENOMEM;
2699 goto done;
2700 }
2701
2702 req->req_id = MLAN_IOCTL_SEC_CFG;
2703 sec = (mlan_ds_sec_cfg *)req->pbuf;
2704 sec->sub_command = MLAN_OID_SEC_CFG_PASSPHRASE;
2705 sec->multi_passphrase = 1;
2706 req->action = MLAN_ACT_SET;
2707
2708 /*Copy user set passphrase */
2709 memcpy((char *)sec->param.roam_passphrase,
2710 (char *)priv->phandle->ssid_passphrase,
2711 MAX_SEC_SSID_NUM * sizeof(mlan_ds_passphrase));
2712 roam_offload_cfg.userset_passphrase =
2713 priv->phandle->fw_roam_params.userset_passphrase;
2714
2715 if (memcmp(priv->pmk.pmk, zero, MLAN_MAX_KEY_LENGTH)) {
2716 /*Download current connection PMK */
2717 if (priv->pmk_saved) {
2718 woal_set_clear_pmk(priv, MLAN_ACT_SET);
2719 priv->pmk_saved = false;
2720 }
2721 }
2722
2723 /*Set userset to mlan adapter */
2724 woal_config_fw_roaming(priv, ROAM_OFFLOAD_ENABLE, &roam_offload_cfg);
2725
2726 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2727 if (status != MLAN_STATUS_SUCCESS) {
2728 ret = -EFAULT;
2729 goto done;
2730 }
2731 if (ret)
2732 goto done;
2733 done:
2734 if (status != MLAN_STATUS_PENDING)
2735 kfree(req);
2736 LEAVE();
2737 return ret;
2738 }
2739
2740 /** @brief This function enable/disable fw roaming
2741 *
2742 * @param priv A Pointer to the moal_private structure
2743 * @param enable Enable/disable fw roaming
2744 * @return MTRUE or MFALSE
2745 */
2746 int
woal_enable_fw_roaming(moal_private * priv,int data)2747 woal_enable_fw_roaming(moal_private *priv, int data)
2748 {
2749 mlan_ioctl_req *ioctl_req = NULL;
2750 mlan_ds_misc_cfg *misc = NULL;
2751 mlan_ds_misc_roam_offload *roam = NULL;
2752 mlan_status status = MLAN_STATUS_SUCCESS;
2753 int ret = 0;
2754
2755 ENTER();
2756
2757 if (!priv || !priv->phandle) {
2758 PRINTM(MERROR, "priv or handle is null\n");
2759 ret = -EFAULT;
2760 goto done;
2761 }
2762
2763 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2764 if (ioctl_req == NULL) {
2765 ret = -ENOMEM;
2766 goto done;
2767 }
2768
2769 misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
2770 misc->sub_command = MLAN_OID_MISC_ROAM_OFFLOAD;
2771 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
2772
2773 roam = (mlan_ds_misc_roam_offload *) & misc->param.roam_offload;
2774 roam->aplist.ap_num = 0;
2775 /* SET operation */
2776 ioctl_req->action = MLAN_ACT_SET;
2777 roam->enable = data;
2778 roam->config_mode = ROAM_OFFLOAD_ENABLE;
2779
2780 if (roamoffload_in_hs && data) {
2781 priv->phandle->fw_roam_enable = data;
2782 goto done;
2783 }
2784
2785 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2786 if (status != MLAN_STATUS_SUCCESS) {
2787 ret = -EFAULT;
2788 goto done;
2789 }
2790 priv->phandle->fw_roam_enable = data;
2791 if (!data) {
2792 memset((char *)&priv->phandle->fw_roam_params, 0,
2793 sizeof(woal_roam_offload_cfg));
2794 memset((char *)&priv->phandle->ssid_passphrase, 0,
2795 MAX_SEC_SSID_NUM * sizeof(mlan_ds_passphrase));
2796 } else if (priv->media_connected && priv->pmk_saved) {
2797 woal_set_clear_pmk(priv, MLAN_ACT_SET);
2798 priv->pmk_saved = false;
2799 }
2800
2801 done:
2802 if (status != MLAN_STATUS_PENDING)
2803 kfree(ioctl_req);
2804
2805 LEAVE();
2806 return ret;
2807 }
2808
2809 #if defined(SDIO_SUSPEND_RESUME)
2810 /** @brief This function enables the host sleep
2811 *
2812 * @param priv A Pointer to the moal_private structure
2813 * @return MTRUE or MFALSE
2814 */
2815 int
woal_enable_hs(moal_private * priv)2816 woal_enable_hs(moal_private *priv)
2817 {
2818 mlan_ds_hs_cfg hscfg;
2819 moal_handle *handle = NULL;
2820 int hs_actived = MFALSE;
2821 int timeout = 0;
2822 int i;
2823 #ifdef SDIO_SUSPEND_RESUME
2824 mlan_ds_ps_info pm_info;
2825 #endif
2826
2827 ENTER();
2828
2829 if (priv == NULL) {
2830 PRINTM(MERROR, "Invalid priv\n");
2831 goto done;
2832 }
2833 handle = priv->phandle;
2834 if (handle->hs_activated == MTRUE) {
2835 PRINTM(MIOCTL, "HS Already actived\n");
2836 hs_actived = MTRUE;
2837 goto done;
2838 }
2839 for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
2840 if (handle->priv[i] &&
2841 (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA)) {
2842 if (disconnect_on_suspend &&
2843 handle->priv[i]->media_connected == MTRUE) {
2844 PRINTM(MIOCTL, "disconnect on suspend\n");
2845 woal_disconnect(handle->priv[i], MOAL_NO_WAIT,
2846 NULL, DEF_DEAUTH_REASON_CODE);
2847 }
2848 }
2849 if (handle->priv[i]) {
2850 PRINTM(MIOCTL, "woal_delba_all on priv[%d]\n", i);
2851 woal_delba_all(handle->priv[i], MOAL_IOCTL_WAIT);
2852 }
2853 }
2854
2855 #if defined(STA_CFG80211) && defined(UAP_CFG80211)
2856 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
2857
2858 if (priv->phandle->is_remain_timer_set) {
2859 woal_cancel_timer(&priv->phandle->remain_timer);
2860 woal_remain_timer_func(priv->phandle);
2861 }
2862 /* cancel pending remain on channel */
2863 if (priv->phandle->remain_on_channel) {
2864 t_u8 channel_status;
2865 moal_private *remain_priv =
2866 priv->phandle->priv[priv->phandle->remain_bss_index];
2867 if (remain_priv) {
2868 woal_cfg80211_remain_on_channel_cfg(remain_priv,
2869 MOAL_NO_WAIT, MTRUE,
2870 &channel_status,
2871 NULL, 0, 0);
2872 if (priv->phandle->cookie) {
2873 cfg80211_remain_on_channel_expired(
2874 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
2875 remain_priv->
2876 netdev,
2877 #else
2878 remain_priv->
2879 wdev,
2880 #endif
2881 priv->
2882 phandle->
2883 cookie,
2884 &priv->
2885 phandle->
2886 chan,
2887 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
2888 priv->
2889 phandle->
2890 channel_type,
2891 #endif
2892 GFP_ATOMIC);
2893 priv->phandle->cookie = 0;
2894 }
2895 }
2896 priv->phandle->remain_on_channel = MFALSE;
2897 }
2898 #endif
2899 #endif
2900
2901 #ifdef STA_SUPPORT
2902 woal_reconfig_bgscan(priv->phandle);
2903 #endif
2904
2905 if (roamoffload_in_hs) {
2906 woal_set_fw_roaming_params(priv);
2907 }
2908 if (handle->fw_roam_enable == ROAM_OFFLOAD_WITH_BSSID ||
2909 handle->fw_roam_enable == ROAM_OFFLOAD_WITH_SSID ||
2910 handle->fw_roam_enable == AUTO_RECONNECT) {
2911 woal_config_fw_roaming(priv, ROAM_OFFLOAD_SUSPEND_CFG, NULL);
2912 if (priv->phandle->fw_roam_enable == AUTO_RECONNECT)
2913 woal_set_clear_pmk(priv, MLAN_ACT_SET);
2914 }
2915
2916 if (handle->hs_auto_arp) {
2917 PRINTM(MIOCTL, "Host Sleep enabled... set FW auto arp\n");
2918 /* Set auto arp response configuration to Fw */
2919 woal_set_auto_arp(handle, MTRUE);
2920 }
2921 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
2922 if (GTK_REKEY_OFFLOAD_SUSPEND == gtk_rekey_offload) {
2923 PRINTM(MIOCTL,
2924 "Host Sleep enabled... set gtk rekey offload to FW\n");
2925 for (i = 0; i < handle->priv_num; i++) {
2926 if (handle->priv[i] && handle->priv[i]->gtk_data_ready) {
2927 PRINTM(MCMND, "set GTK before suspend\n");
2928 woal_set_rekey_data(handle->priv[i],
2929 &handle->priv[i]->
2930 gtk_rekey_data,
2931 MLAN_ACT_SET);
2932 }
2933 }
2934 }
2935 #endif
2936
2937 /* Enable Host Sleep */
2938 handle->hs_activate_wait_q_woken = MFALSE;
2939 memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg));
2940 hscfg.is_invoke_hostcmd = MTRUE;
2941 if (woal_set_get_hs_params(priv, MLAN_ACT_SET, MOAL_NO_WAIT, &hscfg) ==
2942 MLAN_STATUS_FAILURE) {
2943 PRINTM(MIOCTL, "IOCTL request HS enable failed\n");
2944 goto done;
2945 }
2946 timeout = wait_event_interruptible_timeout(handle->hs_activate_wait_q,
2947 handle->
2948 hs_activate_wait_q_woken,
2949 HS_ACTIVE_TIMEOUT);
2950 sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
2951 if ((handle->hs_activated == MTRUE) || (handle->is_suspended == MTRUE)) {
2952 PRINTM(MCMND, "suspend success! force=%u skip=%u\n",
2953 handle->hs_force_count, handle->hs_skip_count);
2954 hs_actived = MTRUE;
2955 }
2956 #ifdef SDIO_SUSPEND_RESUME
2957 else {
2958 handle->suspend_fail = MTRUE;
2959 woal_get_pm_info(priv, &pm_info);
2960 if (pm_info.is_suspend_allowed == MTRUE) {
2961 #ifdef MMC_PM_FUNC_SUSPENDED
2962 woal_wlan_is_suspended(priv->phandle);
2963 #endif
2964 handle->hs_force_count++;
2965 PRINTM(MCMND, "suspend allowed! force=%u skip=%u\n",
2966 handle->hs_force_count, handle->hs_skip_count);
2967 hs_actived = MTRUE;
2968 }
2969 }
2970 #endif /* SDIO_SUSPEND_RESUME */
2971 sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
2972 if (hs_actived != MTRUE) {
2973 handle->hs_skip_count++;
2974 #ifdef SDIO_SUSPEND_RESUME
2975 PRINTM(MCMND,
2976 "suspend skipped! timeout=%d allow=%d force=%u skip=%u\n",
2977 timeout, (int)pm_info.is_suspend_allowed,
2978 handle->hs_force_count, handle->hs_skip_count);
2979 #else
2980 PRINTM(MCMND, "suspend skipped! timeout=%d skip=%u\n",
2981 timeout, handle->hs_skip_count);
2982 #endif
2983 woal_cancel_hs(priv, MOAL_NO_WAIT);
2984 }
2985 done:
2986 LEAVE();
2987 return hs_actived;
2988 }
2989 #endif
2990
2991 #ifdef CONFIG_PROC_FS
2992 /**
2993 * @brief This function send soft_reset command to firmware
2994 *
2995 * @param handle A pointer to moal_handle structure
2996 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING on success,
2997 * otherwise failure code
2998 */
2999 mlan_status
woal_request_soft_reset(moal_handle * handle)3000 woal_request_soft_reset(moal_handle *handle)
3001 {
3002 mlan_status ret = MLAN_STATUS_SUCCESS;
3003 mlan_ioctl_req *req = NULL;
3004 mlan_ds_misc_cfg *misc = NULL;
3005
3006 ENTER();
3007 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3008 if (req) {
3009 misc = (mlan_ds_misc_cfg *)req->pbuf;
3010 misc->sub_command = MLAN_OID_MISC_SOFT_RESET;
3011 req->req_id = MLAN_IOCTL_MISC_CFG;
3012 req->action = MLAN_ACT_SET;
3013 ret = woal_request_ioctl(woal_get_priv
3014 (handle, MLAN_BSS_ROLE_ANY), req,
3015 MOAL_IOCTL_WAIT);
3016 }
3017
3018 handle->surprise_removed = MTRUE;
3019 woal_sched_timeout(5);
3020 if (ret != MLAN_STATUS_PENDING)
3021 kfree(req);
3022 LEAVE();
3023 return ret;
3024 }
3025 #endif /* CONFIG_PROC_FS */
3026
3027 /**
3028 * @brief Set wapi enable
3029 *
3030 * @param priv A pointer to moal_private structure
3031 * @param wait_option Wait option
3032 * @param enable MTRUE or MFALSE
3033 *
3034 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
3035 */
3036 mlan_status
woal_set_wapi_enable(moal_private * priv,t_u8 wait_option,t_u32 enable)3037 woal_set_wapi_enable(moal_private *priv, t_u8 wait_option, t_u32 enable)
3038 {
3039 int ret = 0;
3040 mlan_ioctl_req *req = NULL;
3041 mlan_ds_sec_cfg *sec = NULL;
3042 mlan_status status = MLAN_STATUS_SUCCESS;
3043 ENTER();
3044
3045 /* Allocate an IOCTL request buffer */
3046 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
3047 if (req == NULL) {
3048 ret = -ENOMEM;
3049 goto done;
3050 }
3051
3052 /* Fill request buffer */
3053 sec = (mlan_ds_sec_cfg *)req->pbuf;
3054 sec->sub_command = MLAN_OID_SEC_CFG_WAPI_ENABLED;
3055 req->req_id = MLAN_IOCTL_SEC_CFG;
3056 req->action = MLAN_ACT_SET;
3057 sec->param.wapi_enabled = enable;
3058
3059 /* Send IOCTL request to MLAN */
3060 status = woal_request_ioctl(priv, req, wait_option);
3061 done:
3062 if (status != MLAN_STATUS_PENDING)
3063 kfree(req);
3064 LEAVE();
3065 return status;
3066 }
3067
3068 /**
3069 * @brief Get version
3070 *
3071 * @param handle A pointer to moal_handle structure
3072 * @param version A pointer to version buffer
3073 * @param max_len max length of version buffer
3074 *
3075 * @return N/A
3076 */
3077 void
woal_get_version(moal_handle * handle,char * version,int max_len)3078 woal_get_version(moal_handle *handle, char *version, int max_len)
3079 {
3080 union {
3081 t_u32 l;
3082 t_u8 c[4];
3083 } ver;
3084 char fw_ver[32];
3085
3086 ENTER();
3087
3088 ver.l = handle->fw_release_number;
3089 snprintf(fw_ver, sizeof(fw_ver), "%u.%u.%u.p%u",
3090 ver.c[2], ver.c[1], ver.c[0], ver.c[3]);
3091
3092 snprintf(version, max_len, handle->driver_version, fw_ver);
3093
3094 LEAVE();
3095 }
3096
3097 #if defined(STA_WEXT) || defined(UAP_WEXT)
3098 /**
3099 * @brief Get Driver Version
3100 *
3101 * @param priv A pointer to moal_private structure
3102 * @param req A pointer to ifreq structure
3103 *
3104 * @return 0 --success, otherwise fail
3105 */
3106 int
woal_get_driver_version(moal_private * priv,struct ifreq * req)3107 woal_get_driver_version(moal_private *priv, struct ifreq *req)
3108 {
3109 struct iwreq *wrq = (struct iwreq *)req;
3110 int len;
3111 char buf[MLAN_MAX_VER_STR_LEN];
3112 ENTER();
3113
3114 woal_get_version(priv->phandle, buf, sizeof(buf) - 1);
3115
3116 len = strlen(buf);
3117 if (wrq->u.data.pointer) {
3118 if (copy_to_user(wrq->u.data.pointer, buf, len)) {
3119 PRINTM(MERROR, "Copy to user failed\n");
3120 LEAVE();
3121 return -EFAULT;
3122 }
3123 wrq->u.data.length = len;
3124 }
3125 PRINTM(MINFO, "MOAL VERSION: %s\n", buf);
3126 LEAVE();
3127 return 0;
3128 }
3129
3130 /**
3131 * @brief Get extended driver version
3132 *
3133 * @param priv A pointer to moal_private structure
3134 * @param ireq A pointer to ifreq structure
3135 *
3136 * @return 0 --success, otherwise fail
3137 */
3138 int
woal_get_driver_verext(moal_private * priv,struct ifreq * ireq)3139 woal_get_driver_verext(moal_private *priv, struct ifreq *ireq)
3140 {
3141 struct iwreq *wrq = (struct iwreq *)ireq;
3142 mlan_ds_get_info *info = NULL;
3143 mlan_ioctl_req *req = NULL;
3144 int ret = 0;
3145 mlan_status status = MLAN_STATUS_SUCCESS;
3146
3147 ENTER();
3148
3149 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
3150 if (req == NULL) {
3151 LEAVE();
3152 return -ENOMEM;
3153 }
3154
3155 info = (mlan_ds_get_info *)req->pbuf;
3156 info->sub_command = MLAN_OID_GET_VER_EXT;
3157 req->req_id = MLAN_IOCTL_GET_INFO;
3158 req->action = MLAN_ACT_GET;
3159
3160 if (!wrq->u.data.flags) {
3161 info->param.ver_ext.version_str_sel =
3162 *((int *)(wrq->u.name + SUBCMD_OFFSET));
3163 } else {
3164 if (copy_from_user
3165 (&info->param.ver_ext.version_str_sel, wrq->u.data.pointer,
3166 sizeof(info->param.ver_ext.version_str_sel))) {
3167 PRINTM(MERROR, "Copy from user failed\n");
3168 ret = -EFAULT;
3169 goto done;
3170 } else {
3171 if (((t_s32)(info->param.ver_ext.version_str_sel)) < 0) {
3172 PRINTM(MERROR, "Invalid arguments!\n");
3173 ret = -EINVAL;
3174 goto done;
3175 }
3176 }
3177 }
3178
3179 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3180 if (status != MLAN_STATUS_SUCCESS) {
3181 ret = -EFAULT;
3182 goto done;
3183 }
3184
3185 if (wrq->u.data.pointer) {
3186 if (copy_to_user
3187 (wrq->u.data.pointer, info->param.ver_ext.version_str,
3188 strlen(info->param.ver_ext.version_str))) {
3189 PRINTM(MERROR, "Copy to user failed\n");
3190 ret = -EFAULT;
3191 goto done;
3192 }
3193 wrq->u.data.length = strlen(info->param.ver_ext.version_str);
3194 }
3195
3196 PRINTM(MINFO, "MOAL EXTENDED VERSION: %s\n",
3197 info->param.ver_ext.version_str);
3198 done:
3199 if (status != MLAN_STATUS_PENDING)
3200 kfree(req);
3201
3202 LEAVE();
3203 return ret;
3204 }
3205 #endif
3206
3207 #ifdef DEBUG_LEVEL1
3208 /**
3209 * @brief Set driver debug bit masks to mlan in order to enhance performance
3210 *
3211 * @param priv A pointer to moal_private structure
3212 * @param drvdbg Driver debug level
3213 *
3214 * @return 0 --success, otherwise fail
3215 */
3216 int
woal_set_drvdbg(moal_private * priv,t_u32 drvdbg)3217 woal_set_drvdbg(moal_private *priv, t_u32 drvdbg)
3218 {
3219 mlan_ioctl_req *req = NULL;
3220 mlan_ds_misc_cfg *misc = NULL;
3221 int ret = 0;
3222
3223 ENTER();
3224
3225 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3226 if (req == NULL) {
3227 LEAVE();
3228 return -ENOMEM;
3229 }
3230
3231 misc = (mlan_ds_misc_cfg *)req->pbuf;
3232 misc->sub_command = MLAN_OID_MISC_DRVDBG;
3233 req->req_id = MLAN_IOCTL_MISC_CFG;
3234 req->action = MLAN_ACT_SET;
3235 misc->param.drvdbg = drvdbg;
3236
3237 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3238
3239 if (ret != MLAN_STATUS_PENDING)
3240 kfree(req);
3241
3242 LEAVE();
3243 return ret;
3244 }
3245 #endif
3246
3247 /**
3248 * @brief Mgmt frame forward registration
3249 *
3250 * @param priv A pointer to moal_private structure
3251 * @param action Action: set or get
3252 * @param pmgmt_subtype_mask A Pointer to mgmt frame subtype mask
3253 * @param wait_option wait option (MOAL_IOCTL_WAIT or MOAL_NO_WAIT)
3254 *
3255 * @return 0 --success, otherwise fail
3256 */
3257 int
woal_reg_rx_mgmt_ind(moal_private * priv,t_u16 action,t_u32 * pmgmt_subtype_mask,t_u8 wait_option)3258 woal_reg_rx_mgmt_ind(moal_private *priv, t_u16 action,
3259 t_u32 *pmgmt_subtype_mask, t_u8 wait_option)
3260 {
3261 mlan_ioctl_req *req = NULL;
3262 mlan_ds_misc_cfg *misc = NULL;
3263 int ret = 0;
3264
3265 ENTER();
3266
3267 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3268 if (req == NULL) {
3269 LEAVE();
3270 return -ENOMEM;
3271 }
3272
3273 misc = (mlan_ds_misc_cfg *)req->pbuf;
3274 misc->sub_command = MLAN_OID_MISC_RX_MGMT_IND;
3275 req->req_id = MLAN_IOCTL_MISC_CFG;
3276 req->action = action;
3277 misc->param.mgmt_subtype_mask = *pmgmt_subtype_mask;
3278 if (req->action == MLAN_ACT_SET)
3279 memcpy(&misc->param.mgmt_subtype_mask,
3280 pmgmt_subtype_mask,
3281 sizeof(misc->param.mgmt_subtype_mask));
3282
3283 ret = woal_request_ioctl(priv, req, wait_option);
3284
3285 if (req->action == MLAN_ACT_GET)
3286 memcpy(pmgmt_subtype_mask, &misc->param.mgmt_subtype_mask,
3287 sizeof(misc->param.mgmt_subtype_mask));
3288
3289 if (ret != MLAN_STATUS_PENDING)
3290 kfree(req);
3291
3292 LEAVE();
3293 return ret;
3294 }
3295
3296 /**
3297 * @brief Set/Get Transmit beamforming capabilities
3298 *
3299 * @param priv A pointer to moal_private structure
3300 * @param action Action: set or get
3301 * @param tx_bf_cap A pointer to tx_buf_cap buffer
3302 *
3303 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
3304 */
3305 mlan_status
woal_set_get_tx_bf_cap(moal_private * priv,t_u16 action,t_u32 * tx_bf_cap)3306 woal_set_get_tx_bf_cap(moal_private *priv, t_u16 action, t_u32 *tx_bf_cap)
3307 {
3308 mlan_ioctl_req *req = NULL;
3309 mlan_ds_11n_cfg *bf_cfg = NULL;
3310 mlan_status ret = MLAN_STATUS_SUCCESS;
3311
3312 ENTER();
3313
3314 if (!tx_bf_cap) {
3315 ret = MLAN_STATUS_FAILURE;
3316 goto done;
3317 }
3318 /* Allocate an IOCTL request buffer */
3319 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
3320 if (req == NULL) {
3321 ret = MLAN_STATUS_FAILURE;
3322 goto done;
3323 }
3324
3325 /* Fill request buffer */
3326 bf_cfg = (mlan_ds_11n_cfg *)req->pbuf;
3327 req->req_id = MLAN_IOCTL_11N_CFG;
3328 bf_cfg->sub_command = MLAN_OID_11N_CFG_TX_BF_CAP;
3329 req->action = action;
3330 if (action == MLAN_ACT_SET)
3331 bf_cfg->param.tx_bf_cap = *tx_bf_cap;
3332
3333 /* Send IOCTL request to MLAN */
3334 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3335 if (ret != MLAN_STATUS_SUCCESS) {
3336 goto done;
3337 }
3338
3339 if (action == MLAN_ACT_GET)
3340 *tx_bf_cap = bf_cfg->param.tx_bf_cap;
3341
3342 done:
3343 if (ret != MLAN_STATUS_PENDING)
3344 kfree(req);
3345 LEAVE();
3346 return ret;
3347 }
3348
3349 /**
3350 * @brief Set/Get Transmit beamforming configuration
3351 *
3352 * @param priv A pointer to moal_private structure
3353 * @param action Action: set or get
3354 * @param tx_bf_cfg A pointer to tx_bf_cfg structure
3355 *
3356 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
3357 */
3358 mlan_status
woal_set_get_tx_bf_cfg(moal_private * priv,t_u16 action,mlan_ds_11n_tx_bf_cfg * tx_bf_cfg)3359 woal_set_get_tx_bf_cfg(moal_private *priv, t_u16 action,
3360 mlan_ds_11n_tx_bf_cfg *tx_bf_cfg)
3361 {
3362 mlan_status ret = MLAN_STATUS_SUCCESS;
3363 mlan_ioctl_req *req = NULL;
3364 mlan_ds_11n_cfg *bf_cfg = NULL;
3365
3366 ENTER();
3367
3368 /* Sanity test */
3369 if (tx_bf_cfg == NULL) {
3370 ret = MLAN_STATUS_FAILURE;
3371 goto done;
3372 }
3373
3374 /* Allocate an IOCTL request buffer */
3375 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
3376 if (req == NULL) {
3377 ret = MLAN_STATUS_FAILURE;
3378 goto done;
3379 }
3380
3381 /* Fill request buffer */
3382 bf_cfg = (mlan_ds_11n_cfg *)req->pbuf;
3383 req->req_id = MLAN_IOCTL_11N_CFG;
3384 bf_cfg->sub_command = MLAN_OID_11N_CFG_TX_BF_CFG;
3385
3386 req->action = action;
3387 memcpy(&bf_cfg->param.tx_bf, tx_bf_cfg, sizeof(mlan_ds_11n_tx_bf_cfg));
3388
3389 /* Send IOCTL request to MLAN */
3390 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3391 if (ret != MLAN_STATUS_SUCCESS)
3392 goto done;
3393
3394 if (action == MLAN_ACT_GET)
3395 memcpy(tx_bf_cfg, &bf_cfg->param.tx_bf,
3396 sizeof(mlan_ds_11n_tx_bf_cfg));
3397
3398 done:
3399 if (ret != MLAN_STATUS_PENDING)
3400 kfree(req);
3401 LEAVE();
3402 return ret;
3403 }
3404
3405 /**
3406 * @brief Handle ioctl resp
3407 *
3408 * @param priv Pointer to moal_private structure
3409 * @param req Pointer to mlan_ioctl_req structure
3410 *
3411 * @return N/A
3412 */
3413 void
woal_process_ioctl_resp(moal_private * priv,mlan_ioctl_req * req)3414 woal_process_ioctl_resp(moal_private *priv, mlan_ioctl_req *req)
3415 {
3416 ENTER();
3417
3418 if (priv == NULL) {
3419 LEAVE();
3420 return;
3421 }
3422 switch (req->req_id) {
3423 case MLAN_IOCTL_GET_INFO:
3424 #ifdef STA_WEXT
3425 #ifdef STA_SUPPORT
3426 if (IS_STA_WEXT(cfg80211_wext) &&
3427 GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
3428 woal_ioctl_get_info_resp(priv,
3429 (mlan_ds_get_info *)req->pbuf);
3430 #endif
3431 #endif
3432 #ifdef UAP_WEXT
3433 #ifdef UAP_SUPPORT
3434 if (IS_UAP_WEXT(cfg80211_wext) &&
3435 GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
3436 woal_ioctl_get_uap_info_resp(priv,
3437 (mlan_ds_get_info *)req->
3438 pbuf);
3439 #endif
3440 #endif
3441 break;
3442 #ifdef STA_WEXT
3443 #ifdef STA_SUPPORT
3444 case MLAN_IOCTL_BSS:
3445 if (IS_STA_WEXT(cfg80211_wext) &&
3446 GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
3447 woal_ioctl_get_bss_resp(priv, (mlan_ds_bss *)req->pbuf);
3448 break;
3449 #endif
3450 #endif
3451 case MLAN_IOCTL_MISC_CFG:
3452 woal_ioctl_get_misc_conf(priv, (mlan_ds_misc_cfg *)req->pbuf);
3453 default:
3454 break;
3455 }
3456
3457 LEAVE();
3458 return;
3459 }
3460
3461 /**
3462 * @brief Get PM info
3463 *
3464 * @param priv A pointer to moal_private structure
3465 * @param pm_info A pointer to mlan_ds_ps_info structure
3466 *
3467 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
3468 */
3469 mlan_status
woal_get_pm_info(moal_private * priv,mlan_ds_ps_info * pm_info)3470 woal_get_pm_info(moal_private *priv, mlan_ds_ps_info *pm_info)
3471 {
3472 mlan_status ret = MLAN_STATUS_SUCCESS;
3473 mlan_ds_pm_cfg *pmcfg = NULL;
3474 mlan_ioctl_req *req = NULL;
3475
3476 ENTER();
3477
3478 /* Allocate an IOCTL request buffer */
3479 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
3480 if (req == NULL) {
3481 PRINTM(MERROR, "Fail to alloc mlan_ds_pm_cfg buffer\n");
3482 ret = MLAN_STATUS_FAILURE;
3483 goto done;
3484 }
3485
3486 /* Fill request buffer */
3487 pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
3488 pmcfg->sub_command = MLAN_OID_PM_INFO;
3489 req->req_id = MLAN_IOCTL_PM_CFG;
3490 req->action = MLAN_ACT_GET;
3491
3492 /* Send IOCTL request to MLAN */
3493 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3494 if (ret == MLAN_STATUS_SUCCESS) {
3495 if (pm_info) {
3496 memcpy(pm_info, &pmcfg->param.ps_info,
3497 sizeof(mlan_ds_ps_info));
3498 }
3499 }
3500 done:
3501 if (ret != MLAN_STATUS_PENDING)
3502 kfree(req);
3503 LEAVE();
3504 return ret;
3505 }
3506
3507 /**
3508 * @brief Get Deep Sleep
3509 *
3510 * @param priv Pointer to the moal_private driver data struct
3511 * @param data Pointer to return deep_sleep setting
3512 *
3513 * @return 0 --success, otherwise fail
3514 */
3515 int
woal_get_deep_sleep(moal_private * priv,t_u32 * data)3516 woal_get_deep_sleep(moal_private *priv, t_u32 *data)
3517 {
3518 int ret = 0;
3519 mlan_ioctl_req *req = NULL;
3520 mlan_ds_pm_cfg *pm = NULL;
3521 mlan_status status = MLAN_STATUS_SUCCESS;
3522
3523 ENTER();
3524
3525 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
3526 if (req == NULL) {
3527 LEAVE();
3528 return -ENOMEM;
3529 }
3530 pm = (mlan_ds_pm_cfg *)req->pbuf;
3531 pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP;
3532 req->req_id = MLAN_IOCTL_PM_CFG;
3533
3534 req->action = MLAN_ACT_GET;
3535 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3536 if (status != MLAN_STATUS_SUCCESS) {
3537 ret = -EFAULT;
3538 goto done;
3539 }
3540 *data = pm->param.auto_deep_sleep.auto_ds;
3541 *(data + 1) = pm->param.auto_deep_sleep.idletime;
3542
3543 done:
3544 if (status != MLAN_STATUS_PENDING)
3545 kfree(req);
3546 LEAVE();
3547 return ret;
3548 }
3549
3550 /**
3551 * @brief Set Deep Sleep
3552 *
3553 * @param priv Pointer to the moal_private driver data struct
3554 * @param wait_option wait option
3555 * @param bdeep_sleep TRUE--enalbe deepsleep, FALSE--disable deepsleep
3556 * @param idletime Idle time for optimized PS API
3557 *
3558 * @return 0 --success, otherwise fail
3559 */
3560 int
woal_set_deep_sleep(moal_private * priv,t_u8 wait_option,BOOLEAN bdeep_sleep,t_u16 idletime)3561 woal_set_deep_sleep(moal_private *priv, t_u8 wait_option, BOOLEAN bdeep_sleep,
3562 t_u16 idletime)
3563 {
3564 int ret = 0;
3565 mlan_ioctl_req *req = NULL;
3566 mlan_ds_pm_cfg *pm = NULL;
3567
3568 ENTER();
3569
3570 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
3571 if (req == NULL) {
3572 LEAVE();
3573 return -ENOMEM;
3574 }
3575 pm = (mlan_ds_pm_cfg *)req->pbuf;
3576 pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP;
3577 req->req_id = MLAN_IOCTL_PM_CFG;
3578
3579 req->action = MLAN_ACT_SET;
3580 if (bdeep_sleep == MTRUE) {
3581 PRINTM(MIOCTL, "Deep Sleep: sleep\n");
3582 pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_ON;
3583 if (idletime)
3584 pm->param.auto_deep_sleep.idletime = idletime;
3585 ret = woal_request_ioctl(priv, req, wait_option);
3586 if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING) {
3587 ret = -EFAULT;
3588 goto done;
3589 }
3590 } else {
3591 PRINTM(MIOCTL, "%lu : Deep Sleep: wakeup\n", jiffies);
3592 pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_OFF;
3593 ret = woal_request_ioctl(priv, req, wait_option);
3594 if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING) {
3595 ret = -EFAULT;
3596 goto done;
3597 }
3598 }
3599 done:
3600 if (ret != MLAN_STATUS_PENDING)
3601 kfree(req);
3602 LEAVE();
3603 return ret;
3604 }
3605
3606 /**
3607 * @brief Cancel CAC period block
3608 *
3609 * @param priv A pointer to moal_private structure
3610 *
3611 * @return N/A
3612 */
3613 void
woal_cancel_cac_block(moal_private * priv)3614 woal_cancel_cac_block(moal_private *priv)
3615 {
3616 ENTER();
3617 /* if during CAC period, wake up wait queue */
3618 if (priv->phandle->cac_period == MTRUE) {
3619 priv->phandle->cac_period = MFALSE;
3620 /* Make sure Chan Report is cancelled */
3621 woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT);
3622 priv->phandle->meas_start_jiffies = 0;
3623 if (priv->phandle->delay_bss_start == MTRUE)
3624 priv->phandle->delay_bss_start = MFALSE;
3625 if (priv->phandle->meas_wait_q_woken == MFALSE) {
3626 priv->phandle->meas_wait_q_woken = MTRUE;
3627 wake_up_interruptible(&priv->phandle->meas_wait_q);
3628 }
3629 #ifdef UAP_SUPPORT
3630 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
3631 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
3632 if (priv->uap_host_based && dfs_offload)
3633 woal_cfg80211_dfs_vendor_event(priv,
3634 event_dfs_cac_aborted,
3635 &priv->chan);
3636 #endif
3637 #endif
3638 #endif
3639 }
3640 LEAVE();
3641 }
3642
3643 /** MEAS report timeout value in seconds */
3644
3645 /**
3646 * @brief Issue MLAN_OID_11H_CHANNEL_CHECK ioctl
3647 *
3648 * @param priv Pointer to the moal_private driver data struct
3649 * @param wait_option wait option
3650 *
3651 * @return 0 --success, otherwise fail
3652 */
3653 int
woal_11h_channel_check_ioctl(moal_private * priv,t_u8 wait_option)3654 woal_11h_channel_check_ioctl(moal_private *priv, t_u8 wait_option)
3655 {
3656 int ret = 0;
3657 mlan_ioctl_req *req = NULL;
3658 mlan_ds_11h_cfg *ds_11hcfg = NULL;
3659 mlan_status status = MLAN_STATUS_SUCCESS;
3660
3661 ENTER();
3662
3663 if (priv->skip_cac) {
3664 LEAVE();
3665 return status;
3666 }
3667
3668 /* Skip sending request/report query when DFS_REPEATER_MODE is on. This
3669 * would get rid of CAC timers before starting BSSes in DFS_REPEATER_MODE
3670 */
3671 if (priv->phandle->dfs_repeater_mode) {
3672 LEAVE();
3673 return status;
3674 }
3675
3676 if (woal_is_any_interface_active(priv->phandle)) {
3677 /* When any other interface is active
3678 * Get rid of CAC timer when drcs is disabled */
3679 t_u16 enable = 0;
3680 ret = woal_mc_policy_cfg(priv, &enable, wait_option,
3681 MLAN_ACT_GET);
3682 if (!enable) {
3683 LEAVE();
3684 return status;
3685 }
3686 }
3687
3688 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
3689 if (req == NULL) {
3690 ret = -ENOMEM;
3691 goto done;
3692 }
3693 ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
3694
3695 ds_11hcfg->sub_command = MLAN_OID_11H_CHANNEL_CHECK;
3696 ds_11hcfg->param.chan_rpt_req.host_based = MFALSE;
3697 req->req_id = MLAN_IOCTL_11H_CFG;
3698 req->action = MLAN_ACT_SET;
3699 /* Send Channel Check command and wait until the report is ready */
3700 status = woal_request_ioctl(priv, req, wait_option);
3701 if (status != MLAN_STATUS_SUCCESS) {
3702 ret = -EFAULT;
3703 goto done;
3704 }
3705
3706 /* set flag from here */
3707 priv->phandle->cac_period = MTRUE;
3708 priv->phandle->meas_start_jiffies = jiffies;
3709 priv->phandle->cac_timer_jiffies =
3710 ds_11hcfg->param.chan_rpt_req.millisec_dwell_time * HZ / 1000;
3711 #ifdef UAP_SUPPORT
3712 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
3713 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
3714 if (priv->uap_host_based && dfs_offload)
3715 woal_cfg80211_dfs_vendor_event(priv, event_dfs_cac_started,
3716 &priv->chan);
3717 #endif
3718 #endif
3719 #endif
3720 done:
3721 if (status != MLAN_STATUS_PENDING)
3722 kfree(req);
3723 LEAVE();
3724 return ret;
3725 }
3726
3727 /**
3728 * @brief Issue MLAN_OID_11H_CHAN_REPORT_REQUEST ioctl to cancel dozer
3729 *
3730 * @param priv Pointer to the moal_private driver data struct
3731 * @param wait_option wait option
3732 *
3733 * @return 0 --success, otherwise fail
3734 */
3735 int
woal_11h_cancel_chan_report_ioctl(moal_private * priv,t_u8 wait_option)3736 woal_11h_cancel_chan_report_ioctl(moal_private *priv, t_u8 wait_option)
3737 {
3738 int ret = 0;
3739 mlan_ioctl_req *req = NULL;
3740 mlan_ds_11h_cfg *ds_11hcfg = NULL;
3741 mlan_status status = MLAN_STATUS_SUCCESS;
3742
3743 ENTER();
3744
3745 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
3746 if (req == NULL) {
3747 ret = -ENOMEM;
3748 goto done;
3749 }
3750 ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
3751
3752 ds_11hcfg->sub_command = MLAN_OID_11H_CHAN_REPORT_REQUEST;
3753 req->req_id = MLAN_IOCTL_11H_CFG;
3754 req->action = MLAN_ACT_SET;
3755 ds_11hcfg->param.chan_rpt_req.millisec_dwell_time = 0;
3756 /* Send Channel Check command and wait until the report is ready */
3757 status = woal_request_ioctl(priv, req, wait_option);
3758 if (status != MLAN_STATUS_SUCCESS) {
3759 ret = -EFAULT;
3760 goto done;
3761 }
3762
3763 done:
3764 if (status != MLAN_STATUS_PENDING)
3765 kfree(req);
3766 LEAVE();
3767 return ret;
3768 }
3769
3770 /**
3771 * @brief set remain channel
3772 *
3773 * @param priv A pointer to moal_private structure
3774 * @param wait_option Wait option
3775 * @param pchan A pointer to mlan_ds_remain_chan structure
3776 *
3777 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
3778 */
3779 mlan_status
woal_set_remain_channel_ioctl(moal_private * priv,t_u8 wait_option,mlan_ds_remain_chan * pchan)3780 woal_set_remain_channel_ioctl(moal_private *priv, t_u8 wait_option,
3781 mlan_ds_remain_chan *pchan)
3782 {
3783 mlan_status ret = MLAN_STATUS_SUCCESS;
3784 mlan_ioctl_req *req = NULL;
3785 mlan_ds_radio_cfg *radio_cfg = NULL;
3786
3787 ENTER();
3788 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
3789 if (req == NULL) {
3790 ret = MLAN_STATUS_FAILURE;
3791 goto done;
3792 }
3793 radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
3794 radio_cfg->sub_command = MLAN_OID_REMAIN_CHAN_CFG;
3795 req->req_id = MLAN_IOCTL_RADIO_CFG;
3796
3797 req->action = MLAN_ACT_SET;
3798 memcpy(&radio_cfg->param.remain_chan, pchan,
3799 sizeof(mlan_ds_remain_chan));
3800 ret = woal_request_ioctl(priv, req, wait_option);
3801 if (ret == MLAN_STATUS_SUCCESS) {
3802 memcpy(pchan, &radio_cfg->param.remain_chan,
3803 sizeof(mlan_ds_remain_chan));
3804 }
3805 done:
3806 if (ret != MLAN_STATUS_PENDING)
3807 kfree(req);
3808 LEAVE();
3809 return ret;
3810 }
3811
3812 #if defined(WIFI_DIRECT_SUPPORT)
3813 /**
3814 * @brief set/get wifi direct mode
3815 *
3816 * @param priv A pointer to moal_private structure
3817 * @param action set or get
3818 * @param mode A pointer to wifi direct mode
3819 *
3820 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
3821 */
3822 mlan_status
woal_wifi_direct_mode_cfg(moal_private * priv,t_u16 action,t_u16 * mode)3823 woal_wifi_direct_mode_cfg(moal_private *priv, t_u16 action, t_u16 *mode)
3824 {
3825 mlan_status ret = MLAN_STATUS_SUCCESS;
3826 mlan_ioctl_req *req = NULL;
3827 mlan_ds_bss *bss = NULL;
3828
3829 ENTER();
3830 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
3831 if (req == NULL) {
3832 ret = MLAN_STATUS_FAILURE;
3833 goto done;
3834 }
3835 bss = (mlan_ds_bss *)req->pbuf;
3836 bss->sub_command = MLAN_OID_WIFI_DIRECT_MODE;
3837 req->req_id = MLAN_IOCTL_BSS;
3838
3839 req->action = action;
3840 if (action == MLAN_ACT_SET)
3841 bss->param.wfd_mode = *mode;
3842 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3843 if (ret == MLAN_STATUS_SUCCESS) {
3844 *mode = bss->param.wfd_mode;
3845 PRINTM(MIOCTL, "ACT=%d, wifi_direct_mode=%d\n", action, *mode);
3846 }
3847 done:
3848 if (ret != MLAN_STATUS_PENDING)
3849 kfree(req);
3850 LEAVE();
3851 return ret;
3852 }
3853
3854 /**
3855 * @brief Set p2p config
3856 *
3857 * @param priv A pointer to moal_private structure
3858 * @param action Action set or get
3859 * @param p2p_config A pointer to mlan_ds_wifi_direct_config structure
3860 *
3861 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
3862 */
3863 mlan_status
woal_p2p_config(moal_private * priv,t_u32 action,mlan_ds_wifi_direct_config * p2p_config)3864 woal_p2p_config(moal_private *priv, t_u32 action,
3865 mlan_ds_wifi_direct_config *p2p_config)
3866 {
3867 mlan_status ret = MLAN_STATUS_SUCCESS;
3868 mlan_ioctl_req *req = NULL;
3869 mlan_ds_misc_cfg *misc_cfg = NULL;
3870
3871 ENTER();
3872 if (!p2p_config) {
3873 LEAVE();
3874 return MLAN_STATUS_FAILURE;
3875 }
3876 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3877 if (req == NULL) {
3878 ret = MLAN_STATUS_FAILURE;
3879 goto done;
3880 }
3881 misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
3882 misc_cfg->sub_command = MLAN_OID_MISC_WIFI_DIRECT_CONFIG;
3883 req->req_id = MLAN_IOCTL_MISC_CFG;
3884 req->action = action;
3885 memcpy(&misc_cfg->param.p2p_config, p2p_config,
3886 sizeof(mlan_ds_wifi_direct_config));
3887 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3888 if (ret == MLAN_STATUS_SUCCESS) {
3889 if (action == MLAN_ACT_GET)
3890 memcpy(p2p_config, &misc_cfg->param.p2p_config,
3891 sizeof(mlan_ds_wifi_direct_config));
3892 }
3893 done:
3894 if (ret != MLAN_STATUS_PENDING)
3895 kfree(req);
3896 LEAVE();
3897 return ret;
3898 }
3899 #endif /* WIFI_DIRECT_SUPPORT */
3900
3901 #ifdef STA_SUPPORT
3902 /**
3903 * @brief Get STA Channel Info
3904 *
3905 * @param priv A pointer to moal_private structure
3906 * @param wait_option Wait option
3907 * @param channel A pointer to channel info
3908 *
3909 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
3910 */
3911 mlan_status
woal_get_sta_channel(moal_private * priv,t_u8 wait_option,chan_band_info * channel)3912 woal_get_sta_channel(moal_private *priv, t_u8 wait_option,
3913 chan_band_info * channel)
3914 {
3915 int ret = 0;
3916 mlan_ioctl_req *req = NULL;
3917 mlan_ds_bss *bss = 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_bss));
3923 if (req == NULL) {
3924 PRINTM(MERROR, "woal_get_sta_channel req alloc fail\n");
3925 ret = MLAN_STATUS_FAILURE;
3926 goto done;
3927 }
3928
3929 /* Fill request buffer */
3930 bss = (mlan_ds_bss *)req->pbuf;
3931 bss->sub_command = MLAN_OID_BSS_CHAN_INFO;
3932 req->req_id = MLAN_IOCTL_BSS;
3933 req->action = MLAN_ACT_GET;
3934
3935 /* Send IOCTL request to MLAN */
3936 status = woal_request_ioctl(priv, req, wait_option);
3937 if (status == MLAN_STATUS_SUCCESS && channel)
3938 memcpy(channel, &(bss->param.sta_channel), sizeof(*channel));
3939
3940 done:
3941 if (status != MLAN_STATUS_PENDING)
3942 kfree(req);
3943 LEAVE();
3944 return status;
3945 }
3946
3947 /**
3948 * @brief Get RSSI info
3949 *
3950 * @param priv A pointer to moal_private structure
3951 * @param wait_option Wait option
3952 * @param signal A pointer tp mlan_ds_get_signal structure
3953 *
3954 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
3955 */
3956 mlan_status
woal_get_signal_info(moal_private * priv,t_u8 wait_option,mlan_ds_get_signal * signal)3957 woal_get_signal_info(moal_private *priv, t_u8 wait_option,
3958 mlan_ds_get_signal *signal)
3959 {
3960 int ret = 0;
3961 mlan_ds_get_info *info = NULL;
3962 mlan_ioctl_req *req = NULL;
3963 mlan_status status = MLAN_STATUS_SUCCESS;
3964 ENTER();
3965
3966 /* Allocate an IOCTL request buffer */
3967 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
3968 if (req == NULL) {
3969 ret = -ENOMEM;
3970 goto done;
3971 }
3972
3973 /* Fill request buffer */
3974 info = (mlan_ds_get_info *)req->pbuf;
3975 info->sub_command = MLAN_OID_GET_SIGNAL;
3976 info->param.signal.selector = ALL_RSSI_INFO_MASK;
3977 req->req_id = MLAN_IOCTL_GET_INFO;
3978 req->action = MLAN_ACT_GET;
3979
3980 /* Send IOCTL request to MLAN */
3981 status = woal_request_ioctl(priv, req, wait_option);
3982 if (status == MLAN_STATUS_SUCCESS) {
3983 if (signal)
3984 memcpy(signal, &info->param.signal,
3985 sizeof(mlan_ds_get_signal));
3986 #ifdef STA_WEXT
3987 if (IS_STA_WEXT(cfg80211_wext)) {
3988 if (info->param.signal.selector & BCN_RSSI_AVG_MASK)
3989 priv->w_stats.qual.level =
3990 info->param.signal.bcn_rssi_avg;
3991 if (info->param.signal.selector & BCN_NF_AVG_MASK)
3992 priv->w_stats.qual.noise =
3993 info->param.signal.bcn_nf_avg;
3994 }
3995 #endif
3996 }
3997 done:
3998 if (status != MLAN_STATUS_PENDING)
3999 kfree(req);
4000 LEAVE();
4001 return status;
4002 }
4003
4004 /**
4005 * @brief Get scan table
4006 *
4007 * @param priv A pointer to moal_private structure
4008 * @param wait_option Wait option
4009 * @param scan_resp A pointer to mlan_scan_resp structure
4010 *
4011 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4012 */
4013 mlan_status
woal_get_scan_table(moal_private * priv,t_u8 wait_option,mlan_scan_resp * scan_resp)4014 woal_get_scan_table(moal_private *priv, t_u8 wait_option,
4015 mlan_scan_resp *scan_resp)
4016 {
4017 int ret = 0;
4018 mlan_ioctl_req *req = NULL;
4019 mlan_ds_scan *scan = NULL;
4020 mlan_status status = MLAN_STATUS_SUCCESS;
4021 ENTER();
4022
4023 if (!scan_resp) {
4024 LEAVE();
4025 return MLAN_STATUS_FAILURE;
4026 }
4027
4028 /* Allocate an IOCTL request buffer */
4029 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
4030 if (req == NULL) {
4031 ret = -ENOMEM;
4032 goto done;
4033 }
4034
4035 /* Fill request buffer */
4036 scan = (mlan_ds_scan *)req->pbuf;
4037 scan->sub_command = MLAN_OID_SCAN_NORMAL;
4038 req->req_id = MLAN_IOCTL_SCAN;
4039 req->action = MLAN_ACT_GET;
4040 memcpy((void *)&scan->param.scan_resp, (void *)scan_resp,
4041 sizeof(mlan_scan_resp));
4042
4043 /* Send IOCTL request to MLAN */
4044 status = woal_request_ioctl(priv, req, wait_option);
4045 if (status == MLAN_STATUS_SUCCESS) {
4046 if (scan_resp) {
4047 memcpy(scan_resp, &scan->param.scan_resp,
4048 sizeof(mlan_scan_resp));
4049 }
4050 }
4051
4052 done:
4053 if (status != MLAN_STATUS_PENDING)
4054 kfree(req);
4055 LEAVE();
4056 return status;
4057 }
4058
4059 /**
4060 * @brief Request a scan
4061 *
4062 * @param priv A pointer to moal_private structure
4063 * @param wait_option Wait option
4064 * @param req_ssid A pointer to mlan_802_11_ssid structure
4065 *
4066 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
4067 */
4068 mlan_status
woal_request_scan(moal_private * priv,t_u8 wait_option,mlan_802_11_ssid * req_ssid)4069 woal_request_scan(moal_private *priv,
4070 t_u8 wait_option, mlan_802_11_ssid *req_ssid)
4071 {
4072 mlan_status ret = MLAN_STATUS_SUCCESS;
4073 moal_handle *handle = priv->phandle;
4074 mlan_ioctl_req *ioctl_req = NULL;
4075 mlan_ds_scan *scan = NULL;
4076 mlan_status status = MLAN_STATUS_SUCCESS;
4077 ENTER();
4078
4079 if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->async_sem)) {
4080 PRINTM(MERROR, "Acquire semaphore error, request_scan\n");
4081 LEAVE();
4082 return MLAN_STATUS_FAILURE;
4083 }
4084 handle->scan_pending_on_block = MTRUE;
4085 handle->scan_priv = priv;
4086
4087 /* Allocate an IOCTL request buffer */
4088 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
4089 if (ioctl_req == NULL) {
4090 ret = MLAN_STATUS_FAILURE;
4091 goto done;
4092 }
4093
4094 scan = (mlan_ds_scan *)ioctl_req->pbuf;
4095
4096 if (req_ssid && req_ssid->ssid_len != 0) {
4097 /* Specific SSID scan */
4098 ioctl_req->req_id = MLAN_IOCTL_SCAN;
4099 ioctl_req->action = MLAN_ACT_SET;
4100
4101 scan->sub_command = MLAN_OID_SCAN_SPECIFIC_SSID;
4102
4103 memcpy(scan->param.scan_req.scan_ssid.ssid,
4104 req_ssid->ssid,
4105 MIN(MLAN_MAX_SSID_LENGTH, req_ssid->ssid_len));
4106 scan->param.scan_req.scan_ssid.ssid_len =
4107 MIN(MLAN_MAX_SSID_LENGTH, req_ssid->ssid_len);
4108 } else {
4109 /* Normal scan */
4110 ioctl_req->req_id = MLAN_IOCTL_SCAN;
4111 ioctl_req->action = MLAN_ACT_SET;
4112
4113 scan->sub_command = MLAN_OID_SCAN_NORMAL;
4114 }
4115 /* Send IOCTL request to MLAN */
4116 status = woal_request_ioctl(priv, ioctl_req, wait_option);
4117
4118 if (status == MLAN_STATUS_FAILURE) {
4119 ret = MLAN_STATUS_FAILURE;
4120 goto done;
4121 }
4122 done:
4123 if (status != MLAN_STATUS_PENDING)
4124 kfree(ioctl_req);
4125
4126 if (ret == MLAN_STATUS_FAILURE) {
4127 handle->scan_pending_on_block = MFALSE;
4128 handle->scan_priv = NULL;
4129 MOAL_REL_SEMAPHORE(&handle->async_sem);
4130 }
4131 LEAVE();
4132 return ret;
4133 }
4134
4135 /**
4136 * @brief Change Adhoc Channel
4137 *
4138 * @param priv A pointer to moal_private structure
4139 * @param channel The channel to be set.
4140 * @param wait_option wait_option
4141 *
4142 * @return MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail
4143 */
4144 mlan_status
woal_change_adhoc_chan(moal_private * priv,int channel,t_u8 wait_option)4145 woal_change_adhoc_chan(moal_private *priv, int channel, t_u8 wait_option)
4146 {
4147 mlan_status ret = MLAN_STATUS_SUCCESS;
4148 mlan_bss_info bss_info;
4149 mlan_ds_bss *bss = NULL;
4150 mlan_ioctl_req *req = NULL;
4151
4152 ENTER();
4153
4154 memset(&bss_info, 0, sizeof(bss_info));
4155
4156 /* Get BSS information */
4157 if (MLAN_STATUS_SUCCESS !=
4158 woal_get_bss_info(priv, wait_option, &bss_info)) {
4159 ret = MLAN_STATUS_FAILURE;
4160 goto done;
4161 }
4162 if (bss_info.bss_mode == MLAN_BSS_MODE_INFRA) {
4163 ret = MLAN_STATUS_SUCCESS;
4164 goto done;
4165 }
4166
4167 /* Allocate an IOCTL request buffer */
4168 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4169 if (req == NULL) {
4170 ret = MLAN_STATUS_FAILURE;
4171 goto done;
4172 }
4173
4174 /* Get current channel */
4175 bss = (mlan_ds_bss *)req->pbuf;
4176 bss->sub_command = MLAN_OID_IBSS_CHANNEL;
4177 req->req_id = MLAN_IOCTL_BSS;
4178 req->action = MLAN_ACT_GET;
4179
4180 /* Send IOCTL request to MLAN */
4181 ret = woal_request_ioctl(priv, req, wait_option);
4182 if (ret != MLAN_STATUS_SUCCESS)
4183 goto done;
4184
4185 if (bss->param.bss_chan.channel == (unsigned int)channel) {
4186 ret = MLAN_STATUS_SUCCESS;
4187 goto done;
4188 }
4189 PRINTM(MINFO, "Updating Channel from %d to %d\n",
4190 (int)bss->param.bss_chan.channel, channel);
4191
4192 if (bss_info.media_connected != MTRUE) {
4193 ret = MLAN_STATUS_SUCCESS;
4194 goto done;
4195 }
4196
4197 /* Do disonnect */
4198 bss->sub_command = MLAN_OID_BSS_STOP;
4199 memset((t_u8 *)&bss->param.bssid, 0, ETH_ALEN);
4200
4201 /* Send IOCTL request to MLAN */
4202 ret = woal_request_ioctl(priv, req, wait_option);
4203 if (ret != MLAN_STATUS_SUCCESS)
4204 goto done;
4205
4206 /* Do specific SSID scanning */
4207 if (MLAN_STATUS_SUCCESS !=
4208 woal_request_scan(priv, wait_option, &bss_info.ssid)) {
4209 ret = MLAN_STATUS_FAILURE;
4210 goto done;
4211 }
4212 /* Start/Join Adhoc network */
4213 bss->sub_command = MLAN_OID_BSS_START;
4214 memset(&bss->param.ssid_bssid, 0, sizeof(mlan_ssid_bssid));
4215 memcpy(&bss->param.ssid_bssid.ssid, &bss_info.ssid,
4216 sizeof(mlan_802_11_ssid));
4217
4218 /* Send IOCTL request to MLAN */
4219 ret = woal_request_ioctl(priv, req, wait_option);
4220
4221 done:
4222 if (ret != MLAN_STATUS_PENDING)
4223 kfree(req);
4224 LEAVE();
4225 return ret;
4226 }
4227
4228 /**
4229 * @brief Find the best network to associate
4230 *
4231 * @param priv A pointer to moal_private structure
4232 * @param wait_option Wait option
4233 * @param ssid_bssid A pointer to mlan_ssid_bssid structure
4234 *
4235 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4236 */
4237 mlan_status
woal_find_best_network(moal_private * priv,t_u8 wait_option,mlan_ssid_bssid * ssid_bssid)4238 woal_find_best_network(moal_private *priv, t_u8 wait_option,
4239 mlan_ssid_bssid *ssid_bssid)
4240 {
4241 mlan_ioctl_req *req = NULL;
4242 mlan_ds_bss *bss = NULL;
4243 mlan_status ret = MLAN_STATUS_SUCCESS;
4244 t_u8 *mac = 0;
4245
4246 ENTER();
4247
4248 if (!ssid_bssid) {
4249 ret = MLAN_STATUS_FAILURE;
4250 goto done;
4251 }
4252
4253 /* Allocate an IOCTL request buffer */
4254 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4255 if (req == NULL) {
4256 ret = MLAN_STATUS_FAILURE;
4257 goto done;
4258 }
4259
4260 /* Fill request buffer */
4261 bss = (mlan_ds_bss *)req->pbuf;
4262 req->req_id = MLAN_IOCTL_BSS;
4263 req->action = MLAN_ACT_GET;
4264 bss->sub_command = MLAN_OID_BSS_FIND_BSS;
4265
4266 memcpy(&bss->param.ssid_bssid, ssid_bssid, sizeof(mlan_ssid_bssid));
4267
4268 /* Send IOCTL request to MLAN */
4269 ret = woal_request_ioctl(priv, req, wait_option);
4270 if (ret == MLAN_STATUS_SUCCESS) {
4271 memcpy(ssid_bssid, &bss->param.ssid_bssid,
4272 sizeof(mlan_ssid_bssid));
4273 mac = (t_u8 *)&ssid_bssid->bssid;
4274 PRINTM(MINFO, "Find network: ssid=%s, " MACSTR ", idx=%d\n",
4275 ssid_bssid->ssid.ssid, MAC2STR(mac),
4276 (int)ssid_bssid->idx);
4277 }
4278
4279 done:
4280 if (ret != MLAN_STATUS_PENDING)
4281 kfree(req);
4282 LEAVE();
4283 return ret;
4284 }
4285
4286 /**
4287 * @brief Check if AP channel is valid for STA Region
4288 *
4289 * @param priv A pointer to moal_private structure
4290 * @param wait_option Wait option
4291 * @param ssid_bssid A pointer to mlan_ssid_bssid structure
4292 *
4293 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4294 */
4295 mlan_status
woal_11d_check_ap_channel(moal_private * priv,t_u8 wait_option,mlan_ssid_bssid * ssid_bssid)4296 woal_11d_check_ap_channel(moal_private *priv, t_u8 wait_option,
4297 mlan_ssid_bssid *ssid_bssid)
4298 {
4299 mlan_ioctl_req *req = NULL;
4300 mlan_ds_bss *bss = NULL;
4301 mlan_status ret = MLAN_STATUS_SUCCESS;
4302 t_u8 *mac = 0;
4303
4304 ENTER();
4305
4306 if (!ssid_bssid) {
4307 ret = MLAN_STATUS_FAILURE;
4308 goto done;
4309 }
4310
4311 /* Allocate an IOCTL request buffer */
4312 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4313 if (req == NULL) {
4314 ret = MLAN_STATUS_FAILURE;
4315 goto done;
4316 }
4317
4318 /* Fill request buffer */
4319 bss = (mlan_ds_bss *)req->pbuf;
4320 req->req_id = MLAN_IOCTL_BSS;
4321 req->action = MLAN_ACT_GET;
4322 bss->sub_command = MLAN_OID_BSS_11D_CHECK_CHANNEL;
4323
4324 memcpy(&bss->param.ssid_bssid, ssid_bssid, sizeof(mlan_ssid_bssid));
4325
4326 mac = (t_u8 *)&ssid_bssid->bssid;
4327 PRINTM(MINFO, "ssid=%s, " MACSTR ", idx=%d\n",
4328 ssid_bssid->ssid.ssid, MAC2STR(mac), (int)ssid_bssid->idx);
4329
4330 /* Send IOCTL request to MLAN */
4331 ret = woal_request_ioctl(priv, req, wait_option);
4332
4333 done:
4334 if (ret != MLAN_STATUS_PENDING)
4335 kfree(req);
4336 LEAVE();
4337 return ret;
4338 }
4339
4340 /**
4341 * @brief Get authentication mode
4342 *
4343 * @param priv A pointer to moal_private structure
4344 * @param wait_option Wait option
4345 * @param auth_mode A pointer to authentication mode
4346 *
4347 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4348 */
4349 mlan_status
woal_get_auth_mode(moal_private * priv,t_u8 wait_option,t_u32 * auth_mode)4350 woal_get_auth_mode(moal_private *priv, t_u8 wait_option, t_u32 *auth_mode)
4351 {
4352 int ret = 0;
4353 mlan_ioctl_req *req = NULL;
4354 mlan_ds_sec_cfg *sec = NULL;
4355 mlan_status status = MLAN_STATUS_SUCCESS;
4356 ENTER();
4357
4358 /* Allocate an IOCTL request buffer */
4359 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
4360 if (req == NULL) {
4361 ret = -ENOMEM;
4362 goto done;
4363 }
4364
4365 /* Fill request buffer */
4366 sec = (mlan_ds_sec_cfg *)req->pbuf;
4367 sec->sub_command = MLAN_OID_SEC_CFG_AUTH_MODE;
4368 req->req_id = MLAN_IOCTL_SEC_CFG;
4369 req->action = MLAN_ACT_GET;
4370
4371 /* Send IOCTL request to MLAN */
4372 status = woal_request_ioctl(priv, req, wait_option);
4373 if (status == MLAN_STATUS_SUCCESS && auth_mode)
4374 *auth_mode = sec->param.auth_mode;
4375 done:
4376 if (status != MLAN_STATUS_PENDING)
4377 kfree(req);
4378 LEAVE();
4379 return status;
4380 }
4381
4382 /**
4383 * @brief Get encrypt mode
4384 *
4385 * @param priv A pointer to moal_private structure
4386 * @param wait_option Wait option
4387 * @param encrypt_mode A pointer to encrypt mode
4388 *
4389 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4390 */
4391 mlan_status
woal_get_encrypt_mode(moal_private * priv,t_u8 wait_option,t_u32 * encrypt_mode)4392 woal_get_encrypt_mode(moal_private *priv, t_u8 wait_option, t_u32 *encrypt_mode)
4393 {
4394 int ret = 0;
4395 mlan_ioctl_req *req = NULL;
4396 mlan_ds_sec_cfg *sec = NULL;
4397 mlan_status status = MLAN_STATUS_SUCCESS;
4398
4399 ENTER();
4400
4401 /* Allocate an IOCTL request buffer */
4402 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
4403 if (req == NULL) {
4404 ret = -ENOMEM;
4405 goto done;
4406 }
4407
4408 /* Fill request buffer */
4409 sec = (mlan_ds_sec_cfg *)req->pbuf;
4410 sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_MODE;
4411 req->req_id = MLAN_IOCTL_SEC_CFG;
4412 req->action = MLAN_ACT_GET;
4413
4414 /* Send IOCTL request to MLAN */
4415 status = woal_request_ioctl(priv, req, wait_option);
4416 if (status == MLAN_STATUS_SUCCESS && encrypt_mode)
4417 *encrypt_mode = sec->param.encrypt_mode;
4418 done:
4419 if (status != MLAN_STATUS_PENDING)
4420 kfree(req);
4421 LEAVE();
4422 return status;
4423 }
4424
4425 /**
4426 * @brief Get WPA enable
4427 *
4428 * @param priv A pointer to moal_private structure
4429 * @param wait_option Wait option
4430 * @param enable A pointer to wpa enable status
4431 *
4432 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4433 */
4434 mlan_status
woal_get_wpa_enable(moal_private * priv,t_u8 wait_option,t_u32 * enable)4435 woal_get_wpa_enable(moal_private *priv, t_u8 wait_option, t_u32 *enable)
4436 {
4437 int ret = 0;
4438 mlan_ioctl_req *req = NULL;
4439 mlan_ds_sec_cfg *sec = NULL;
4440 mlan_status status = MLAN_STATUS_SUCCESS;
4441
4442 ENTER();
4443
4444 /* Allocate an IOCTL request buffer */
4445 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
4446 if (req == NULL) {
4447 ret = -ENOMEM;
4448 goto done;
4449 }
4450
4451 /* Fill request buffer */
4452 sec = (mlan_ds_sec_cfg *)req->pbuf;
4453 sec->sub_command = MLAN_OID_SEC_CFG_WPA_ENABLED;
4454 req->req_id = MLAN_IOCTL_SEC_CFG;
4455 req->action = MLAN_ACT_GET;
4456
4457 /* Send IOCTL request to MLAN */
4458 status = woal_request_ioctl(priv, req, wait_option);
4459 if (status == MLAN_STATUS_SUCCESS && enable)
4460 *enable = sec->param.wpa_enabled;
4461 done:
4462 if (status != MLAN_STATUS_PENDING)
4463 kfree(req);
4464 LEAVE();
4465 return status;
4466 }
4467
4468 /**
4469 * @brief Set authentication mode
4470 *
4471 * @param priv A pointer to moal_private structure
4472 * @param wait_option Wait option
4473 * @param auth_mode Authentication mode
4474 *
4475 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4476 */
4477 mlan_status
woal_set_auth_mode(moal_private * priv,t_u8 wait_option,t_u32 auth_mode)4478 woal_set_auth_mode(moal_private *priv, t_u8 wait_option, t_u32 auth_mode)
4479 {
4480 int ret = 0;
4481 mlan_ioctl_req *req = NULL;
4482 mlan_ds_sec_cfg *sec = NULL;
4483 mlan_status status = MLAN_STATUS_SUCCESS;
4484 ENTER();
4485
4486 /* Allocate an IOCTL request buffer */
4487 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
4488 if (req == NULL) {
4489 ret = -ENOMEM;
4490 goto done;
4491 }
4492
4493 /* Fill request buffer */
4494 sec = (mlan_ds_sec_cfg *)req->pbuf;
4495 sec->sub_command = MLAN_OID_SEC_CFG_AUTH_MODE;
4496 req->req_id = MLAN_IOCTL_SEC_CFG;
4497 req->action = MLAN_ACT_SET;
4498 sec->param.auth_mode = auth_mode;
4499
4500 /* Send IOCTL request to MLAN */
4501 status = woal_request_ioctl(priv, req, wait_option);
4502 done:
4503 if (status != MLAN_STATUS_PENDING)
4504 kfree(req);
4505 LEAVE();
4506 return status;
4507 }
4508
4509 /**
4510 * @brief Set encrypt mode
4511 *
4512 * @param priv A pointer to moal_private structure
4513 * @param wait_option Wait option
4514 * @param encrypt_mode Encryption mode
4515 *
4516 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4517 */
4518 mlan_status
woal_set_encrypt_mode(moal_private * priv,t_u8 wait_option,t_u32 encrypt_mode)4519 woal_set_encrypt_mode(moal_private *priv, t_u8 wait_option, t_u32 encrypt_mode)
4520 {
4521 int ret = 0;
4522 mlan_ioctl_req *req = NULL;
4523 mlan_ds_sec_cfg *sec = NULL;
4524 mlan_status status = MLAN_STATUS_SUCCESS;
4525 ENTER();
4526
4527 /* Allocate an IOCTL request buffer */
4528 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
4529 if (req == NULL) {
4530 ret = -ENOMEM;
4531 goto done;
4532 }
4533
4534 /* Fill request buffer */
4535 sec = (mlan_ds_sec_cfg *)req->pbuf;
4536 sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_MODE;
4537 req->req_id = MLAN_IOCTL_SEC_CFG;
4538 req->action = MLAN_ACT_SET;
4539 sec->param.encrypt_mode = encrypt_mode;
4540
4541 /* Send IOCTL request to MLAN */
4542 status = woal_request_ioctl(priv, req, wait_option);
4543 done:
4544 if (status != MLAN_STATUS_PENDING)
4545 kfree(req);
4546 LEAVE();
4547 return status;
4548 }
4549
4550 /**
4551 * @brief Set wpa enable
4552 *
4553 * @param priv A pointer to moal_private structure
4554 * @param wait_option Wait option
4555 * @param enable MTRUE or MFALSE
4556 *
4557 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4558 */
4559 mlan_status
woal_set_wpa_enable(moal_private * priv,t_u8 wait_option,t_u32 enable)4560 woal_set_wpa_enable(moal_private *priv, t_u8 wait_option, t_u32 enable)
4561 {
4562 int ret = 0;
4563 mlan_ioctl_req *req = NULL;
4564 mlan_ds_sec_cfg *sec = NULL;
4565 mlan_status status = MLAN_STATUS_SUCCESS;
4566 ENTER();
4567
4568 /* Allocate an IOCTL request buffer */
4569 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
4570 if (req == NULL) {
4571 ret = -ENOMEM;
4572 goto done;
4573 }
4574
4575 /* Fill request buffer */
4576 sec = (mlan_ds_sec_cfg *)req->pbuf;
4577 sec->sub_command = MLAN_OID_SEC_CFG_WPA_ENABLED;
4578 req->req_id = MLAN_IOCTL_SEC_CFG;
4579 req->action = MLAN_ACT_SET;
4580 sec->param.wpa_enabled = enable;
4581
4582 /* Send IOCTL request to MLAN */
4583 status = woal_request_ioctl(priv, req, wait_option);
4584 done:
4585 if (status != MLAN_STATUS_PENDING)
4586 kfree(req);
4587 LEAVE();
4588 return status;
4589 }
4590
4591 /**
4592 * @brief enable wep key
4593 *
4594 * @param priv A pointer to moal_private structure
4595 * @param wait_option Wait option
4596 *
4597 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4598 */
4599 mlan_status
woal_enable_wep_key(moal_private * priv,t_u8 wait_option)4600 woal_enable_wep_key(moal_private *priv, t_u8 wait_option)
4601 {
4602 int ret = 0;
4603 mlan_ioctl_req *req = NULL;
4604 mlan_ds_sec_cfg *sec = NULL;
4605 mlan_status status = MLAN_STATUS_SUCCESS;
4606 ENTER();
4607
4608 /* Allocate an IOCTL request buffer */
4609 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
4610 if (req == NULL) {
4611 ret = -ENOMEM;
4612 goto done;
4613 }
4614
4615 /* Fill request buffer */
4616 sec = (mlan_ds_sec_cfg *)req->pbuf;
4617 sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
4618 req->req_id = MLAN_IOCTL_SEC_CFG;
4619 req->action = MLAN_ACT_SET;
4620 sec->param.encrypt_key.key_disable = MFALSE;
4621 sec->param.encrypt_key.key_index = MLAN_KEY_INDEX_DEFAULT;
4622 sec->param.encrypt_key.is_current_wep_key = MTRUE;
4623
4624 /* Send IOCTL request to MLAN */
4625 status = woal_request_ioctl(priv, req, wait_option);
4626 done:
4627 if (status != MLAN_STATUS_PENDING)
4628 kfree(req);
4629 LEAVE();
4630 return status;
4631 }
4632
4633 /**
4634 * @brief Request user scan
4635 *
4636 * @param priv A pointer to moal_private structure
4637 * @param wait_option Wait option
4638 * @param scan_cfg A pointer to wlan_user_scan_config structure
4639 *
4640 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
4641 */
4642 mlan_status
woal_request_userscan(moal_private * priv,t_u8 wait_option,wlan_user_scan_cfg * scan_cfg)4643 woal_request_userscan(moal_private *priv,
4644 t_u8 wait_option, wlan_user_scan_cfg *scan_cfg)
4645 {
4646 mlan_status ret = MLAN_STATUS_SUCCESS;
4647 mlan_ioctl_req *ioctl_req = NULL;
4648 mlan_ds_scan *scan = NULL;
4649 mlan_status status = MLAN_STATUS_SUCCESS;
4650 moal_handle *handle = priv->phandle;
4651 ENTER();
4652
4653 if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->async_sem)) {
4654 PRINTM(MERROR, "Acquire semaphore error, request_scan\n");
4655 LEAVE();
4656 return MLAN_STATUS_FAILURE;
4657 }
4658 handle->scan_pending_on_block = MTRUE;
4659 handle->scan_priv = priv;
4660
4661 /* Allocate an IOCTL request buffer */
4662 ioctl_req =
4663 woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan) +
4664 sizeof(wlan_user_scan_cfg));
4665 if (ioctl_req == NULL) {
4666 ret = MLAN_STATUS_FAILURE;
4667 goto done;
4668 }
4669
4670 scan = (mlan_ds_scan *)ioctl_req->pbuf;
4671 scan->sub_command = MLAN_OID_SCAN_USER_CONFIG;
4672 ioctl_req->req_id = MLAN_IOCTL_SCAN;
4673 ioctl_req->action = MLAN_ACT_SET;
4674 memcpy(scan->param.user_scan.scan_cfg_buf, scan_cfg,
4675 sizeof(wlan_user_scan_cfg));
4676 /* Send IOCTL request to MLAN */
4677 status = woal_request_ioctl(priv, ioctl_req, wait_option);
4678 if (status == MLAN_STATUS_FAILURE) {
4679 ret = MLAN_STATUS_FAILURE;
4680 goto done;
4681 }
4682
4683 done:
4684 if (status != MLAN_STATUS_PENDING)
4685 kfree(ioctl_req);
4686
4687 if (ret == MLAN_STATUS_FAILURE) {
4688 handle->scan_pending_on_block = MFALSE;
4689 handle->scan_priv = NULL;
4690 MOAL_REL_SEMAPHORE(&handle->async_sem);
4691 }
4692 LEAVE();
4693 return ret;
4694 }
4695
4696 /**
4697 * @brief woal_get_scan_config
4698 *
4699 * @param priv A pointer to moal_private structure
4700 * @param scan_cfg A pointer to scan_cfg structure
4701 *
4702 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
4703 */
4704 mlan_status
woal_get_scan_config(moal_private * priv,mlan_scan_cfg * scan_cfg)4705 woal_get_scan_config(moal_private *priv, mlan_scan_cfg *scan_cfg)
4706 {
4707 mlan_status ret = MLAN_STATUS_SUCCESS;
4708 mlan_ds_scan *scan = NULL;
4709 mlan_ioctl_req *req = NULL;
4710
4711 ENTER();
4712
4713 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
4714 if (req == NULL) {
4715 ret = MLAN_STATUS_FAILURE;
4716 goto done;
4717 }
4718 scan = (mlan_ds_scan *)req->pbuf;
4719 scan->sub_command = MLAN_OID_SCAN_CONFIG;
4720 req->req_id = MLAN_IOCTL_SCAN;
4721 req->action = MLAN_ACT_GET;
4722 memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
4723 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4724 if (ret == MLAN_STATUS_SUCCESS && scan_cfg)
4725 memcpy(scan_cfg, &scan->param.scan_cfg, sizeof(mlan_scan_cfg));
4726
4727 done:
4728 if (ret != MLAN_STATUS_PENDING)
4729 kfree(req);
4730 LEAVE();
4731 return ret;
4732 }
4733
4734 /**
4735 * @brief set scan time
4736 *
4737 * @param priv A pointer to moal_private structure
4738 * @param active_scan_time Active scan time
4739 * @param passive_scan_time Passive scan time
4740 * @param specific_scan_time Specific scan time
4741 *
4742 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
4743 */
4744 mlan_status
woal_set_scan_time(moal_private * priv,t_u16 active_scan_time,t_u16 passive_scan_time,t_u16 specific_scan_time)4745 woal_set_scan_time(moal_private *priv, t_u16 active_scan_time,
4746 t_u16 passive_scan_time, t_u16 specific_scan_time)
4747 {
4748 mlan_status ret = MLAN_STATUS_SUCCESS;
4749 mlan_ds_scan *scan = NULL;
4750 mlan_ioctl_req *req = NULL;
4751 mlan_scan_cfg scan_cfg;
4752
4753 ENTER();
4754
4755 memset(&scan_cfg, 0, sizeof(scan_cfg));
4756 if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) {
4757 ret = MLAN_STATUS_FAILURE;
4758 goto done;
4759 }
4760 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
4761 if (req == NULL) {
4762 ret = MLAN_STATUS_FAILURE;
4763 goto done;
4764 }
4765 scan = (mlan_ds_scan *)req->pbuf;
4766 scan->sub_command = MLAN_OID_SCAN_CONFIG;
4767 req->req_id = MLAN_IOCTL_SCAN;
4768 req->action = MLAN_ACT_SET;
4769 memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
4770 scan_cfg.scan_time.active_scan_time = active_scan_time;
4771 scan_cfg.scan_time.specific_scan_time = specific_scan_time;
4772 scan_cfg.scan_time.passive_scan_time = passive_scan_time;
4773 PRINTM(MIOCTL, "Set specific=%d, active=%d, passive=%d\n",
4774 (int)active_scan_time, (int)passive_scan_time,
4775 (int)specific_scan_time);
4776 memcpy(&scan->param.scan_cfg, &scan_cfg, sizeof(mlan_scan_cfg));
4777 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4778
4779 done:
4780 if (ret != MLAN_STATUS_PENDING)
4781 kfree(req);
4782 LEAVE();
4783 return ret;
4784 }
4785
4786 /**
4787 * @brief request scan
4788 *
4789 * @param priv A pointer to moal_private structure
4790 * @param scan_cfg A pointer to wlan_user_scan_cfg structure
4791 *
4792 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
4793 */
4794 mlan_status
woal_do_scan(moal_private * priv,wlan_user_scan_cfg * scan_cfg)4795 woal_do_scan(moal_private *priv, wlan_user_scan_cfg *scan_cfg)
4796 {
4797 mlan_status ret = MLAN_STATUS_SUCCESS;
4798 moal_handle *handle = priv->phandle;
4799
4800 ENTER();
4801 if (handle->scan_pending_on_block == MTRUE) {
4802 PRINTM(MINFO, "scan already in processing...\n");
4803 LEAVE();
4804 return ret;
4805 }
4806 #ifdef REASSOCIATION
4807 if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->reassoc_sem)) {
4808 PRINTM(MERROR, "Acquire semaphore error, woal_do_combo_scan\n");
4809 LEAVE();
4810 return -EBUSY;
4811 }
4812 #endif /* REASSOCIATION */
4813 priv->report_scan_result = MTRUE;
4814
4815 if (!scan_cfg)
4816 ret = woal_request_scan(priv, MOAL_NO_WAIT, NULL);
4817 else
4818 ret = woal_request_userscan(priv, MOAL_NO_WAIT, scan_cfg);
4819
4820 #ifdef REASSOCIATION
4821 MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
4822 #endif
4823 LEAVE();
4824 return ret;
4825 }
4826
4827 /**
4828 * @brief Cancel pending scan
4829 *
4830 * @param priv A pointer to moal_private structure
4831 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
4832 */
4833 mlan_status
woal_cancel_scan(moal_private * priv,t_u8 wait_option)4834 woal_cancel_scan(moal_private *priv, t_u8 wait_option)
4835 {
4836 mlan_ioctl_req *req = NULL;
4837 mlan_status ret = MLAN_STATUS_SUCCESS;
4838 moal_handle *handle = priv->phandle;
4839 moal_private *scan_priv = handle->scan_priv;
4840 #ifdef STA_CFG80211
4841 unsigned long flags;
4842 #endif
4843
4844 /* If scan is in process, cancel the scan command */
4845 if (!handle->scan_pending_on_block || !scan_priv)
4846 return ret;
4847 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
4848 if (req == NULL) {
4849 ret = MLAN_STATUS_FAILURE;
4850 goto done;
4851 }
4852 req->req_id = MLAN_IOCTL_SCAN;
4853 req->action = MLAN_ACT_SET;
4854 ((mlan_ds_scan *)req->pbuf)->sub_command = MLAN_OID_SCAN_CANCEL;
4855 ret = woal_request_ioctl(scan_priv, req, wait_option);
4856 handle->scan_pending_on_block = MFALSE;
4857 MOAL_REL_SEMAPHORE(&handle->async_sem);
4858 #ifdef STA_CFG80211
4859 spin_lock_irqsave(&handle->scan_req_lock, flags);
4860 if (IS_STA_CFG80211(cfg80211_wext) && handle->scan_request) {
4861 /** some supplicant can not handle SCAN abort event */
4862 if (scan_priv->bss_type == MLAN_BSS_TYPE_STA)
4863 woal_cfg80211_scan_done(handle->scan_request, MTRUE);
4864 else
4865 woal_cfg80211_scan_done(handle->scan_request, MFALSE);
4866 handle->scan_request = NULL;
4867 }
4868 spin_unlock_irqrestore(&handle->scan_req_lock, flags);
4869 #endif
4870 /* add 10ms delay, incase firmware delay 0x7f event after scan cancel command response */
4871 woal_sched_timeout(10);
4872 handle->scan_priv = NULL;
4873 done:
4874 if (ret != MLAN_STATUS_PENDING)
4875 kfree(req);
4876 return ret;
4877 }
4878
4879 /**
4880 * @brief find ssid in scan_table
4881 *
4882 * @param priv A pointer to moal_private
4883 * @param ssid_bssid A pointer to mlan_ssid_bssid structure
4884 *
4885 *
4886 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
4887 */
4888 int
woal_find_essid(moal_private * priv,mlan_ssid_bssid * ssid_bssid,t_u8 wait_option)4889 woal_find_essid(moal_private *priv, mlan_ssid_bssid *ssid_bssid,
4890 t_u8 wait_option)
4891 {
4892 int ret = 0;
4893 mlan_scan_resp scan_resp;
4894 struct timeval t;
4895 ENTER();
4896
4897 if (MLAN_STATUS_SUCCESS !=
4898 woal_get_scan_table(priv, wait_option, &scan_resp)) {
4899 LEAVE();
4900 return MLAN_STATUS_FAILURE;
4901 }
4902 #ifdef STA_CFG80211
4903 if (priv->ft_pre_connect) {
4904 /** skip check the scan age out */
4905 ret = woal_find_best_network(priv, wait_option, ssid_bssid);
4906 LEAVE();
4907 return ret;
4908 }
4909 #endif
4910 do_gettimeofday(&t);
4911 /** scan result timeout value */
4912 #define SCAN_RESULT_AGEOUT 10
4913 if (t.tv_sec > (scan_resp.age_in_secs + SCAN_RESULT_AGEOUT)) {
4914 LEAVE();
4915 return MLAN_STATUS_FAILURE;
4916 }
4917 ret = woal_find_best_network(priv, wait_option, ssid_bssid);
4918 LEAVE();
4919 return ret;
4920 }
4921
4922 /**
4923 * @brief auto reconnection configure
4924 *
4925 * @param priv Pointer to moal_private structure
4926 * @param cfg_mode configure mode
4927 * @param roam_offload_cfg Pointer to woal_roam_offload_cfg structure
4928 *
4929 * @return Number of bytes written, negative for failure.
4930 */
4931 mlan_status
woal_config_fw_roaming(moal_private * priv,t_u8 cfg_mode,woal_roam_offload_cfg * roam_offload_cfg)4932 woal_config_fw_roaming(moal_private *priv, t_u8 cfg_mode,
4933 woal_roam_offload_cfg * roam_offload_cfg)
4934 {
4935 mlan_ioctl_req *ioctl_req = NULL;
4936 mlan_ds_misc_cfg *misc = NULL;
4937 mlan_ds_misc_roam_offload *roam = NULL;
4938 mlan_status status = MLAN_STATUS_SUCCESS;
4939 int ret = 0;
4940
4941 ENTER();
4942
4943 if (!priv || !priv->phandle) {
4944 PRINTM(MERROR, "priv or handle is null\n");
4945 ret = -EFAULT;
4946 goto done;
4947 }
4948
4949 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
4950 if (ioctl_req == NULL) {
4951 ret = -ENOMEM;
4952 goto done;
4953 }
4954
4955 misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
4956 misc->sub_command = MLAN_OID_MISC_ROAM_OFFLOAD;
4957 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
4958
4959 roam = (mlan_ds_misc_roam_offload *) & misc->param.roam_offload;
4960 roam->aplist.ap_num = 0;
4961 ioctl_req->action = MLAN_ACT_SET;
4962 roam->enable = priv->phandle->fw_roam_enable;
4963 roam->config_mode = cfg_mode;
4964
4965 if ((roam->config_mode == ROAM_OFFLOAD_ENABLE) && roam_offload_cfg) {
4966 roam->userset_passphrase = roam_offload_cfg->userset_passphrase;
4967 if (roam->userset_passphrase)
4968 roam->enable = 0;
4969 }
4970 if (roam->config_mode == ROAM_OFFLOAD_PARAM_CFG) {
4971 memcpy((t_u8 *)&roam->bssid_reconnect,
4972 (t_u8 *)&roam_offload_cfg->bssid, MLAN_MAC_ADDR_LENGTH);
4973 if (roam_offload_cfg->ssid_list.ssid_num) {
4974 memcpy((t_u8 *)&roam->ssid_list,
4975 (t_u8 *)&roam_offload_cfg->ssid_list,
4976 sizeof(mlan_ds_misc_ssid_list));
4977 }
4978 if (roam_offload_cfg->black_list.ap_num) {
4979 memcpy((t_u8 *)&roam->black_list,
4980 (t_u8 *)&roam_offload_cfg->black_list,
4981 sizeof(mlan_ds_misc_roam_offload_aplist));
4982 }
4983 roam->trigger_condition = roam_offload_cfg->trigger_condition;
4984 roam->retry_count = roam_offload_cfg->retry_count;
4985 if (roam_offload_cfg->rssi_param_set_flag) {
4986 roam->para_rssi.set_flag = 1;
4987 roam->para_rssi.max_rssi = roam_offload_cfg->max_rssi;
4988 roam->para_rssi.min_rssi = roam_offload_cfg->min_rssi;
4989 roam->para_rssi.step_rssi = roam_offload_cfg->step_rssi;
4990 }
4991 if (roam_offload_cfg->band_rssi_flag) {
4992 roam->band_rssi_flag = roam_offload_cfg->band_rssi_flag;
4993 memcpy((t_u8 *)&roam->band_rssi,
4994 (t_u8 *)&roam_offload_cfg->band_rssi,
4995 sizeof(mlan_ds_misc_band_rssi));
4996 }
4997 if (roam_offload_cfg->bgscan_set_flag) {
4998 roam->bgscan_set_flag =
4999 roam_offload_cfg->bgscan_set_flag;
5000 memcpy((t_u8 *)&roam->bgscan_cfg,
5001 (t_u8 *)&roam_offload_cfg->bgscan_cfg,
5002 sizeof(mlan_ds_misc_bgscan_cfg));
5003 }
5004 if (roam_offload_cfg->ees_param_set_flag) {
5005 roam->ees_param_set_flag =
5006 roam_offload_cfg->ees_param_set_flag;
5007 memcpy((t_u8 *)&roam->ees_cfg,
5008 (t_u8 *)&roam_offload_cfg->ees_cfg,
5009 sizeof(mlan_ds_misc_ees_cfg));
5010 }
5011 roam->bcn_miss_threshold = roam_offload_cfg->bcn_miss_threshold;
5012 roam->pre_bcn_miss_threshold =
5013 roam_offload_cfg->pre_bcn_miss_threshold;
5014 roam->repeat_count = roam_offload_cfg->repeat_count;
5015 }
5016 if (roam->config_mode == ROAM_OFFLOAD_SUSPEND_CFG) {
5017 memcpy(roam->bssid_reconnect,
5018 priv->phandle->auto_reconnect_bssid,
5019 MLAN_MAC_ADDR_LENGTH);
5020 roam->ssid_list.ssid_num = 1;
5021 memcpy((t_u8 *)&roam->ssid_list.ssids[0].ssid,
5022 (t_u8 *)&priv->phandle->auto_reconnect_ssid.ssid,
5023 priv->phandle->auto_reconnect_ssid.ssid_len);
5024
5025 roam->retry_count = priv->phandle->auto_reconnect_retry_count;
5026 }
5027
5028 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
5029 if (status != MLAN_STATUS_SUCCESS) {
5030 ret = -EFAULT;
5031 goto done;
5032 }
5033
5034 done:
5035 if (status != MLAN_STATUS_PENDING)
5036 kfree(ioctl_req);
5037
5038 LEAVE();
5039 return ret;
5040 }
5041
5042 /**
5043 * @brief Request user scan
5044 *
5045 * @param priv A pointer to moal_private structure
5046 * @param wait_option Wait option
5047 * @param scan_cfg A pointer to wlan_bgscan_cfg structure
5048 *
5049 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5050 */
5051 mlan_status
woal_request_bgscan(moal_private * priv,t_u8 wait_option,wlan_bgscan_cfg * scan_cfg)5052 woal_request_bgscan(moal_private *priv,
5053 t_u8 wait_option, wlan_bgscan_cfg *scan_cfg)
5054 {
5055 mlan_status ret = MLAN_STATUS_SUCCESS;
5056 mlan_ioctl_req *ioctl_req = NULL;
5057 mlan_ds_scan *scan = NULL;
5058 mlan_status status = MLAN_STATUS_SUCCESS;
5059 ENTER();
5060
5061 /* Allocate an IOCTL request buffer */
5062 ioctl_req =
5063 woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan) +
5064 sizeof(wlan_bgscan_cfg));
5065 if (ioctl_req == NULL) {
5066 ret = MLAN_STATUS_FAILURE;
5067 goto done;
5068 }
5069
5070 scan = (mlan_ds_scan *)ioctl_req->pbuf;
5071 scan->sub_command = MLAN_OID_SCAN_BGSCAN_CONFIG;
5072 ioctl_req->req_id = MLAN_IOCTL_SCAN;
5073 ioctl_req->action = MLAN_ACT_SET;
5074 memcpy(scan->param.user_scan.scan_cfg_buf, scan_cfg,
5075 sizeof(wlan_bgscan_cfg));
5076
5077 /* Send IOCTL request to MLAN */
5078 status = woal_request_ioctl(priv, ioctl_req, wait_option);
5079 if (status == MLAN_STATUS_FAILURE) {
5080 ret = MLAN_STATUS_FAILURE;
5081 goto done;
5082 }
5083 done:
5084 if (status != MLAN_STATUS_PENDING)
5085 kfree(ioctl_req);
5086 LEAVE();
5087 return ret;
5088 }
5089
5090 /**
5091 * @brief set bgscan config
5092 *
5093 * @param priv A pointer to moal_private structure
5094 * @param buf A pointer to scan command buf
5095 * @param length buf length
5096 *
5097 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5098 */
5099 mlan_status
woal_set_bg_scan(moal_private * priv,char * buf,int length)5100 woal_set_bg_scan(moal_private *priv, char *buf, int length)
5101 {
5102 t_u8 *ptr = buf + strlen("BGSCAN-CONFIG") + 1;
5103 int buf_left = length - (strlen("BGSCAN-CONFIG") + 1);
5104 int band = 0;
5105 int num_ssid = 0;
5106 int ssid_len = 0;
5107 mlan_status ret = MLAN_STATUS_FAILURE;
5108
5109 ENTER();
5110 memset(&priv->scan_cfg, 0, sizeof(priv->scan_cfg));
5111 priv->scan_cfg.report_condition =
5112 BG_SCAN_SSID_MATCH | BG_SCAN_WAIT_ALL_CHAN_DONE;
5113 while (buf_left >= 2) {
5114 switch (*ptr) {
5115 case WEXT_CSCAN_SSID_SECTION:
5116 ssid_len = *(ptr + 1);
5117 if ((buf_left < (ssid_len + 2)) ||
5118 (ssid_len > MLAN_MAX_SSID_LENGTH)) {
5119 PRINTM(MERROR,
5120 "Invalid ssid, buf_left=%d, ssid_len=%d\n",
5121 buf_left, ssid_len);
5122 buf_left = 0;
5123 break;
5124 }
5125 if (ssid_len &&
5126 (num_ssid < (MRVDRV_MAX_SSID_LIST_LENGTH - 1))) {
5127 strncpy(priv->scan_cfg.ssid_list[num_ssid].ssid,
5128 ptr + 2, ssid_len);
5129 priv->scan_cfg.ssid_list[num_ssid].max_len = 0;
5130 PRINTM(MIOCTL, "BG scan: ssid=%s\n",
5131 priv->scan_cfg.ssid_list[num_ssid].ssid);
5132 num_ssid++;
5133 }
5134 buf_left -= ssid_len + 2;
5135 ptr += ssid_len + 2;
5136 break;
5137 case WEXT_BGSCAN_RSSI_SECTION:
5138 priv->scan_cfg.report_condition =
5139 BG_SCAN_SSID_RSSI_MATCH |
5140 BG_SCAN_WAIT_ALL_CHAN_DONE;
5141 priv->scan_cfg.rssi_threshold = ptr[1];
5142 PRINTM(MIOCTL, "BG scan: rssi_threshold=%d\n",
5143 (int)priv->scan_cfg.rssi_threshold);
5144 ptr += 2;
5145 buf_left -= 2;
5146 break;
5147 case WEXT_BGSCAN_REPEAT_SECTION:
5148 priv->scan_cfg.repeat_count = (t_u16)ptr[1];
5149 PRINTM(MIOCTL, "BG scan: repeat_count=%d\n",
5150 (int)priv->scan_cfg.repeat_count);
5151 ptr += 2;
5152 buf_left -= 2;
5153 break;
5154 case WEXT_BGSCAN_INTERVAL_SECTION:
5155 if (buf_left < 3) {
5156 PRINTM(MERROR,
5157 "Invalid scan_interval, buf_left=%d\n",
5158 buf_left);
5159 buf_left = 0;
5160 break;
5161 }
5162 priv->scan_cfg.scan_interval =
5163 (ptr[2] << 8 | ptr[1]) * 1000;
5164 PRINTM(MIOCTL, "BG scan: scan_interval=%d\n",
5165 (int)priv->scan_cfg.scan_interval);
5166 ptr += 3;
5167 buf_left -= 3;
5168 break;
5169 default:
5170 buf_left = 0;
5171 break;
5172 }
5173 }
5174 /** set bgscan when ssid_num > 0 */
5175 if (num_ssid) {
5176 if (MLAN_STATUS_SUCCESS != woal_get_band(priv, &band)) {
5177 ret = MLAN_STATUS_FAILURE;
5178 goto done;
5179 }
5180 switch (band) {
5181 case WIFI_FREQUENCY_BAND_2GHZ:
5182 priv->scan_cfg.chan_list[0].radio_type =
5183 0 | BAND_SPECIFIED;
5184 break;
5185 case WIFI_FREQUENCY_BAND_5GHZ:
5186 priv->scan_cfg.chan_list[0].radio_type =
5187 1 | BAND_SPECIFIED;
5188 break;
5189 default:
5190 break;
5191 }
5192 priv->scan_cfg.bss_type = MLAN_BSS_MODE_INFRA;
5193 priv->scan_cfg.action = BG_SCAN_ACT_SET;
5194 priv->scan_cfg.enable = MTRUE;
5195 ret = woal_request_bgscan(priv, MOAL_IOCTL_WAIT,
5196 &priv->scan_cfg);
5197 }
5198 done:
5199 LEAVE();
5200 return ret;
5201 }
5202
5203 #ifdef STA_CFG80211
5204 /**
5205 * @brief set bgscan and new rssi_low_threshold
5206 *
5207 * @param priv A pointer to moal_private structure
5208 * @param set_rssi flag for set rssi_low_threshold
5209 *
5210 * @return N/A
5211 */
5212 void
woal_config_bgscan_and_rssi(moal_private * priv,t_u8 set_rssi)5213 woal_config_bgscan_and_rssi(moal_private *priv, t_u8 set_rssi)
5214 {
5215 char rssi_low[11];
5216 mlan_bss_info bss_info;
5217 int band = 0;
5218
5219 ENTER();
5220 memset(&bss_info, 0, sizeof(bss_info));
5221 woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
5222 if (!bss_info.media_connected) {
5223 PRINTM(MIOCTL, "We already lost connection\n");
5224 LEAVE();
5225 return;
5226 }
5227 memset(&priv->scan_cfg, 0, sizeof(priv->scan_cfg));
5228 strncpy(priv->scan_cfg.ssid_list[0].ssid, bss_info.ssid.ssid,
5229 bss_info.ssid.ssid_len);
5230 priv->scan_cfg.ssid_list[0].max_len = 0;
5231
5232 priv->scan_cfg.report_condition =
5233 BG_SCAN_SSID_RSSI_MATCH | BG_SCAN_WAIT_ALL_CHAN_DONE;
5234 priv->scan_cfg.rssi_threshold = priv->rssi_low - RSSI_HYSTERESIS;
5235 priv->scan_cfg.repeat_count = DEF_REPEAT_COUNT;
5236 priv->scan_cfg.scan_interval = MIN_BGSCAN_INTERVAL;
5237 woal_get_band(priv, &band);
5238 switch (band) {
5239 case WIFI_FREQUENCY_BAND_2GHZ:
5240 priv->scan_cfg.chan_list[0].radio_type = 0 | BAND_SPECIFIED;
5241 break;
5242 case WIFI_FREQUENCY_BAND_5GHZ:
5243 priv->scan_cfg.chan_list[0].radio_type = 1 | BAND_SPECIFIED;
5244 break;
5245 default:
5246 break;
5247 }
5248 priv->scan_cfg.bss_type = MLAN_BSS_MODE_INFRA;
5249 priv->scan_cfg.action = BG_SCAN_ACT_SET;
5250 priv->scan_cfg.enable = MTRUE;
5251 woal_request_bgscan(priv, MOAL_NO_WAIT, &priv->scan_cfg);
5252 if (set_rssi &&
5253 ((priv->rssi_low + RSSI_HYSTERESIS) <= LOWEST_RSSI_THRESHOLD)) {
5254 priv->rssi_low += RSSI_HYSTERESIS;
5255 sprintf(rssi_low, "%d", priv->rssi_low);
5256 woal_set_rssi_low_threshold(priv, rssi_low, MOAL_NO_WAIT);
5257 }
5258 LEAVE();
5259 }
5260 #endif
5261
5262 /**
5263 * @brief stop bg scan
5264 *
5265 * @param priv A pointer to moal_private structure
5266 * @param wait_option wait option
5267 *
5268 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5269 */
5270 mlan_status
woal_stop_bg_scan(moal_private * priv,t_u8 wait_option)5271 woal_stop_bg_scan(moal_private *priv, t_u8 wait_option)
5272 {
5273 wlan_bgscan_cfg scan_cfg;
5274 mlan_status ret = MLAN_STATUS_SUCCESS;
5275 ENTER();
5276
5277 memset(&scan_cfg, 0, sizeof(scan_cfg));
5278 scan_cfg.action = BG_SCAN_ACT_SET;
5279 scan_cfg.enable = MFALSE;
5280 ret = woal_request_bgscan(priv, wait_option, &scan_cfg);
5281
5282 LEAVE();
5283 return ret;
5284 }
5285
5286 /**
5287 * @brief set bgscan config
5288 *
5289 * @param handle A pointer to moal_handle structure
5290 *
5291 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5292 */
5293 void
woal_reconfig_bgscan(moal_handle * handle)5294 woal_reconfig_bgscan(moal_handle *handle)
5295 {
5296 int i;
5297 for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
5298 if (handle->priv[i] &&
5299 (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA)) {
5300 if (handle->priv[i]->bg_scan_start &&
5301 handle->priv[i]->bg_scan_reported) {
5302 PRINTM(MIOCTL, "Reconfig BGSCAN\n");
5303 woal_request_bgscan(handle->priv[i],
5304 MOAL_NO_WAIT,
5305 &handle->priv[i]->scan_cfg);
5306 handle->priv[i]->bg_scan_reported = MFALSE;
5307 }
5308 }
5309 }
5310 }
5311
5312 /**
5313 * @brief set rssi low threshold
5314 *
5315 * @param priv A pointer to moal_private structure
5316 * @param rssi A pointer to low rssi
5317 * @param wait_option Wait option
5318 *
5319 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5320 */
5321 mlan_status
woal_set_rssi_low_threshold(moal_private * priv,char * rssi,t_u8 wait_option)5322 woal_set_rssi_low_threshold(moal_private *priv, char *rssi, t_u8 wait_option)
5323 {
5324 mlan_status ret = MLAN_STATUS_SUCCESS;
5325 mlan_ioctl_req *req = NULL;
5326 mlan_ds_misc_cfg *misc = NULL;
5327 int low_rssi = 0;
5328
5329 ENTER();
5330 if (priv->media_connected == MFALSE)
5331 goto done;
5332
5333 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
5334 if (req == NULL) {
5335 ret = MLAN_STATUS_FAILURE;
5336 goto done;
5337 }
5338 misc = (mlan_ds_misc_cfg *)req->pbuf;
5339 req->req_id = MLAN_IOCTL_MISC_CFG;
5340 misc->sub_command = MLAN_OID_MISC_SUBSCRIBE_EVENT;
5341 req->action = MLAN_ACT_SET;
5342 misc->param.subscribe_event.evt_action = SUBSCRIBE_EVT_ACT_BITWISE_SET;
5343 misc->param.subscribe_event.evt_bitmap = SUBSCRIBE_EVT_RSSI_LOW;
5344 misc->param.subscribe_event.evt_bitmap |= SUBSCRIBE_EVT_PRE_BEACON_LOST;
5345 misc->param.subscribe_event.pre_beacon_miss = DEFAULT_PRE_BEACON_MISS;
5346
5347 if (MLAN_STATUS_SUCCESS != woal_atoi(&low_rssi, rssi)) {
5348 ret = MLAN_STATUS_FAILURE;
5349 goto done;
5350 }
5351 #ifdef STA_CFG80211
5352 priv->mrvl_rssi_low = low_rssi;
5353 #endif
5354 misc->param.subscribe_event.low_rssi = low_rssi;
5355 misc->param.subscribe_event.low_rssi_freq = 0;
5356 ret = woal_request_ioctl(priv, req, wait_option);
5357 if (ret == MLAN_STATUS_FAILURE) {
5358 PRINTM(MERROR, "request set rssi_low_threshold fail!\n");
5359 goto done;
5360 }
5361 done:
5362 if (ret != MLAN_STATUS_PENDING)
5363 kfree(req);
5364 LEAVE();
5365 return ret;
5366 }
5367
5368 #if defined(STA_CFG80211)
5369 /**
5370 * @brief set rssi low threshold
5371 *
5372 * @param priv A pointer to moal_private structure
5373 * @param event_id event id.
5374 * @param wait_option wait option
5375 *
5376 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5377 */
5378 mlan_status
woal_set_rssi_threshold(moal_private * priv,t_u32 event_id,t_u8 wait_option)5379 woal_set_rssi_threshold(moal_private *priv, t_u32 event_id, t_u8 wait_option)
5380 {
5381 mlan_status ret = MLAN_STATUS_SUCCESS;
5382 mlan_ioctl_req *req = NULL;
5383 mlan_ds_misc_cfg *misc = NULL;
5384
5385 ENTER();
5386 if (priv->media_connected == MFALSE)
5387 goto done;
5388 if (priv->mrvl_rssi_low)
5389 goto done;
5390 if (event_id == MLAN_EVENT_ID_FW_BCN_RSSI_LOW) {
5391 if (priv->last_rssi_low < 100)
5392 priv->last_rssi_low += priv->cqm_rssi_hyst;
5393 priv->last_rssi_high = abs(priv->cqm_rssi_high_thold);
5394 } else if (event_id == MLAN_EVENT_ID_FW_BCN_RSSI_HIGH) {
5395 priv->last_rssi_low = abs(priv->cqm_rssi_thold);
5396 if (priv->last_rssi_high > priv->cqm_rssi_hyst)
5397 priv->last_rssi_high -= priv->cqm_rssi_hyst;
5398 } else {
5399 priv->last_rssi_low = abs(priv->cqm_rssi_thold);
5400 priv->last_rssi_high = abs(priv->cqm_rssi_high_thold);
5401 }
5402
5403 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
5404 if (req == NULL) {
5405 ret = -ENOMEM;
5406 goto done;
5407 }
5408 misc = (mlan_ds_misc_cfg *)req->pbuf;
5409 req->req_id = MLAN_IOCTL_MISC_CFG;
5410 misc->sub_command = MLAN_OID_MISC_SUBSCRIBE_EVENT;
5411 req->action = MLAN_ACT_SET;
5412 if (!event_id && !priv->cqm_rssi_thold && !priv->cqm_rssi_hyst)
5413 misc->param.subscribe_event.evt_action =
5414 SUBSCRIBE_EVT_ACT_BITWISE_CLR;
5415 else
5416 misc->param.subscribe_event.evt_action =
5417 SUBSCRIBE_EVT_ACT_BITWISE_SET;
5418 misc->param.subscribe_event.evt_bitmap =
5419 SUBSCRIBE_EVT_RSSI_LOW | SUBSCRIBE_EVT_RSSI_HIGH;
5420 misc->param.subscribe_event.low_rssi_freq = 0;
5421 misc->param.subscribe_event.low_rssi = priv->last_rssi_low;
5422 misc->param.subscribe_event.high_rssi_freq = 0;
5423 misc->param.subscribe_event.high_rssi = priv->last_rssi_high;
5424 PRINTM(MIOCTL, "rssi_low=%d, rssi_high=%d action=%d\n",
5425 (int)priv->last_rssi_low, (int)priv->last_rssi_high,
5426 misc->param.subscribe_event.evt_action);
5427 ret = woal_request_ioctl(priv, req, wait_option);
5428 done:
5429 if (ret != MLAN_STATUS_PENDING)
5430 kfree(req);
5431 LEAVE();
5432 return ret;
5433 }
5434 #endif
5435
5436 /**
5437 * @brief Get power mode
5438 *
5439 * @param priv A pointer to moal_private structure
5440 * @param powermode A pointer to powermode buf
5441 *
5442 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5443 */
5444 mlan_status
woal_get_powermode(moal_private * priv,int * powermode)5445 woal_get_powermode(moal_private *priv, int *powermode)
5446 {
5447 mlan_status ret = MLAN_STATUS_SUCCESS;
5448 int ps_mode;
5449
5450 ENTER();
5451
5452 if (MLAN_STATUS_SUCCESS !=
5453 woal_set_get_power_mgmt(priv, MLAN_ACT_GET, &ps_mode, 0,
5454 MOAL_IOCTL_WAIT)) {
5455 ret = MLAN_STATUS_FAILURE;
5456 goto done;
5457 }
5458
5459 if (ps_mode)
5460 *powermode = MFALSE;
5461 else
5462 *powermode = MTRUE;
5463
5464 done:
5465 LEAVE();
5466 return ret;
5467 }
5468
5469 /**
5470 * @brief set scan type
5471 *
5472 * @param priv A pointer to moal_private structure
5473 * @param scan_type MLAN_SCAN_TYPE_ACTIVE/MLAN_SCAN_TYPE_PASSIVE
5474 *
5475 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5476 */
5477 mlan_status
woal_set_scan_type(moal_private * priv,t_u32 scan_type)5478 woal_set_scan_type(moal_private *priv, t_u32 scan_type)
5479 {
5480 mlan_status ret = MLAN_STATUS_SUCCESS;
5481 mlan_ds_scan *scan = NULL;
5482 mlan_ioctl_req *req = NULL;
5483 mlan_scan_cfg scan_cfg;
5484
5485 ENTER();
5486 memset(&scan_cfg, 0, sizeof(scan_cfg));
5487 if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) {
5488 ret = MLAN_STATUS_FAILURE;
5489 goto done;
5490 }
5491
5492 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
5493 if (req == NULL) {
5494 ret = MLAN_STATUS_FAILURE;
5495 goto done;
5496 }
5497 scan = (mlan_ds_scan *)req->pbuf;
5498 scan->sub_command = MLAN_OID_SCAN_CONFIG;
5499 req->req_id = MLAN_IOCTL_SCAN;
5500 req->action = MLAN_ACT_SET;
5501 memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
5502 scan_cfg.scan_type = scan_type;
5503 PRINTM(MIOCTL, "Set scan_type=%d\n", (int)scan_type);
5504 memcpy(&scan->param.scan_cfg, &scan_cfg, sizeof(mlan_scan_cfg));
5505 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5506
5507 done:
5508 if (ret != MLAN_STATUS_PENDING)
5509 kfree(req);
5510 LEAVE();
5511 return ret;
5512 }
5513
5514 /**
5515 * @brief enable/disable ext_scan
5516 *
5517 * @param priv A pointer to moal_private structure
5518 * @param enable MTRUE -- enable, MFALSE --disable
5519 *
5520 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5521 */
5522 mlan_status
woal_enable_ext_scan(moal_private * priv,t_u8 enable)5523 woal_enable_ext_scan(moal_private *priv, t_u8 enable)
5524 {
5525 mlan_status ret = MLAN_STATUS_SUCCESS;
5526 mlan_ds_scan *scan = NULL;
5527 mlan_ioctl_req *req = NULL;
5528 mlan_scan_cfg scan_cfg;
5529
5530 ENTER();
5531 memset(&scan_cfg, 0, sizeof(scan_cfg));
5532 if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) {
5533 ret = MLAN_STATUS_FAILURE;
5534 goto done;
5535 }
5536
5537 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
5538 if (req == NULL) {
5539 ret = MLAN_STATUS_FAILURE;
5540 goto done;
5541 }
5542 scan = (mlan_ds_scan *)req->pbuf;
5543 scan->sub_command = MLAN_OID_SCAN_CONFIG;
5544 req->req_id = MLAN_IOCTL_SCAN;
5545 req->action = MLAN_ACT_SET;
5546 memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
5547 scan_cfg.ext_scan = enable;
5548 PRINTM(MIOCTL, "Set ext_scan=%d\n", (int)enable);
5549 memcpy(&scan->param.scan_cfg, &scan_cfg, sizeof(mlan_scan_cfg));
5550 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5551
5552 done:
5553 if (ret != MLAN_STATUS_PENDING)
5554 kfree(req);
5555 LEAVE();
5556 return ret;
5557 }
5558
5559 /**
5560 * @brief set power mode
5561 *
5562 * @param priv A pointer to moal_private structure
5563 * @param powermode A pointer to powermode string.
5564 *
5565 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5566 */
5567 mlan_status
woal_set_powermode(moal_private * priv,char * powermode)5568 woal_set_powermode(moal_private *priv, char *powermode)
5569 {
5570 mlan_status ret = MLAN_STATUS_SUCCESS;
5571 int disabled;
5572
5573 ENTER();
5574
5575 if (*powermode == '1') {
5576 PRINTM(MIOCTL, "Disable power save\n");
5577 disabled = 1;
5578 } else if (*powermode == '0') {
5579 PRINTM(MIOCTL, "Enable power save\n");
5580 disabled = 0;
5581 } else {
5582 PRINTM(MERROR, "unsupported power mode\n");
5583 ret = MLAN_STATUS_FAILURE;
5584 goto done;
5585 }
5586
5587 if (MLAN_STATUS_SUCCESS !=
5588 woal_set_get_power_mgmt(priv, MLAN_ACT_SET, &disabled, 0,
5589 MOAL_IOCTL_WAIT))
5590 ret = MLAN_STATUS_FAILURE;
5591
5592 done:
5593 LEAVE();
5594 return ret;
5595 }
5596
5597 /**
5598 * @brief set combo scan
5599 *
5600 * @param priv A pointer to moal_private structure
5601 * @param buf A pointer to scan command buf
5602 * @param length buf length
5603 *
5604 * @return 0 -- success, otherwise fail
5605 */
5606 int
woal_set_combo_scan(moal_private * priv,char * buf,int length)5607 woal_set_combo_scan(moal_private *priv, char *buf, int length)
5608 {
5609 int ret = 0;
5610 wlan_user_scan_cfg scan_cfg;
5611 t_u8 *ptr = buf + WEXT_CSCAN_HEADER_SIZE;
5612 int buf_left = length - WEXT_CSCAN_HEADER_SIZE;
5613 int num_ssid = 0;
5614 int num_chan = 0;
5615 int ssid_len = 0;
5616 int i = 0;
5617 t_u16 passive_scan_time = 0;
5618 t_u16 specific_scan_time = 0;
5619
5620 ENTER();
5621 memset(&scan_cfg, 0, sizeof(scan_cfg));
5622 while (buf_left >= 2) {
5623 switch (*ptr) {
5624 case WEXT_CSCAN_SSID_SECTION:
5625 ssid_len = *(ptr + 1);
5626 if ((buf_left < (ssid_len + 2)) ||
5627 (ssid_len > MLAN_MAX_SSID_LENGTH)) {
5628 PRINTM(MERROR,
5629 "Invalid ssid, buf_left=%d, ssid_len=%d\n",
5630 buf_left, ssid_len);
5631 buf_left = 0;
5632 break;
5633 }
5634 if (ssid_len &&
5635 (num_ssid < (MRVDRV_MAX_SSID_LIST_LENGTH - 1))) {
5636 strncpy(scan_cfg.ssid_list[num_ssid].ssid,
5637 ptr + 2, ssid_len);
5638 scan_cfg.ssid_list[num_ssid].max_len = 0;
5639 PRINTM(MIOCTL, "Combo scan: ssid=%s\n",
5640 scan_cfg.ssid_list[num_ssid].ssid);
5641 num_ssid++;
5642 }
5643 buf_left -= ssid_len + 2;
5644 ptr += ssid_len + 2;
5645 break;
5646 case WEXT_CSCAN_CHANNEL_SECTION:
5647 num_chan = ptr[1];
5648 if ((buf_left < (num_chan + 2)) ||
5649 (num_chan > WLAN_USER_SCAN_CHAN_MAX)) {
5650 PRINTM(MERROR,
5651 "Invalid channel list, buf_left=%d, num_chan=%d\n",
5652 buf_left, num_chan);
5653 buf_left = 0;
5654 break;
5655 }
5656 for (i = 0; i < num_chan; i++) {
5657 scan_cfg.chan_list[i].chan_number = ptr[2 + i];
5658 PRINTM(MIOCTL, "Combo scan: chan=%d\n",
5659 scan_cfg.chan_list[i].chan_number);
5660 }
5661 buf_left -= 2 + num_chan;
5662 ptr += 2 + num_chan;
5663 break;
5664 case WEXT_CSCAN_PASV_DWELL_SECTION:
5665 if (buf_left < 3) {
5666 PRINTM(MERROR,
5667 "Invalid PASV_DWELL_SECTION, buf_left=%d\n",
5668 buf_left);
5669 buf_left = 0;
5670 break;
5671 }
5672 passive_scan_time = ptr[2] << 8 | ptr[1];
5673 ptr += 3;
5674 buf_left -= 3;
5675 break;
5676 case WEXT_CSCAN_HOME_DWELL_SECTION:
5677 if (buf_left < 3) {
5678 PRINTM(MERROR,
5679 "Invalid HOME_DWELL_SECTION, buf_left=%d\n",
5680 buf_left);
5681 buf_left = 0;
5682 break;
5683 }
5684 specific_scan_time = ptr[2] << 8 | ptr[1];
5685 ptr += 3;
5686 buf_left -= 3;
5687 break;
5688 default:
5689 buf_left = 0;
5690 break;
5691 }
5692 }
5693 if (passive_scan_time || specific_scan_time) {
5694 PRINTM(MIOCTL,
5695 "Set passive_scan_time=%d specific_scan_time=%d\n",
5696 passive_scan_time, specific_scan_time);
5697 if (MLAN_STATUS_FAILURE ==
5698 woal_set_scan_time(priv, 0, passive_scan_time,
5699 specific_scan_time)) {
5700 ret = -EFAULT;
5701 goto done;
5702 }
5703 }
5704 if (num_ssid || num_chan) {
5705 if (num_ssid) {
5706 /* Add broadcast scan to ssid_list */
5707 scan_cfg.ssid_list[num_ssid].max_len = 0xff;
5708 if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
5709 woal_set_scan_type(priv, MLAN_SCAN_TYPE_ACTIVE);
5710 }
5711 if (MLAN_STATUS_FAILURE == woal_do_scan(priv, &scan_cfg))
5712 ret = -EFAULT;
5713 if (num_ssid && (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE))
5714 woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE);
5715 } else {
5716 /* request broadcast scan */
5717 if (MLAN_STATUS_FAILURE == woal_do_scan(priv, NULL))
5718 ret = -EFAULT;
5719 }
5720 done:
5721 LEAVE();
5722 return ret;
5723 }
5724
5725 /**
5726 * @brief Get band
5727 *
5728 * @param priv A pointer to moal_private structure
5729 * @param band A pointer to band buf
5730 *
5731 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5732 */
5733 mlan_status
woal_get_band(moal_private * priv,int * band)5734 woal_get_band(moal_private *priv, int *band)
5735 {
5736 mlan_status ret = MLAN_STATUS_SUCCESS;
5737 mlan_ioctl_req *req = NULL;
5738 mlan_ds_radio_cfg *radio_cfg = NULL;
5739 int support_band = 0;
5740
5741 ENTER();
5742
5743 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
5744 if (req == NULL) {
5745 ret = MLAN_STATUS_FAILURE;
5746 goto done;
5747 }
5748 radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
5749 radio_cfg->sub_command = MLAN_OID_BAND_CFG;
5750 req->req_id = MLAN_IOCTL_RADIO_CFG;
5751 /* Get config_bands, adhoc_start_band and adhoc_channel values from MLAN */
5752 req->action = MLAN_ACT_GET;
5753 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5754 if (ret != MLAN_STATUS_SUCCESS)
5755 goto done;
5756
5757 if (radio_cfg->param.band_cfg.
5758 config_bands & (BAND_B | BAND_G | BAND_GN))
5759 support_band |= WIFI_FREQUENCY_BAND_2GHZ;
5760 if (radio_cfg->param.band_cfg.config_bands & (BAND_A | BAND_AN))
5761 support_band |= WIFI_FREQUENCY_BAND_5GHZ;
5762 *band = support_band;
5763 if (support_band == WIFI_FREQUENCY_ALL_BAND)
5764 *band = WIFI_FREQUENCY_BAND_AUTO;
5765 done:
5766 if (ret != MLAN_STATUS_PENDING)
5767 kfree(req);
5768 LEAVE();
5769 return ret;
5770 }
5771
5772 /**
5773 * @brief set band
5774 *
5775 * @param priv A pointer to moal_private structure
5776 * @param pband A pointer to band string.
5777 *
5778 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5779 */
5780 mlan_status
woal_set_band(moal_private * priv,char * pband)5781 woal_set_band(moal_private *priv, char *pband)
5782 {
5783 mlan_status ret = MLAN_STATUS_SUCCESS;
5784 int band = 0;
5785 mlan_ioctl_req *req = NULL;
5786 mlan_ds_radio_cfg *radio_cfg = NULL;
5787
5788 ENTER();
5789 if (priv->media_connected == MTRUE) {
5790 PRINTM(MERROR, "Set band is not allowed in connected state\n");
5791 ret = MLAN_STATUS_FAILURE;
5792 goto done;
5793 }
5794 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
5795 if (req == NULL) {
5796 ret = MLAN_STATUS_FAILURE;
5797 goto done;
5798 }
5799 radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
5800 radio_cfg->sub_command = MLAN_OID_BAND_CFG;
5801 req->req_id = MLAN_IOCTL_RADIO_CFG;
5802
5803 /* Get fw supported values from MLAN */
5804 req->action = MLAN_ACT_GET;
5805 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5806 if (ret != MLAN_STATUS_SUCCESS)
5807 goto done;
5808
5809 if (*pband == '0') {
5810 PRINTM(MIOCTL, "Set band to AUTO\n");
5811 band = radio_cfg->param.band_cfg.fw_bands;
5812 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
5813 if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev &&
5814 priv->wdev->wiphy) {
5815 if (radio_cfg->param.band_cfg.fw_bands & BAND_A)
5816 priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ] =
5817 &cfg80211_band_5ghz;
5818 priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ] =
5819 &cfg80211_band_2ghz;
5820 }
5821 #endif
5822 } else if (*pband == '1') {
5823 PRINTM(MIOCTL, "Set band to 5G\n");
5824 if (!(radio_cfg->param.band_cfg.fw_bands & BAND_A)) {
5825 PRINTM(MERROR, "Don't support 5G band\n");
5826 ret = MLAN_STATUS_FAILURE;
5827 goto done;
5828 }
5829 band = BAND_A;
5830 if (radio_cfg->param.band_cfg.fw_bands & BAND_AN)
5831 band |= BAND_AN;
5832 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
5833 if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev &&
5834 priv->wdev->wiphy) {
5835 priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ] =
5836 &cfg80211_band_5ghz;
5837 priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
5838 }
5839 #endif
5840 } else if (*pband == '2') {
5841 PRINTM(MIOCTL, "Set band to 2G\n");
5842 band = BAND_B | BAND_G;
5843 band |= BAND_GN;
5844 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
5845 if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev &&
5846 priv->wdev->wiphy) {
5847 priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
5848 priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ] =
5849 &cfg80211_band_2ghz;
5850 }
5851 #endif
5852 } else {
5853 PRINTM(MERROR, "unsupported band\n");
5854 ret = MLAN_STATUS_FAILURE;
5855 goto done;
5856 }
5857 /* Set config_bands to MLAN */
5858 req->action = MLAN_ACT_SET;
5859 memset(&radio_cfg->param.band_cfg, 0, sizeof(mlan_ds_band_cfg));
5860 radio_cfg->param.band_cfg.config_bands = band;
5861 radio_cfg->param.band_cfg.adhoc_start_band = band;
5862 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5863
5864 done:
5865 if (ret != MLAN_STATUS_PENDING)
5866 kfree(req);
5867 LEAVE();
5868 return ret;
5869 }
5870
5871 /**
5872 * @brief Add RX Filter
5873 *
5874 * @param priv A pointer to moal_private structure
5875 * @param rxfilter A pointer to rxfilter string.
5876 *
5877 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5878 */
5879 mlan_status
woal_add_rxfilter(moal_private * priv,char * rxfilter)5880 woal_add_rxfilter(moal_private *priv, char *rxfilter)
5881 {
5882 mlan_status ret = MLAN_STATUS_SUCCESS;
5883 ENTER();
5884 /* Android command:
5885 "DRIVER RXFILTER-ADD 0"
5886 "DRIVER RXFILTER-ADD 1"
5887 "DRIVER RXFILTER-ADD 3" */
5888 if (*rxfilter == '0') {
5889 PRINTM(MIOCTL, "Add IPV4 multicast filter\n");
5890 priv->rx_filter |= RX_FILTER_IPV4_MULTICAST;
5891 } else if (*rxfilter == '1') {
5892 PRINTM(MIOCTL, "Add broadcast filter\n");
5893 priv->rx_filter |= RX_FILTER_BROADCAST;
5894 } else if (*rxfilter == '2') {
5895 PRINTM(MIOCTL, "Add unicast filter\n");
5896 priv->rx_filter |= RX_FILTER_UNICAST;
5897 } else if (*rxfilter == '3') {
5898 PRINTM(MIOCTL, "Add IPV6 multicast fitler\n");
5899 priv->rx_filter |= RX_FILTER_IPV6_MULTICAST;
5900 } else {
5901 PRINTM(MERROR, "unsupported rx fitler\n");
5902 ret = MLAN_STATUS_FAILURE;
5903 goto done;
5904 }
5905 done:
5906 LEAVE();
5907 return ret;
5908 }
5909
5910 /**
5911 * @brief Remove RX Filter
5912 *
5913 * @param priv A pointer to moal_private structure
5914 * @param rxfilter A pointer to rxfilter string.
5915 *
5916 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5917 */
5918 mlan_status
woal_remove_rxfilter(moal_private * priv,char * rxfilter)5919 woal_remove_rxfilter(moal_private *priv, char *rxfilter)
5920 {
5921 mlan_status ret = MLAN_STATUS_SUCCESS;
5922 ENTER();
5923 if (*rxfilter == '0') {
5924 PRINTM(MIOCTL, "Remove IPV4 multicast filter\n");
5925 priv->rx_filter &= ~RX_FILTER_IPV4_MULTICAST;
5926 } else if (*rxfilter == '1') {
5927 PRINTM(MIOCTL, "Remove broadcast filter\n");
5928 priv->rx_filter &= ~RX_FILTER_BROADCAST;
5929 } else if (*rxfilter == '2') {
5930 PRINTM(MIOCTL, "Remove unicast filter\n");
5931 priv->rx_filter &= ~RX_FILTER_UNICAST;
5932 } else if (*rxfilter == '3') {
5933 PRINTM(MIOCTL, "Remove IPV6 multicast fitler\n");
5934 priv->rx_filter &= ~RX_FILTER_IPV6_MULTICAST;
5935 } else {
5936 PRINTM(MERROR, "unsupported rx fitler\n");
5937 ret = MLAN_STATUS_FAILURE;
5938 goto done;
5939 }
5940 done:
5941 LEAVE();
5942 return ret;
5943 }
5944
5945 /**
5946 * @brief Set/Get WMM IE QoS configuration
5947 *
5948 * @param priv A pointer to moal_private structure
5949 * @param action Action set or get
5950 * @param qos_cfg A pointer to QoS configuration structure
5951 *
5952 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
5953 */
5954 mlan_status
woal_priv_qos_cfg(moal_private * priv,t_u32 action,char * qos_cfg)5955 woal_priv_qos_cfg(moal_private *priv, t_u32 action, char *qos_cfg)
5956 {
5957 mlan_status ret = MLAN_STATUS_SUCCESS;
5958 mlan_ds_wmm_cfg *cfg = NULL;
5959 mlan_ioctl_req *req = NULL;
5960 int qosinfo = 0;
5961
5962 ENTER();
5963
5964 if (qos_cfg == NULL) {
5965 PRINTM(MERROR, "QOS info buffer is null\n");
5966 return MLAN_STATUS_FAILURE;
5967 }
5968 if ((action == MLAN_ACT_SET) &&
5969 (MLAN_STATUS_SUCCESS != woal_atoi(&qosinfo, qos_cfg))) {
5970 ret = MLAN_STATUS_FAILURE;
5971 goto done;
5972 }
5973 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
5974 if (req == NULL) {
5975 ret = MLAN_STATUS_FAILURE;
5976 goto done;
5977 }
5978 cfg = (mlan_ds_wmm_cfg *)req->pbuf;
5979 cfg->sub_command = MLAN_OID_WMM_CFG_QOS;
5980 req->req_id = MLAN_IOCTL_WMM_CFG;
5981 req->action = action;
5982 if (action == MLAN_ACT_SET) {
5983 cfg->param.qos_cfg = (t_u8)qosinfo;
5984 PRINTM(MIOCTL, "set qosinfo=%d\n", qosinfo);
5985 }
5986 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5987
5988 if (action == MLAN_ACT_GET)
5989 *qos_cfg = cfg->param.qos_cfg;
5990 done:
5991 if (ret != MLAN_STATUS_PENDING)
5992 kfree(req);
5993 LEAVE();
5994 return ret;
5995 }
5996
5997 /**
5998 * @brief Set sleep period
5999 *
6000 * @param priv A pointer to moal_private structure
6001 * @param psleeppd A pointer to sleep period configuration structure
6002 *
6003 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6004 */
6005 mlan_status
woal_set_sleeppd(moal_private * priv,char * psleeppd)6006 woal_set_sleeppd(moal_private *priv, char *psleeppd)
6007 {
6008 mlan_status ret = MLAN_STATUS_SUCCESS;
6009 mlan_ds_pm_cfg *pm_cfg = NULL;
6010 mlan_ioctl_req *req = NULL;
6011 int sleeppd = 0;
6012
6013 ENTER();
6014
6015 if (MLAN_STATUS_SUCCESS != woal_atoi(&sleeppd, psleeppd)) {
6016 ret = MLAN_STATUS_FAILURE;
6017 goto done;
6018 }
6019 PRINTM(MIOCTL, "set sleeppd=%d\n", sleeppd);
6020 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
6021 if (req == NULL) {
6022 ret = MLAN_STATUS_FAILURE;
6023 goto done;
6024 }
6025 pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
6026 pm_cfg->sub_command = MLAN_OID_PM_CFG_SLEEP_PD;
6027 req->req_id = MLAN_IOCTL_PM_CFG;
6028 if ((sleeppd <= MAX_SLEEP_PERIOD && sleeppd >= MIN_SLEEP_PERIOD) ||
6029 (sleeppd == 0)
6030 || (sleeppd == SLEEP_PERIOD_RESERVED_FF)
6031 ) {
6032 req->action = MLAN_ACT_SET;
6033 pm_cfg->param.sleep_period = sleeppd;
6034 } else {
6035 ret = MLAN_STATUS_FAILURE;
6036 goto done;
6037 }
6038
6039 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6040
6041 done:
6042 if (ret != MLAN_STATUS_PENDING)
6043 kfree(req);
6044 LEAVE();
6045 return ret;
6046 }
6047
6048 /**
6049 * @brief Set scan period function
6050 *
6051 * @param priv A pointer to moal_private structure
6052 * @param buf A pointer to scan command buf
6053 * @param length buf length
6054 *
6055 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6056 */
6057 int
woal_set_scan_cfg(moal_private * priv,char * buf,int length)6058 woal_set_scan_cfg(moal_private *priv, char *buf, int length)
6059 {
6060 mlan_status ret = MLAN_STATUS_SUCCESS;
6061 t_u8 *ptr = buf + NL80211_SCANCFG_HEADER_SIZE;
6062 int buf_left = length - NL80211_SCANCFG_HEADER_SIZE;
6063 t_u16 active_scan_time = 0;
6064 t_u16 passive_scan_time = 0;
6065 t_u16 specific_scan_time = 0;
6066
6067 ENTER();
6068 while (buf_left >= 2) {
6069 switch (*ptr) {
6070 case NL80211_SCANCFG_ACTV_DWELL_SECTION:
6071 if (buf_left < 3) {
6072 PRINTM(MERROR,
6073 "Invalid ACTV_DWELL_SECTION, buf_left=%d\n",
6074 buf_left);
6075 buf_left = 0;
6076 break;
6077 }
6078 active_scan_time = ptr[2] << 8 | ptr[1];
6079 ptr += 3;
6080 buf_left -= 3;
6081 break;
6082 case NL80211_SCANCFG_PASV_DWELL_SECTION:
6083 if (buf_left < 3) {
6084 PRINTM(MERROR,
6085 "Invalid PASV_DWELL_SECTION, buf_left=%d\n",
6086 buf_left);
6087 buf_left = 0;
6088 break;
6089 }
6090 passive_scan_time = ptr[2] << 8 | ptr[1];
6091 ptr += 3;
6092 buf_left -= 3;
6093 break;
6094 case NL80211_SCANCFG_SPCF_DWELL_SECTION:
6095 if (buf_left < 3) {
6096 PRINTM(MERROR,
6097 "Invalid SPCF_DWELL_SECTION, buf_left=%d\n",
6098 buf_left);
6099 buf_left = 0;
6100 break;
6101 }
6102 specific_scan_time = ptr[2] << 8 | ptr[1];
6103 ptr += 3;
6104 buf_left -= 3;
6105 break;
6106 default:
6107 buf_left = 0;
6108 break;
6109 }
6110 }
6111
6112 if (active_scan_time || passive_scan_time || specific_scan_time) {
6113 PRINTM(MIOCTL,
6114 "Set active_scan_time= %d passive_scan_time=%d specific_scan_time=%d\n",
6115 active_scan_time, passive_scan_time, specific_scan_time);
6116 if (MLAN_STATUS_FAILURE ==
6117 woal_set_scan_time(priv, active_scan_time,
6118 passive_scan_time, specific_scan_time)) {
6119 ret = -EFAULT;
6120 }
6121 }
6122
6123 LEAVE();
6124 return ret;
6125 }
6126
6127 /**
6128 * @brief Set Radio On/OFF
6129 *
6130 * @param priv A pointer to moal_private structure
6131 * @param option Radio Option
6132 *
6133 * @return 0 --success, otherwise fail
6134 */
6135 int
woal_set_radio(moal_private * priv,t_u8 option)6136 woal_set_radio(moal_private *priv, t_u8 option)
6137 {
6138 int ret = 0;
6139 mlan_ds_radio_cfg *radio = NULL;
6140 mlan_ioctl_req *req = NULL;
6141 mlan_status status = MLAN_STATUS_SUCCESS;
6142 ENTER();
6143 if ((option != 0) && (option != 1)) {
6144 ret = -EINVAL;
6145 goto done;
6146 }
6147 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
6148 if (req == NULL) {
6149 ret = -ENOMEM;
6150 goto done;
6151 }
6152 radio = (mlan_ds_radio_cfg *)req->pbuf;
6153 radio->sub_command = MLAN_OID_RADIO_CTRL;
6154 req->req_id = MLAN_IOCTL_RADIO_CFG;
6155 req->action = MLAN_ACT_SET;
6156 radio->param.radio_on_off = option;
6157 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6158 if (status != MLAN_STATUS_SUCCESS)
6159 ret = -EFAULT;
6160
6161 done:
6162 if (status != MLAN_STATUS_PENDING)
6163 kfree(req);
6164 LEAVE();
6165 return ret;
6166 }
6167
6168 #endif /* STA_SUPPORT */
6169
6170 /**
6171 * @brief Set/Get configure multi-channel policy
6172 *
6173 * @param priv A pointer to moal_private structure
6174 * @param enable A pointer to enable
6175 * @param wait_option wait_option of ioctl
6176 * @param action action of ioctl
6177 *
6178 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6179 */
6180 mlan_status
woal_mc_policy_cfg(moal_private * priv,t_u16 * enable,t_u8 wait_option,t_u8 action)6181 woal_mc_policy_cfg(moal_private *priv, t_u16 *enable,
6182 t_u8 wait_option, t_u8 action)
6183 {
6184 mlan_ioctl_req *req = NULL;
6185 mlan_ds_misc_cfg *cfg = NULL;
6186 mlan_status status = MLAN_STATUS_SUCCESS;
6187
6188 ENTER();
6189
6190 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
6191 if (req == NULL) {
6192 status = MLAN_STATUS_FAILURE;
6193 goto done;
6194 }
6195
6196 cfg = (mlan_ds_misc_cfg *)req->pbuf;
6197 cfg->sub_command = MLAN_OID_MISC_MULTI_CHAN_POLICY;
6198 req->req_id = MLAN_IOCTL_MISC_CFG;
6199 req->action = action;
6200 if (MLAN_ACT_SET == action)
6201 cfg->param.multi_chan_policy = *enable;
6202 status = woal_request_ioctl(priv, req, wait_option);
6203 if (status != MLAN_STATUS_SUCCESS)
6204 goto done;
6205 if (MLAN_ACT_GET == action)
6206 *enable = cfg->param.multi_chan_policy;
6207
6208 done:
6209 if (status != MLAN_STATUS_PENDING)
6210 kfree(req);
6211 LEAVE();
6212 return status;
6213 }
6214
6215 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
6216 /**
6217 * @brief Set/Get network monitor configurations
6218 *
6219 * @param priv Pointer to moal_private structure
6220 * @param wait_option wait option
6221 * @param enable Enable/Disable
6222 * @param filter Filter flag - Management/Control/Data
6223 * @param band_chan_cfg Network monitor band channel config
6224 *
6225 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
6226 */
6227 mlan_status
woal_set_net_monitor(moal_private * priv,t_u8 wait_option,t_u8 enable,t_u8 filter,netmon_band_chan_cfg * band_chan_cfg)6228 woal_set_net_monitor(moal_private *priv, t_u8 wait_option,
6229 t_u8 enable, t_u8 filter,
6230 netmon_band_chan_cfg * band_chan_cfg)
6231 {
6232 mlan_status ret = MLAN_STATUS_SUCCESS;
6233 mlan_ioctl_req *req = NULL;
6234 mlan_ds_misc_cfg *misc = NULL;
6235 mlan_ds_misc_net_monitor *net_mon = NULL;
6236 mlan_status status = MLAN_STATUS_SUCCESS;
6237
6238 ENTER();
6239
6240 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
6241 if (req == NULL) {
6242 ret = MLAN_STATUS_FAILURE;
6243 goto done;
6244 }
6245 misc = (mlan_ds_misc_cfg *)req->pbuf;
6246 net_mon = (mlan_ds_misc_net_monitor *)&misc->param.net_mon;
6247 misc->sub_command = MLAN_OID_MISC_NET_MONITOR;
6248 req->req_id = MLAN_IOCTL_MISC_CFG;
6249 req->action = MLAN_ACT_SET;
6250 net_mon->enable_net_mon = enable;
6251 if (net_mon->enable_net_mon) {
6252 net_mon->filter_flag = filter;
6253 if (net_mon->enable_net_mon == CHANNEL_SPEC_SNIFFER_MODE) {
6254 net_mon->band = band_chan_cfg->band;
6255 net_mon->channel = band_chan_cfg->channel;
6256 net_mon->chan_bandwidth = band_chan_cfg->chan_bandwidth;
6257 }
6258 }
6259
6260 status = woal_request_ioctl(priv, req, wait_option);
6261 if (status != MLAN_STATUS_SUCCESS) {
6262 ret = MLAN_STATUS_FAILURE;
6263 goto done;
6264 }
6265
6266 done:
6267 if (status != MLAN_STATUS_PENDING)
6268 kfree(req);
6269
6270 LEAVE();
6271 return ret;
6272 }
6273 #endif
6274
6275 /**
6276 * @brief Send delelte all BA command to MLAN
6277 *
6278 * @param priv A pointer to moal_private structure
6279 * @param wait_option Wait option
6280 *
6281 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
6282 */
6283 mlan_status
woal_delba_all(moal_private * priv,t_u8 wait_option)6284 woal_delba_all(moal_private *priv, t_u8 wait_option)
6285 {
6286 mlan_ioctl_req *req = NULL;
6287 mlan_ds_11n_cfg *cfg_11n = NULL;
6288 mlan_ds_11n_delba *del_ba = NULL;
6289 t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0 };
6290 mlan_status status = MLAN_STATUS_SUCCESS;
6291 int ret = 0;
6292
6293 req = (mlan_ioctl_req *)
6294 woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
6295 if (req == NULL) {
6296 ret = -ENOMEM;
6297 goto done;
6298 }
6299 cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
6300 req->req_id = MLAN_IOCTL_11N_CFG;
6301 cfg_11n->sub_command = MLAN_OID_11N_CFG_DELBA;
6302
6303 del_ba = &cfg_11n->param.del_ba;
6304 memset(del_ba, 0, sizeof(mlan_ds_11n_delba));
6305 del_ba->direction = DELBA_RX | DELBA_TX;
6306 del_ba->tid = DELBA_ALL_TIDS;
6307 memcpy(del_ba->peer_mac_addr, zero_mac, ETH_ALEN);
6308
6309 status = woal_request_ioctl(priv, req, wait_option);
6310
6311 if (status != MLAN_STATUS_SUCCESS) {
6312 ret = -EFAULT;
6313 goto done;
6314 }
6315
6316 done:
6317 if (status != MLAN_STATUS_PENDING)
6318 kfree(req);
6319 LEAVE();
6320 return ret;
6321 }
6322
6323 /**
6324 * @brief Send 11d enable/disable command to firmware.
6325 *
6326 * @param priv A pointer to moal_private structure
6327 * @param wait_option Wait option
6328 * @param enable Enable/Disable 11d
6329 *
6330 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
6331 */
6332 mlan_status
woal_set_11d(moal_private * priv,t_u8 wait_option,t_u8 enable)6333 woal_set_11d(moal_private *priv, t_u8 wait_option, t_u8 enable)
6334 {
6335 mlan_ioctl_req *req = NULL;
6336 mlan_ds_snmp_mib *snmp = NULL;
6337 mlan_status ret = MLAN_STATUS_SUCCESS;
6338
6339 ENTER();
6340
6341 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
6342 if (req == NULL) {
6343 LEAVE();
6344 return -ENOMEM;
6345 }
6346
6347 req->action = MLAN_ACT_SET;
6348 req->req_id = MLAN_IOCTL_SNMP_MIB;
6349
6350 snmp = (mlan_ds_snmp_mib *)req->pbuf;
6351 snmp->sub_command = MLAN_OID_SNMP_MIB_DOT11D;
6352 snmp->param.oid_value = enable;
6353
6354 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6355 if (ret != MLAN_STATUS_PENDING)
6356 kfree(req);
6357
6358 LEAVE();
6359 return ret;
6360 }
6361
6362 /**
6363 * @brief Handle miscellaneous ioctls for asynchronous command response
6364 *
6365 * @param priv Pointer to moal_private structure
6366 * @param info Pointer to mlan_ds_misc_cfg structure
6367 *
6368 * @return N/A
6369 */
6370 void
woal_ioctl_get_misc_conf(moal_private * priv,mlan_ds_misc_cfg * info)6371 woal_ioctl_get_misc_conf(moal_private *priv, mlan_ds_misc_cfg *info)
6372 {
6373 char event[1000];
6374 mlan_ds_host_clock *host_clock = NULL;
6375 ENTER();
6376 switch (info->sub_command) {
6377 case MLAN_OID_MISC_GET_CORRELATED_TIME:
6378 host_clock = &info->param.host_clock;
6379 memset(event, 0, sizeof(event));
6380 sprintf(event, "%s %llu %llu", CUS_EVT_GET_CORRELATED_TIME,
6381 host_clock->time, host_clock->fw_time);
6382 woal_broadcast_event(priv, event, strlen(event));
6383 PRINTM(MERROR, "CMD = %s\n", event);
6384 default:
6385 break;
6386 }
6387 }
6388
6389 module_param(disconnect_on_suspend, int, 0);
6390 MODULE_PARM_DESC(disconnect_on_suspend,
6391 "1: Enable disconnect wifi on suspend; 0: Disable disconnect wifi on suspend");
6392