blob: b868e32e7bc72b7bcd37beded4a8c422e3bc81c5 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
106#include "wlan_hdd_cfg80211.h"
107#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700109int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "sapApi.h"
111#include <linux/semaphore.h>
112#include <mach/subsystem_restart.h>
113#include <wlan_hdd_hostapd.h>
114#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "wlan_hdd_dev_pwr.h"
117#ifdef WLAN_BTAMP_FEATURE
118#include "bap_hdd_misc.h"
119#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700120#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800122#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530123#ifdef FEATURE_WLAN_TDLS
124#include "wlan_hdd_tdls.h"
125#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700126#include "wlan_hdd_debugfs.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700127
128#ifdef MODULE
129#define WLAN_MODULE_NAME module_name(THIS_MODULE)
130#else
131#define WLAN_MODULE_NAME "wlan"
132#endif
133
134#ifdef TIMER_MANAGER
135#define TIMER_MANAGER_STR " +TIMER_MANAGER"
136#else
137#define TIMER_MANAGER_STR ""
138#endif
139
140#ifdef MEMORY_DEBUG
141#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
142#else
143#define MEMORY_DEBUG_STR ""
144#endif
145
146/* the Android framework expects this param even though we don't use it */
147#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700148static char fwpath_buffer[BUF_LEN];
149static struct kparam_string fwpath = {
150 .string = fwpath_buffer,
151 .maxlen = BUF_LEN,
152};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700153#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700154static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700155#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700156
Jeff Johnsone7245742012-09-05 17:12:55 -0700157/*
158 * The rate at which the driver sends RESTART event to supplicant
159 * once the function 'vos_wlanRestart()' is called
160 *
161 */
162#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
163#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700164
165/*
166 * Size of Driver command strings from upper layer
167 */
168#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
169#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
170
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800171#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700172static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700173#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700174/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700175static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700176
177//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700178static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
179static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
180static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
181void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800182void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700183
Jeff Johnson295189b2012-06-20 16:38:30 -0700184v_U16_t hdd_select_queue(struct net_device *dev,
185 struct sk_buff *skb);
186
187#ifdef WLAN_FEATURE_PACKET_FILTERING
188static void hdd_set_multicast_list(struct net_device *dev);
189#endif
190
191void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700192int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700193
194extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800195#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
196void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
197static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
198static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700199static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
200 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
201 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700202static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
203 tANI_U8 *pTargetApBssid,
204 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800205#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700206static int hdd_netdev_notifier_call(struct notifier_block * nb,
207 unsigned long state,
208 void *ndev)
209{
210 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700211 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700212 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700213#ifdef WLAN_BTAMP_FEATURE
214 VOS_STATUS status;
215 hdd_context_t *pHddCtx;
216#endif
217
218 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700219 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700220 (strncmp(dev->name, "p2p", 3)))
221 return NOTIFY_DONE;
222
223 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700224 return NOTIFY_DONE;
225
Jeff Johnson295189b2012-06-20 16:38:30 -0700226 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700227 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700228
Jeff Johnson27cee452013-03-27 11:10:24 -0700229 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700230 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800231 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700232 VOS_ASSERT(0);
233 return NOTIFY_DONE;
234 }
235
Jeff Johnson27cee452013-03-27 11:10:24 -0700236 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
237 if (NULL == pHddCtx)
238 {
239 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
240 VOS_ASSERT(0);
241 return NOTIFY_DONE;
242 }
243
244 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
245 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700246
247 switch (state) {
248 case NETDEV_REGISTER:
249 break;
250
251 case NETDEV_UNREGISTER:
252 break;
253
254 case NETDEV_UP:
255 break;
256
257 case NETDEV_DOWN:
258 break;
259
260 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700261 if(TRUE == pAdapter->isLinkUpSvcNeeded)
262 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700263 break;
264
265 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700266 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700267 {
268 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800269 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700270 hdd_abort_mac_scan(pAdapter->pHddCtx);
271 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800272 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700273 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
274 if(!result)
275 {
276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800277 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700278 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700279 }
280 }
281 else
282 {
283 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700284 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700285 }
286#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700287 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700288 status = WLANBAP_StopAmp();
289 if(VOS_STATUS_SUCCESS != status )
290 {
291 pHddCtx->isAmpAllowed = VOS_TRUE;
292 hddLog(VOS_TRACE_LEVEL_FATAL,
293 "%s: Failed to stop AMP", __func__);
294 }
295 else
296 {
297 //a state m/c implementation in PAL is TBD to avoid this delay
298 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700299 if ( pHddCtx->isAmpAllowed )
300 {
301 WLANBAP_DeregisterFromHCI();
302 pHddCtx->isAmpAllowed = VOS_FALSE;
303 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700304 }
305#endif //WLAN_BTAMP_FEATURE
306 break;
307
308 default:
309 break;
310 }
311
312 return NOTIFY_DONE;
313}
314
315struct notifier_block hdd_netdev_notifier = {
316 .notifier_call = hdd_netdev_notifier_call,
317};
318
319/*---------------------------------------------------------------------------
320 * Function definitions
321 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700322void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
323void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700324//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700325static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700326#ifndef MODULE
327/* current con_mode - used only for statically linked driver
328 * con_mode is changed by userspace to indicate a mode change which will
329 * result in calling the module exit and init functions. The module
330 * exit function will clean up based on the value of con_mode prior to it
331 * being changed by userspace. So curr_con_mode records the current con_mode
332 * for exit when con_mode becomes the next mode for init
333 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700334static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700335#endif
336
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800337/**---------------------------------------------------------------------------
338
339 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
340
341 Called immediately after the cfg.ini is read in order to configure
342 the desired trace levels.
343
344 \param - moduleId - module whose trace level is being configured
345 \param - bitmask - bitmask of log levels to be enabled
346
347 \return - void
348
349 --------------------------------------------------------------------------*/
350static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
351{
352 wpt_tracelevel level;
353
354 /* if the bitmask is the default value, then a bitmask was not
355 specified in cfg.ini, so leave the logging level alone (it
356 will remain at the "compiled in" default value) */
357 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
358 {
359 return;
360 }
361
362 /* a mask was specified. start by disabling all logging */
363 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
364
365 /* now cycle through the bitmask until all "set" bits are serviced */
366 level = VOS_TRACE_LEVEL_FATAL;
367 while (0 != bitmask)
368 {
369 if (bitmask & 1)
370 {
371 vos_trace_setValue(moduleId, level, 1);
372 }
373 level++;
374 bitmask >>= 1;
375 }
376}
377
378
Jeff Johnson295189b2012-06-20 16:38:30 -0700379/**---------------------------------------------------------------------------
380
381 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
382
383 Called immediately after the cfg.ini is read in order to configure
384 the desired trace levels in the WDI.
385
386 \param - moduleId - module whose trace level is being configured
387 \param - bitmask - bitmask of log levels to be enabled
388
389 \return - void
390
391 --------------------------------------------------------------------------*/
392static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
393{
394 wpt_tracelevel level;
395
396 /* if the bitmask is the default value, then a bitmask was not
397 specified in cfg.ini, so leave the logging level alone (it
398 will remain at the "compiled in" default value) */
399 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
400 {
401 return;
402 }
403
404 /* a mask was specified. start by disabling all logging */
405 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
406
407 /* now cycle through the bitmask until all "set" bits are serviced */
408 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
409 while (0 != bitmask)
410 {
411 if (bitmask & 1)
412 {
413 wpalTraceSetLevel(moduleId, level, 1);
414 }
415 level++;
416 bitmask >>= 1;
417 }
418}
Jeff Johnson295189b2012-06-20 16:38:30 -0700419
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530420/*
421 * FUNCTION: wlan_hdd_validate_context
422 * This function is used to check the HDD context
423 */
424int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
425{
426 ENTER();
427
428 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
429 {
430 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
431 "%s: HDD context is Null", __func__);
432 return -ENODEV;
433 }
434
435 if (pHddCtx->isLogpInProgress)
436 {
437 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
438 "%s: LOGP in Progress. Ignore!!!", __func__);
439 return -EAGAIN;
440 }
441
442 if (pHddCtx->isLoadUnloadInProgress)
443 {
444 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
445 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
446 return -EAGAIN;
447 }
448 return 0;
449}
450
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530451void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
452{
453 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
454 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
455 hdd_config_t *cfg_param;
456 eCsrPhyMode phyMode;
457
458 if (NULL == pHddCtx)
459 {
460 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
461 "HDD Context is null !!");
462 return ;
463 }
464
465 cfg_param = pHddCtx->cfg_ini;
466
467 if (NULL == cfg_param)
468 {
469 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
470 "cfg_params not available !!");
471 return ;
472 }
473
474 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
475
476 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
477 {
478 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
479 (eCSR_DOT11_MODE_11ac == phyMode) ||
480 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
481 {
482 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
483 "Setting phymode to 11n!!");
484 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
485 }
486 }
487 else
488 {
489 /*New country Supports 11ac as well resetting value back from .ini*/
490 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
491 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
492 return ;
493 }
494
495 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
496 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
497 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
498 {
499 VOS_STATUS vosStatus;
500
501 // need to issue a disconnect to CSR.
502 INIT_COMPLETION(pAdapter->disconnect_comp_var);
503 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
504 pAdapter->sessionId,
505 eCSR_DISCONNECT_REASON_UNSPECIFIED );
506
507 if (VOS_STATUS_SUCCESS == vosStatus)
508 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
509 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
510
511 }
512}
513
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700514void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
515{
516 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
517 hdd_config_t *cfg_param;
518
519 if (NULL == pHddCtx)
520 {
521 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
522 "HDD Context is null !!");
523 return ;
524 }
525
526 cfg_param = pHddCtx->cfg_ini;
527
528 if (NULL == cfg_param)
529 {
530 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
531 "cfg_params not available !!");
532 return ;
533 }
534
535 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
536 {
537 /*New country doesn't support DFS */
538 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
539 }
540 else
541 {
542 /*New country Supports DFS as well resetting value back from .ini*/
543 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
544 }
545
546}
547
Jeff Johnson295189b2012-06-20 16:38:30 -0700548int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
549{
550 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
551 hdd_priv_data_t priv_data;
552 tANI_U8 *command = NULL;
553 int ret = 0;
554
555 if (NULL == pAdapter)
556 {
557 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700558 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700559 ret = -ENODEV;
560 goto exit;
561 }
562
Jeff Johnsone7245742012-09-05 17:12:55 -0700563 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700564 {
565 ret = -EINVAL;
566 goto exit;
567 }
568
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -0700569 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
570 {
571 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
572 "%s:LOGP in Progress. Ignore!!!", __func__);
573 ret = -EBUSY;
574 goto exit;
575 }
576
Jeff Johnson295189b2012-06-20 16:38:30 -0700577 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
578 {
579 ret = -EFAULT;
580 goto exit;
581 }
582
583 command = kmalloc(priv_data.total_len, GFP_KERNEL);
584 if (!command)
585 {
586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700587 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700588 ret = -ENOMEM;
589 goto exit;
590 }
591
592 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
593 {
594 ret = -EFAULT;
595 goto exit;
596 }
597
598 if ((SIOCDEVPRIVATE + 1) == cmd)
599 {
600 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
601
602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700603 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700604
605 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
606 {
607 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
608 sizeof(tSirMacAddr)))
609 {
610 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700611 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700612 ret = -EFAULT;
613 }
614 }
Amar Singhal0974e402013-02-12 14:27:46 -0800615 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700616 {
Amar Singhal0974e402013-02-12 14:27:46 -0800617 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700618 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800619
Jeff Johnson295189b2012-06-20 16:38:30 -0700620 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800621
622 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700623 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700624 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800625 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, command, priv_data.used_len, priv_data.total_len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700626 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800627 ret = hdd_setBand_helper(dev, ptr);
628 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700629 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
630 {
631 char *country_code;
632
633 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700634
635 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530636 hdd_checkandupdate_phymode(pAdapter, country_code);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700637 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
Gopichand Nakkalaacd94112013-05-29 21:37:47 +0530638 pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700639 if( 0 != ret )
640 {
641 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
642 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
643
644 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700645 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800646#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
647 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
648 {
649 tANI_U8 *value = command;
650 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
651 tANI_U8 revision = 0;
652 eHalStatus status = eHAL_STATUS_SUCCESS;
653 v_REGDOMAIN_t regId;
654
655 status = hdd_parse_countryrev(value, countryCode, &revision);
656 if (eHAL_STATUS_SUCCESS != status)
657 {
658 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
659 "%s: Failed to parse country revision information", __func__);
660 ret = -EINVAL;
661 goto exit;
662 }
663
664 /* Validate country code */
665 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
666 if (eHAL_STATUS_SUCCESS != status)
667 {
668 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
669 "%s: Invalid country code %s", __func__, countryCode);
670 ret = -EINVAL;
671 goto exit;
672 }
673
674 /* Validate revision */
675 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
676 {
677 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
678 "%s: Invalid revision %d", __func__, revision);
679 ret = -EINVAL;
680 goto exit;
681 }
682
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700683 hdd_checkandupdate_dfssetting(pAdapter, countryCode);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530684 hdd_checkandupdate_phymode(pAdapter, countryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800685 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
Gopichand Nakkalaacd94112013-05-29 21:37:47 +0530686 pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800687 if (0 != ret)
688 {
689 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
690 "%s: SME Change Country code fail ret=%d", __func__, ret);
691 ret = -EINVAL;
692 goto exit;
693 }
694
695 if (0 == strncmp(countryCode, "KR", 2))
696 {
697 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
698 revision);
699 if (eHAL_STATUS_SUCCESS != status)
700 {
701 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
702 "%s: Failed to build valid channel list", __func__);
703 ret = -EINVAL;
704 goto exit;
705 }
706 }
707 }
708#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700709 /*
710 command should be a string having format
711 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
712 */
Amar Singhal0974e402013-02-12 14:27:46 -0800713 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700714 {
Amar Singhal0974e402013-02-12 14:27:46 -0800715 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700716
717 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700718 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700719
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800720 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700721 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800722 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
723 {
724 int suspend = 0;
725 tANI_U8 *ptr = (tANI_U8*)command + 15;
726
727 suspend = *ptr - '0';
728 hdd_set_wlan_suspend_mode(suspend);
729 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800730#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
731 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
732 {
733 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700734 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800735 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
736 eHalStatus status = eHAL_STATUS_SUCCESS;
737
738 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
739 value = value + 15;
740
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700741 /* Convert the value from ascii to integer */
742 ret = kstrtos8(value, 10, &rssi);
743 if (ret < 0)
744 {
745 /* If the input value is greater than max value of datatype, then also
746 kstrtou8 fails */
747 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
748 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
749 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
750 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
751 ret = -EINVAL;
752 goto exit;
753 }
754
Srinivas Girigowdade697412013-02-14 16:31:48 -0800755 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700756
Srinivas Girigowdade697412013-02-14 16:31:48 -0800757 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
758 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
759 {
760 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
761 "Neighbor lookup threshold value %d is out of range"
762 " (Min: %d Max: %d)", lookUpThreshold,
763 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
764 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
765 ret = -EINVAL;
766 goto exit;
767 }
768
769 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
770 "%s: Received Command to Set Roam trigger"
771 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
772
773 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
774 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
775 if (eHAL_STATUS_SUCCESS != status)
776 {
777 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
778 "%s: Failed to set roam trigger, try again", __func__);
779 ret = -EPERM;
780 goto exit;
781 }
782
783 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
784 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
785 }
786 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
787 {
788 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
789 int rssi = (-1) * lookUpThreshold;
790 char extra[32];
791 tANI_U8 len = 0;
792
793 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
794 if (copy_to_user(priv_data.buf, &extra, len + 1))
795 {
796 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
797 "%s: failed to copy data to user buffer", __func__);
798 ret = -EFAULT;
799 goto exit;
800 }
801 }
802 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
803 {
804 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700805 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700806 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700807
Srinivas Girigowdade697412013-02-14 16:31:48 -0800808 /* input refresh period is in terms of seconds */
809 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
810 value = value + 18;
811 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700812 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800813 if (ret < 0)
814 {
815 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700816 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800817 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700818 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -0800819 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700820 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
821 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800822 ret = -EINVAL;
823 goto exit;
824 }
825
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700826 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
827 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800828 {
829 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700830 "Roam scan period value %d is out of range"
831 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700832 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
833 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800834 ret = -EINVAL;
835 goto exit;
836 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700837 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800838
839 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
840 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700841 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800842
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700843 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
844 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800845 }
846 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
847 {
848 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
849 char extra[32];
850 tANI_U8 len = 0;
851
852 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
853 /* Returned value is in units of seconds */
854 if (copy_to_user(priv_data.buf, &extra, len + 1))
855 {
856 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
857 "%s: failed to copy data to user buffer", __func__);
858 ret = -EFAULT;
859 goto exit;
860 }
861 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700862 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
863 {
864 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700865 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700866 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700867
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700868 /* input refresh period is in terms of seconds */
869 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
870 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700871
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700872 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700873 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700874 if (ret < 0)
875 {
876 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700877 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700878 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700879 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700880 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700881 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
882 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
883 ret = -EINVAL;
884 goto exit;
885 }
886
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700887 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
888 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
889 {
890 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
891 "Neighbor scan results refresh period value %d is out of range"
892 " (Min: %d Max: %d)", roamScanRefreshPeriod,
893 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
894 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
895 ret = -EINVAL;
896 goto exit;
897 }
898 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
899
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
901 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700902 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700903
904 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
905 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
906 }
907 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
908 {
909 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
910 char extra[32];
911 tANI_U8 len = 0;
912
913 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
914 /* Returned value is in units of seconds */
915 if (copy_to_user(priv_data.buf, &extra, len + 1))
916 {
917 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
918 "%s: failed to copy data to user buffer", __func__);
919 ret = -EFAULT;
920 goto exit;
921 }
922 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700923#ifdef FEATURE_WLAN_LFR
924 /* SETROAMMODE */
925 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
926 {
927 tANI_U8 *value = command;
928 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
929
930 /* Move pointer to ahead of SETROAMMODE<delimiter> */
931 value = value + SIZE_OF_SETROAMMODE + 1;
932
933 /* Convert the value from ascii to integer */
934 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
935 if (ret < 0)
936 {
937 /* If the input value is greater than max value of datatype, then also
938 kstrtou8 fails */
939 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
940 "%s: kstrtou8 failed range [%d - %d]", __func__,
941 CFG_LFR_FEATURE_ENABLED_MIN,
942 CFG_LFR_FEATURE_ENABLED_MAX);
943 ret = -EINVAL;
944 goto exit;
945 }
946 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
947 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
948 {
949 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
950 "Roam Mode value %d is out of range"
951 " (Min: %d Max: %d)", roamMode,
952 CFG_LFR_FEATURE_ENABLED_MIN,
953 CFG_LFR_FEATURE_ENABLED_MAX);
954 ret = -EINVAL;
955 goto exit;
956 }
957
958 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
959 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
960 /*
961 * Note that
962 * SETROAMMODE 0 is to enable LFR while
963 * SETROAMMODE 1 is to disable LFR, but
964 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
965 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
966 */
967 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
968 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
969 else
970 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
971
972 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
973 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
974 }
975 /* GETROAMMODE */
976 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
977 {
978 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
979 char extra[32];
980 tANI_U8 len = 0;
981
982 /*
983 * roamMode value shall be inverted because the sementics is different.
984 */
985 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
986 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
987 else
988 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
989
990 len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode);
991 if (copy_to_user(priv_data.buf, &extra, len + 1))
992 {
993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
994 "%s: failed to copy data to user buffer", __func__);
995 ret = -EFAULT;
996 goto exit;
997 }
998 }
999#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08001000#endif
1001#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1002 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
1003 {
1004 tANI_U8 *value = command;
1005 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
1006
1007 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
1008 value = value + 13;
1009 /* Convert the value from ascii to integer */
1010 ret = kstrtou8(value, 10, &roamRssiDiff);
1011 if (ret < 0)
1012 {
1013 /* If the input value is greater than max value of datatype, then also
1014 kstrtou8 fails */
1015 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1016 "%s: kstrtou8 failed range [%d - %d]", __func__,
1017 CFG_ROAM_RSSI_DIFF_MIN,
1018 CFG_ROAM_RSSI_DIFF_MAX);
1019 ret = -EINVAL;
1020 goto exit;
1021 }
1022
1023 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1024 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1025 {
1026 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1027 "Roam rssi diff value %d is out of range"
1028 " (Min: %d Max: %d)", roamRssiDiff,
1029 CFG_ROAM_RSSI_DIFF_MIN,
1030 CFG_ROAM_RSSI_DIFF_MAX);
1031 ret = -EINVAL;
1032 goto exit;
1033 }
1034
1035 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1036 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1037
1038 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1039 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1040 }
1041 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1042 {
1043 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1044 char extra[32];
1045 tANI_U8 len = 0;
1046
1047 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
1048 if (copy_to_user(priv_data.buf, &extra, len + 1))
1049 {
1050 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1051 "%s: failed to copy data to user buffer", __func__);
1052 ret = -EFAULT;
1053 goto exit;
1054 }
1055 }
1056#endif
1057#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1058 else if (strncmp(command, "GETBAND", 7) == 0)
1059 {
1060 int band = -1;
1061 char extra[32];
1062 tANI_U8 len = 0;
1063 hdd_getBand_helper(pHddCtx, &band);
1064
1065 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
1066 if (copy_to_user(priv_data.buf, &extra, len + 1))
1067 {
1068 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1069 "%s: failed to copy data to user buffer", __func__);
1070 ret = -EFAULT;
1071 goto exit;
1072 }
1073 }
1074 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
1075 {
1076 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
1077 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
1078 tANI_U8 revision = 0;
1079 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
1080 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
1081 char extra[32] = {0};
1082 tANI_U8 len = 0;
1083
1084 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
1085 {
1086 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1087 "%s: failed to get country code", __func__);
1088 ret = -EFAULT;
1089 goto exit;
1090 }
1091 pBuf[uBufLen] = '\0';
1092 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
1093
1094 if (0 == strncmp(pBuf, "KR", 2))
1095 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
1096 else
1097 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
1098
1099 if (copy_to_user(priv_data.buf, &extra, len + 1))
1100 {
1101 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1102 "%s: failed to copy data to user buffer", __func__);
1103 ret = -EFAULT;
1104 goto exit;
1105 }
1106 }
1107 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1108 {
1109 tANI_U8 *value = command;
1110 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1111 tANI_U8 numChannels = 0;
1112 eHalStatus status = eHAL_STATUS_SUCCESS;
1113
1114 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1115 if (eHAL_STATUS_SUCCESS != status)
1116 {
1117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1118 "%s: Failed to parse channel list information", __func__);
1119 ret = -EINVAL;
1120 goto exit;
1121 }
1122
1123 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1124 {
1125 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1126 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1127 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1128 ret = -EINVAL;
1129 goto exit;
1130 }
1131 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1132 numChannels);
1133 if (eHAL_STATUS_SUCCESS != status)
1134 {
1135 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1136 "%s: Failed to update channel list information", __func__);
1137 ret = -EINVAL;
1138 goto exit;
1139 }
1140 }
1141 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1142 {
1143 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1144 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001145 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001146 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001147 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001148
1149 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1150 ChannelList, &numChannels ))
1151 {
1152 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1153 "%s: failed to get roam scan channel list", __func__);
1154 ret = -EFAULT;
1155 goto exit;
1156 }
1157 /* output channel list is of the format
1158 [Number of roam scan channels][Channel1][Channel2]... */
1159 /* copy the number of channels in the 0th index */
1160 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1161 for (j = 0; (j < numChannels); j++)
1162 {
1163 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1164 }
1165
1166 if (copy_to_user(priv_data.buf, &extra, len + 1))
1167 {
1168 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1169 "%s: failed to copy data to user buffer", __func__);
1170 ret = -EFAULT;
1171 goto exit;
1172 }
1173 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001174 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1175 {
1176 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1177 char extra[32];
1178 tANI_U8 len = 0;
1179
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001180 /* Check if the features OKC/CCX/11R are supported simultaneously,
1181 then this operation is not permitted (return FAILURE) */
1182 if (ccxMode &&
1183 hdd_is_okc_mode_enabled(pHddCtx) &&
1184 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1185 {
1186 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1187 "%s: OKC/CCX/11R are supported simultaneously"
1188 " hence this operation is not permitted!", __func__);
1189 ret = -EPERM;
1190 goto exit;
1191 }
1192
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001193 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1194 if (copy_to_user(priv_data.buf, &extra, len + 1))
1195 {
1196 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1197 "%s: failed to copy data to user buffer", __func__);
1198 ret = -EFAULT;
1199 goto exit;
1200 }
1201 }
1202 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1203 {
1204 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1205 char extra[32];
1206 tANI_U8 len = 0;
1207
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001208 /* Check if the features OKC/CCX/11R are supported simultaneously,
1209 then this operation is not permitted (return FAILURE) */
1210 if (okcMode &&
1211 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1212 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1213 {
1214 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1215 "%s: OKC/CCX/11R are supported simultaneously"
1216 " hence this operation is not permitted!", __func__);
1217 ret = -EPERM;
1218 goto exit;
1219 }
1220
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001221 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1222 if (copy_to_user(priv_data.buf, &extra, len + 1))
1223 {
1224 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1225 "%s: failed to copy data to user buffer", __func__);
1226 ret = -EFAULT;
1227 goto exit;
1228 }
1229 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001230 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001231 {
1232 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1233 char extra[32];
1234 tANI_U8 len = 0;
1235
1236 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1237 if (copy_to_user(priv_data.buf, &extra, len + 1))
1238 {
1239 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1240 "%s: failed to copy data to user buffer", __func__);
1241 ret = -EFAULT;
1242 goto exit;
1243 }
1244 }
1245 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1246 {
1247 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1248 char extra[32];
1249 tANI_U8 len = 0;
1250
1251 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1252 if (copy_to_user(priv_data.buf, &extra, len + 1))
1253 {
1254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1255 "%s: failed to copy data to user buffer", __func__);
1256 ret = -EFAULT;
1257 goto exit;
1258 }
1259 }
1260 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1261 {
1262 tANI_U8 *value = command;
1263 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1264
1265 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1266 value = value + 26;
1267 /* Convert the value from ascii to integer */
1268 ret = kstrtou8(value, 10, &minTime);
1269 if (ret < 0)
1270 {
1271 /* If the input value is greater than max value of datatype, then also
1272 kstrtou8 fails */
1273 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1274 "%s: kstrtou8 failed range [%d - %d]", __func__,
1275 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1276 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1277 ret = -EINVAL;
1278 goto exit;
1279 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001280 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1281 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1282 {
1283 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1284 "scan min channel time value %d is out of range"
1285 " (Min: %d Max: %d)", minTime,
1286 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1287 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1288 ret = -EINVAL;
1289 goto exit;
1290 }
1291
1292 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1293 "%s: Received Command to change channel min time = %d", __func__, minTime);
1294
1295 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1296 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1297 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001298 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1299 {
1300 tANI_U8 *value = command;
1301 tANI_U8 channel = 0;
1302 tANI_U8 dwellTime = 0;
1303 tANI_U8 bufLen = 0;
1304 tANI_U8 *buf = NULL;
1305 tSirMacAddr targetApBssid;
1306 eHalStatus status = eHAL_STATUS_SUCCESS;
1307 struct ieee80211_channel chan;
1308 tANI_U8 finalLen = 0;
1309 tANI_U8 *finalBuf = NULL;
1310 tANI_U8 temp = 0;
1311 u64 cookie;
1312 hdd_station_ctx_t *pHddStaCtx = NULL;
1313 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1314
1315 /* if not associated, no need to send action frame */
1316 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1317 {
1318 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1319 ret = -EINVAL;
1320 goto exit;
1321 }
1322
1323 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1324 &dwellTime, &buf, &bufLen);
1325 if (eHAL_STATUS_SUCCESS != status)
1326 {
1327 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1328 "%s: Failed to parse send action frame data", __func__);
1329 ret = -EINVAL;
1330 goto exit;
1331 }
1332
1333 /* if the target bssid is different from currently associated AP,
1334 then no need to send action frame */
1335 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1336 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1337 {
1338 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1339 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001340 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001341 goto exit;
1342 }
1343
1344 /* if the channel number is different from operating channel then
1345 no need to send action frame */
1346 if (channel != pHddStaCtx->conn_info.operationChannel)
1347 {
1348 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1349 "%s: channel(%d) is different from operating channel(%d)",
1350 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1351 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001352 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001353 goto exit;
1354 }
1355 chan.center_freq = sme_ChnToFreq(channel);
1356
1357 finalLen = bufLen + 24;
1358 finalBuf = vos_mem_malloc(finalLen);
1359 if (NULL == finalBuf)
1360 {
1361 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1362 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001363 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001364 goto exit;
1365 }
1366 vos_mem_zero(finalBuf, finalLen);
1367
1368 /* Fill subtype */
1369 temp = SIR_MAC_MGMT_ACTION << 4;
1370 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1371
1372 /* Fill type */
1373 temp = SIR_MAC_MGMT_FRAME;
1374 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1375
1376 /* Fill destination address (bssid of the AP) */
1377 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1378
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001379 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001380 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1381
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001382 /* Fill BSSID (AP mac address) */
1383 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001384
1385 /* Fill received buffer from 24th address */
1386 vos_mem_copy(finalBuf + 24, buf, bufLen);
1387
Jeff Johnson11c33152013-04-16 17:52:40 -07001388 /* done with the parsed buffer */
1389 vos_mem_free(buf);
1390
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001391 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1392 1, dwellTime, finalBuf, finalLen, 1,
1393 1, &cookie );
1394 vos_mem_free(finalBuf);
1395 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001396 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1397 {
1398 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1399 char extra[32];
1400 tANI_U8 len = 0;
1401
1402 /* value is interms of msec */
1403 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1404 if (copy_to_user(priv_data.buf, &extra, len + 1))
1405 {
1406 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1407 "%s: failed to copy data to user buffer", __func__);
1408 ret = -EFAULT;
1409 goto exit;
1410 }
1411 }
1412 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1413 {
1414 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001415 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001416 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001417
1418 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1419 value = value + 19;
1420 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001421 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001422 if (ret < 0)
1423 {
1424 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001425 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001426 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001427 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001428 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1429 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1430 ret = -EINVAL;
1431 goto exit;
1432 }
1433
1434 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1435 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1436 {
1437 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1438 "lfr mode value %d is out of range"
1439 " (Min: %d Max: %d)", maxTime,
1440 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1441 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1442 ret = -EINVAL;
1443 goto exit;
1444 }
1445
1446 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1447 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1448
1449 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001450
1451 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1452 * where RFS is the RF Switching time. It is twice RFS to consider the
1453 * time to go off channel and return to the home channel. */
1454 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1455 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1456 {
1457 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1458 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1459 " Hence enforcing home away time to disable (0)",
1460 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1461 homeAwayTime = 0;
1462 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1463 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
1464 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001465 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1466 }
1467 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1468 {
1469 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1470 char extra[32];
1471 tANI_U8 len = 0;
1472
1473 /* value is interms of msec */
1474 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1475 if (copy_to_user(priv_data.buf, &extra, len + 1))
1476 {
1477 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1478 "%s: failed to copy data to user buffer", __func__);
1479 ret = -EFAULT;
1480 goto exit;
1481 }
1482 }
1483 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1484 {
1485 tANI_U8 *value = command;
1486 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1487
1488 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1489 value = value + 16;
1490 /* Convert the value from ascii to integer */
1491 ret = kstrtou16(value, 10, &val);
1492 if (ret < 0)
1493 {
1494 /* If the input value is greater than max value of datatype, then also
1495 kstrtou16 fails */
1496 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1497 "%s: kstrtou16 failed range [%d - %d]", __func__,
1498 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1499 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1500 ret = -EINVAL;
1501 goto exit;
1502 }
1503
1504 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1505 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1506 {
1507 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1508 "scan home time value %d is out of range"
1509 " (Min: %d Max: %d)", val,
1510 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1511 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1512 ret = -EINVAL;
1513 goto exit;
1514 }
1515
1516 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1517 "%s: Received Command to change scan home time = %d", __func__, val);
1518
1519 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1520 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1521 }
1522 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1523 {
1524 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1525 char extra[32];
1526 tANI_U8 len = 0;
1527
1528 /* value is interms of msec */
1529 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1530 if (copy_to_user(priv_data.buf, &extra, len + 1))
1531 {
1532 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1533 "%s: failed to copy data to user buffer", __func__);
1534 ret = -EFAULT;
1535 goto exit;
1536 }
1537 }
1538 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1539 {
1540 tANI_U8 *value = command;
1541 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1542
1543 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1544 value = value + 17;
1545 /* Convert the value from ascii to integer */
1546 ret = kstrtou8(value, 10, &val);
1547 if (ret < 0)
1548 {
1549 /* If the input value is greater than max value of datatype, then also
1550 kstrtou8 fails */
1551 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1552 "%s: kstrtou8 failed range [%d - %d]", __func__,
1553 CFG_ROAM_INTRA_BAND_MIN,
1554 CFG_ROAM_INTRA_BAND_MAX);
1555 ret = -EINVAL;
1556 goto exit;
1557 }
1558
1559 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1560 (val > CFG_ROAM_INTRA_BAND_MAX))
1561 {
1562 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1563 "intra band mode value %d is out of range"
1564 " (Min: %d Max: %d)", val,
1565 CFG_ROAM_INTRA_BAND_MIN,
1566 CFG_ROAM_INTRA_BAND_MAX);
1567 ret = -EINVAL;
1568 goto exit;
1569 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001570 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1571 "%s: Received Command to change intra band = %d", __func__, val);
1572
1573 pHddCtx->cfg_ini->nRoamIntraBand = val;
1574 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1575 }
1576 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1577 {
1578 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1579 char extra[32];
1580 tANI_U8 len = 0;
1581
1582 /* value is interms of msec */
1583 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1584 if (copy_to_user(priv_data.buf, &extra, len + 1))
1585 {
1586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1587 "%s: failed to copy data to user buffer", __func__);
1588 ret = -EFAULT;
1589 goto exit;
1590 }
1591 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001592 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1593 {
1594 tANI_U8 *value = command;
1595 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1596
1597 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1598 value = value + 15;
1599 /* Convert the value from ascii to integer */
1600 ret = kstrtou8(value, 10, &nProbes);
1601 if (ret < 0)
1602 {
1603 /* If the input value is greater than max value of datatype, then also
1604 kstrtou8 fails */
1605 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1606 "%s: kstrtou8 failed range [%d - %d]", __func__,
1607 CFG_ROAM_SCAN_N_PROBES_MIN,
1608 CFG_ROAM_SCAN_N_PROBES_MAX);
1609 ret = -EINVAL;
1610 goto exit;
1611 }
1612
1613 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1614 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1615 {
1616 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1617 "NProbes value %d is out of range"
1618 " (Min: %d Max: %d)", nProbes,
1619 CFG_ROAM_SCAN_N_PROBES_MIN,
1620 CFG_ROAM_SCAN_N_PROBES_MAX);
1621 ret = -EINVAL;
1622 goto exit;
1623 }
1624
1625 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1626 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1627
1628 pHddCtx->cfg_ini->nProbes = nProbes;
1629 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1630 }
1631 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1632 {
1633 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1634 char extra[32];
1635 tANI_U8 len = 0;
1636
1637 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1638 if (copy_to_user(priv_data.buf, &extra, len + 1))
1639 {
1640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1641 "%s: failed to copy data to user buffer", __func__);
1642 ret = -EFAULT;
1643 goto exit;
1644 }
1645 }
1646 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1647 {
1648 tANI_U8 *value = command;
1649 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001650 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001651
1652 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1653 /* input value is in units of msec */
1654 value = value + 20;
1655 /* Convert the value from ascii to integer */
1656 ret = kstrtou16(value, 10, &homeAwayTime);
1657 if (ret < 0)
1658 {
1659 /* If the input value is greater than max value of datatype, then also
1660 kstrtou8 fails */
1661 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1662 "%s: kstrtou8 failed range [%d - %d]", __func__,
1663 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1664 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1665 ret = -EINVAL;
1666 goto exit;
1667 }
1668
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001669 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1670 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1671 {
1672 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1673 "homeAwayTime value %d is out of range"
1674 " (Min: %d Max: %d)", homeAwayTime,
1675 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1676 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1677 ret = -EINVAL;
1678 goto exit;
1679 }
1680
1681 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1682 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1683
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001684 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1685 * where RFS is the RF Switching time. It is twice RFS to consider the
1686 * time to go off channel and return to the home channel. */
1687 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1688 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1689 {
1690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1691 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1692 " Hence enforcing home away time to disable (0)",
1693 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1694 homeAwayTime = 0;
1695 }
1696
1697 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
1698 {
1699 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1700 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
1701 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001702 }
1703 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1704 {
1705 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1706 char extra[32];
1707 tANI_U8 len = 0;
1708
1709 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1710 if (copy_to_user(priv_data.buf, &extra, len + 1))
1711 {
1712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1713 "%s: failed to copy data to user buffer", __func__);
1714 ret = -EFAULT;
1715 goto exit;
1716 }
1717 }
1718 else if (strncmp(command, "REASSOC", 7) == 0)
1719 {
1720 tANI_U8 *value = command;
1721 tANI_U8 channel = 0;
1722 tSirMacAddr targetApBssid;
1723 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001724#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1725 tCsrHandoffRequest handoffInfo;
1726#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001727 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001728 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1729
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001730 /* if not associated, no need to proceed with reassoc */
1731 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1732 {
1733 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1734 ret = -EINVAL;
1735 goto exit;
1736 }
1737
1738 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1739 if (eHAL_STATUS_SUCCESS != status)
1740 {
1741 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1742 "%s: Failed to parse reassoc command data", __func__);
1743 ret = -EINVAL;
1744 goto exit;
1745 }
1746
1747 /* if the target bssid is same as currently associated AP,
1748 then no need to proceed with reassoc */
1749 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1750 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1751 {
1752 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1753 ret = -EINVAL;
1754 goto exit;
1755 }
1756
1757 /* Check channel number is a valid channel number */
1758 if(VOS_STATUS_SUCCESS !=
1759 wlan_hdd_validate_operation_channel(pAdapter, channel))
1760 {
1761 hddLog(VOS_TRACE_LEVEL_ERROR,
1762 "%s: Invalid Channel [%d] \n", __func__, channel);
1763 return -EINVAL;
1764 }
1765
1766 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001767#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1768 handoffInfo.channel = channel;
1769 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1770 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1771#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001772 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001773#endif
1774#ifdef FEATURE_WLAN_LFR
1775 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1776 {
1777 tANI_U8 *value = command;
1778 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1779
1780 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1781 value = value + 12;
1782 /* Convert the value from ascii to integer */
1783 ret = kstrtou8(value, 10, &lfrMode);
1784 if (ret < 0)
1785 {
1786 /* If the input value is greater than max value of datatype, then also
1787 kstrtou8 fails */
1788 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1789 "%s: kstrtou8 failed range [%d - %d]", __func__,
1790 CFG_LFR_FEATURE_ENABLED_MIN,
1791 CFG_LFR_FEATURE_ENABLED_MAX);
1792 ret = -EINVAL;
1793 goto exit;
1794 }
1795
1796 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1797 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1798 {
1799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1800 "lfr mode value %d is out of range"
1801 " (Min: %d Max: %d)", lfrMode,
1802 CFG_LFR_FEATURE_ENABLED_MIN,
1803 CFG_LFR_FEATURE_ENABLED_MAX);
1804 ret = -EINVAL;
1805 goto exit;
1806 }
1807
1808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1809 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1810
1811 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1812 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1813 }
1814#endif
1815#ifdef WLAN_FEATURE_VOWIFI_11R
1816 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1817 {
1818 tANI_U8 *value = command;
1819 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1820
1821 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1822 value = value + 18;
1823 /* Convert the value from ascii to integer */
1824 ret = kstrtou8(value, 10, &ft);
1825 if (ret < 0)
1826 {
1827 /* If the input value is greater than max value of datatype, then also
1828 kstrtou8 fails */
1829 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1830 "%s: kstrtou8 failed range [%d - %d]", __func__,
1831 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1832 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1833 ret = -EINVAL;
1834 goto exit;
1835 }
1836
1837 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1838 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1839 {
1840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1841 "ft mode value %d is out of range"
1842 " (Min: %d Max: %d)", ft,
1843 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1844 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1845 ret = -EINVAL;
1846 goto exit;
1847 }
1848
1849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1850 "%s: Received Command to change ft mode = %d", __func__, ft);
1851
1852 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1853 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1854 }
1855#endif
1856#ifdef FEATURE_WLAN_CCX
1857 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1858 {
1859 tANI_U8 *value = command;
1860 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1861
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001862 /* Check if the features OKC/CCX/11R are supported simultaneously,
1863 then this operation is not permitted (return FAILURE) */
1864 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1865 hdd_is_okc_mode_enabled(pHddCtx) &&
1866 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1867 {
1868 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1869 "%s: OKC/CCX/11R are supported simultaneously"
1870 " hence this operation is not permitted!", __func__);
1871 ret = -EPERM;
1872 goto exit;
1873 }
1874
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001875 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1876 value = value + 11;
1877 /* Convert the value from ascii to integer */
1878 ret = kstrtou8(value, 10, &ccxMode);
1879 if (ret < 0)
1880 {
1881 /* If the input value is greater than max value of datatype, then also
1882 kstrtou8 fails */
1883 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1884 "%s: kstrtou8 failed range [%d - %d]", __func__,
1885 CFG_CCX_FEATURE_ENABLED_MIN,
1886 CFG_CCX_FEATURE_ENABLED_MAX);
1887 ret = -EINVAL;
1888 goto exit;
1889 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001890 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1891 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1892 {
1893 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1894 "Ccx mode value %d is out of range"
1895 " (Min: %d Max: %d)", ccxMode,
1896 CFG_CCX_FEATURE_ENABLED_MIN,
1897 CFG_CCX_FEATURE_ENABLED_MAX);
1898 ret = -EINVAL;
1899 goto exit;
1900 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001901 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1902 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1903
1904 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1905 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1906 }
1907#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001908 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1909 {
1910 tANI_U8 *value = command;
1911 tANI_BOOLEAN roamScanControl = 0;
1912
1913 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1914 value = value + 19;
1915 /* Convert the value from ascii to integer */
1916 ret = kstrtou8(value, 10, &roamScanControl);
1917 if (ret < 0)
1918 {
1919 /* If the input value is greater than max value of datatype, then also
1920 kstrtou8 fails */
1921 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1922 "%s: kstrtou8 failed ", __func__);
1923 ret = -EINVAL;
1924 goto exit;
1925 }
1926
1927 if (0 != roamScanControl)
1928 {
1929 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1930 "roam scan control invalid value = %d",
1931 roamScanControl);
1932 ret = -EINVAL;
1933 goto exit;
1934 }
1935 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1936 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1937
1938 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1939 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001940#ifdef FEATURE_WLAN_OKC
1941 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1942 {
1943 tANI_U8 *value = command;
1944 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1945
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001946 /* Check if the features OKC/CCX/11R are supported simultaneously,
1947 then this operation is not permitted (return FAILURE) */
1948 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1949 hdd_is_okc_mode_enabled(pHddCtx) &&
1950 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1951 {
1952 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1953 "%s: OKC/CCX/11R are supported simultaneously"
1954 " hence this operation is not permitted!", __func__);
1955 ret = -EPERM;
1956 goto exit;
1957 }
1958
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001959 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1960 value = value + 11;
1961 /* Convert the value from ascii to integer */
1962 ret = kstrtou8(value, 10, &okcMode);
1963 if (ret < 0)
1964 {
1965 /* If the input value is greater than max value of datatype, then also
1966 kstrtou8 fails */
1967 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1968 "%s: kstrtou8 failed range [%d - %d]", __func__,
1969 CFG_OKC_FEATURE_ENABLED_MIN,
1970 CFG_OKC_FEATURE_ENABLED_MAX);
1971 ret = -EINVAL;
1972 goto exit;
1973 }
1974
1975 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1976 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1977 {
1978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1979 "Okc mode value %d is out of range"
1980 " (Min: %d Max: %d)", okcMode,
1981 CFG_OKC_FEATURE_ENABLED_MIN,
1982 CFG_OKC_FEATURE_ENABLED_MAX);
1983 ret = -EINVAL;
1984 goto exit;
1985 }
1986
1987 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1988 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1989
1990 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1991 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001992 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1993 {
1994 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1995 char extra[32];
1996 tANI_U8 len = 0;
1997
1998 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1999 if (copy_to_user(priv_data.buf, &extra, len + 1))
2000 {
2001 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2002 "%s: failed to copy data to user buffer", __func__);
2003 ret = -EFAULT;
2004 goto exit;
2005 }
2006 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002007#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05302008#ifdef WLAN_FEATURE_PACKET_FILTERING
2009 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
2010 {
2011 tANI_U8 filterType = 0;
2012 tANI_U8 *value = command;
2013
2014 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
2015 value = value + 22;
2016
2017 /* Convert the value from ascii to integer */
2018 ret = kstrtou8(value, 10, &filterType);
2019 if (ret < 0)
2020 {
2021 /* If the input value is greater than max value of datatype,
2022 * then also kstrtou8 fails
2023 */
2024 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2025 "%s: kstrtou8 failed range ", __func__);
2026 ret = -EINVAL;
2027 goto exit;
2028 }
2029
2030 if (filterType != 0 && filterType != 1)
2031 {
2032 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2033 "%s: Accepted Values are 0 and 1 ", __func__);
2034 ret = -EINVAL;
2035 goto exit;
2036 }
2037 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
2038 pAdapter->sessionId);
2039 }
2040#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05302041 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
2042 {
2043 char *dhcpPhase;
2044 dhcpPhase = command + 12;
2045 if ('1' == *dhcpPhase)
2046 {
2047 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
2048 pAdapter->macAddressCurrent.bytes);
2049 }
2050 else if ('2' == *dhcpPhase)
2051 {
2052 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
2053 pAdapter->macAddressCurrent.bytes);
2054 }
2055 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07002056 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
2057 {
2058 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
2059 }
2060 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
2061 {
2062 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
2063 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05302064 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2065 {
2066 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
2067 char extra[32];
2068 tANI_U8 len = 0;
2069
2070 len = snprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
2071 (int)pCfg->nActiveMaxChnTime);
2072 if (copy_to_user(priv_data.buf, &extra, len + 1))
2073 {
2074 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2075 "%s: failed to copy data to user buffer", __func__);
2076 ret = -EFAULT;
2077 goto exit;
2078 }
2079 ret = len;
2080 }
2081 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2082 {
2083 tANI_U8 *value = command;
2084 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
2085 int val = 0, temp;
2086
2087 value = value + 13;
2088 temp = kstrtou32(value, 10, &val);
2089 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2090 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2091 {
2092 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2093 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2094 ret = -EFAULT;
2095 goto exit;
2096 }
2097 pCfg->nActiveMaxChnTime = val;
2098 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002099 else {
2100 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2101 __func__, command);
2102 }
2103
Jeff Johnson295189b2012-06-20 16:38:30 -07002104 }
2105exit:
2106 if (command)
2107 {
2108 kfree(command);
2109 }
2110 return ret;
2111}
2112
Srinivas Girigowdade697412013-02-14 16:31:48 -08002113#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2114void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2115{
2116 eCsrBand band = -1;
2117 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2118 switch (band)
2119 {
2120 case eCSR_BAND_ALL:
2121 *pBand = WLAN_HDD_UI_BAND_AUTO;
2122 break;
2123
2124 case eCSR_BAND_24:
2125 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2126 break;
2127
2128 case eCSR_BAND_5G:
2129 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2130 break;
2131
2132 default:
2133 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2134 *pBand = -1;
2135 break;
2136 }
2137}
2138
2139/**---------------------------------------------------------------------------
2140
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002141 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2142
2143 This function parses the send action frame data passed in the format
2144 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2145
2146 \param - pValue Pointer to input country code revision
2147 \param - pTargetApBssid Pointer to target Ap bssid
2148 \param - pChannel Pointer to the Target AP channel
2149 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2150 \param - pBuf Pointer to data
2151 \param - pBufLen Pointer to data length
2152
2153 \return - 0 for success non-zero for failure
2154
2155 --------------------------------------------------------------------------*/
2156VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2157 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2158{
2159 tANI_U8 *inPtr = pValue;
2160 tANI_U8 *dataEnd;
2161 int tempInt;
2162 int j = 0;
2163 int i = 0;
2164 int v = 0;
2165 tANI_U8 tempBuf[32];
2166 tANI_U8 tempByte = 0;
2167
2168 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2169 /*no argument after the command*/
2170 if (NULL == inPtr)
2171 {
2172 return -EINVAL;
2173 }
2174
2175 /*no space after the command*/
2176 else if (SPACE_ASCII_VALUE != *inPtr)
2177 {
2178 return -EINVAL;
2179 }
2180
2181 /*removing empty spaces*/
2182 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2183
2184 /*no argument followed by spaces*/
2185 if ('\0' == *inPtr)
2186 {
2187 return -EINVAL;
2188 }
2189
2190 /*getting the first argument ie the target AP bssid */
2191 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2192 {
2193 return -EINVAL;
2194 }
2195 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2196 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2197 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2198
2199 /* point to the next argument */
2200 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2201 /*no argument after the command*/
2202 if (NULL == inPtr) return -EINVAL;
2203
2204 /*removing empty spaces*/
2205 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2206
2207 /*no argument followed by spaces*/
2208 if ('\0' == *inPtr)
2209 {
2210 return -EINVAL;
2211 }
2212
2213 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002214 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002215 v = kstrtos32(tempBuf, 10, &tempInt);
2216 if ( v < 0) return -EINVAL;
2217
2218 *pChannel = tempInt;
2219
2220 /* point to the next argument */
2221 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2222 /*no argument after the command*/
2223 if (NULL == inPtr) return -EINVAL;
2224 /*removing empty spaces*/
2225 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2226
2227 /*no argument followed by spaces*/
2228 if ('\0' == *inPtr)
2229 {
2230 return -EINVAL;
2231 }
2232
2233 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002234 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002235 v = kstrtos32(tempBuf, 10, &tempInt);
2236 if ( v < 0) return -EINVAL;
2237
2238 *pDwellTime = tempInt;
2239
2240 /* point to the next argument */
2241 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2242 /*no argument after the command*/
2243 if (NULL == inPtr) return -EINVAL;
2244 /*removing empty spaces*/
2245 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2246
2247 /*no argument followed by spaces*/
2248 if ('\0' == *inPtr)
2249 {
2250 return -EINVAL;
2251 }
2252
2253 /* find the length of data */
2254 dataEnd = inPtr;
2255 while(('\0' != *dataEnd) )
2256 {
2257 dataEnd++;
2258 ++(*pBufLen);
2259 }
2260 if ( *pBufLen <= 0) return -EINVAL;
2261
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002262 /* Allocate the number of bytes based on the number of input characters
2263 whether it is even or odd.
2264 if the number of input characters are even, then we need N/2 byte.
2265 if the number of input characters are odd, then we need do (N+1)/2 to
2266 compensate rounding off.
2267 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2268 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2269 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002270 if (NULL == *pBuf)
2271 {
2272 hddLog(VOS_TRACE_LEVEL_FATAL,
2273 "%s: vos_mem_alloc failed ", __func__);
2274 return -EINVAL;
2275 }
2276
2277 /* the buffer received from the upper layer is character buffer,
2278 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2279 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2280 and f0 in 3rd location */
2281 for (i = 0, j = 0; j < *pBufLen; j += 2)
2282 {
2283 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2284 (*pBuf)[i++] = tempByte;
2285 }
2286 *pBufLen = i;
2287 return VOS_STATUS_SUCCESS;
2288}
2289
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002290/**---------------------------------------------------------------------------
2291
Srinivas Girigowdade697412013-02-14 16:31:48 -08002292 \brief hdd_parse_countryrev() - HDD Parse country code revision
2293
2294 This function parses the country code revision passed in the format
2295 SETCOUNTRYREV<space><Country code><space>revision
2296
2297 \param - pValue Pointer to input country code revision
2298 \param - pCountryCode Pointer to local output array to record country code
2299 \param - pRevision Pointer to store revision integer number
2300
2301 \return - 0 for success non-zero for failure
2302
2303 --------------------------------------------------------------------------*/
2304VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
2305{
2306 tANI_U8 *inPtr = pValue;
2307 int tempInt;
2308
2309 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2310 /*no argument after the command*/
2311 if (NULL == inPtr)
2312 {
2313 return -EINVAL;
2314 }
2315
2316 /*no space after the command*/
2317 else if (SPACE_ASCII_VALUE != *inPtr)
2318 {
2319 return -EINVAL;
2320 }
2321
2322 /*removing empty spaces*/
2323 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
2324
2325 /*no argument followed by spaces*/
2326 if ('\0' == *inPtr)
2327 {
2328 return -EINVAL;
2329 }
2330
2331 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07002332 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002333
2334 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2335 "Country code is : %s", pCountryCode);
2336
2337 /*inPtr pointing to the beginning of first space after country code */
2338 inPtr = strpbrk( inPtr, " " );
2339 /*no revision number after the country code argument */
2340 if (NULL == inPtr)
2341 {
2342 return -EINVAL;
2343 }
2344
2345 inPtr++;
2346
2347 /*removing empty space*/
2348 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2349
2350 /*no channel list after the number of channels argument and spaces*/
2351 if (0 == strncmp(pCountryCode, "KR", 2))
2352 {
2353 if ('\0' == *inPtr)
2354 {
2355 return -EINVAL;
2356 }
2357
2358 sscanf(inPtr, "%d", &tempInt);
2359 *pRevision = tempInt;
2360 }
2361 else
2362 {
2363 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2364 "Revision input is required only for Country KR");
2365 return -EINVAL;
2366 }
2367 return VOS_STATUS_SUCCESS;
2368}
2369
2370/**---------------------------------------------------------------------------
2371
2372 \brief hdd_parse_channellist() - HDD Parse channel list
2373
2374 This function parses the channel list passed in the format
2375 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002376 if the Number of channels (N) does not match with the actual number of channels passed
2377 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2378 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2379 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2380 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002381
2382 \param - pValue Pointer to input channel list
2383 \param - ChannelList Pointer to local output array to record channel list
2384 \param - pNumChannels Pointer to number of roam scan channels
2385
2386 \return - 0 for success non-zero for failure
2387
2388 --------------------------------------------------------------------------*/
2389VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2390{
2391 tANI_U8 *inPtr = pValue;
2392 int tempInt;
2393 int j = 0;
2394 int v = 0;
2395 char buf[32];
2396
2397 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2398 /*no argument after the command*/
2399 if (NULL == inPtr)
2400 {
2401 return -EINVAL;
2402 }
2403
2404 /*no space after the command*/
2405 else if (SPACE_ASCII_VALUE != *inPtr)
2406 {
2407 return -EINVAL;
2408 }
2409
2410 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002411 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002412
2413 /*no argument followed by spaces*/
2414 if ('\0' == *inPtr)
2415 {
2416 return -EINVAL;
2417 }
2418
2419 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002420 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002421 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002422 if ((v < 0) ||
2423 (tempInt <= 0) ||
2424 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2425 {
2426 return -EINVAL;
2427 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002428
2429 *pNumChannels = tempInt;
2430
2431 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2432 "Number of channels are: %d", *pNumChannels);
2433
2434 for (j = 0; j < (*pNumChannels); j++)
2435 {
2436 /*inPtr pointing to the beginning of first space after number of channels*/
2437 inPtr = strpbrk( inPtr, " " );
2438 /*no channel list after the number of channels argument*/
2439 if (NULL == inPtr)
2440 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002441 if (0 != j)
2442 {
2443 *pNumChannels = j;
2444 return VOS_STATUS_SUCCESS;
2445 }
2446 else
2447 {
2448 return -EINVAL;
2449 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002450 }
2451
2452 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002453 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002454
2455 /*no channel list after the number of channels argument and spaces*/
2456 if ( '\0' == *inPtr )
2457 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002458 if (0 != j)
2459 {
2460 *pNumChannels = j;
2461 return VOS_STATUS_SUCCESS;
2462 }
2463 else
2464 {
2465 return -EINVAL;
2466 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002467 }
2468
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002469 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002470 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002471 if ((v < 0) ||
2472 (tempInt <= 0) ||
2473 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2474 {
2475 return -EINVAL;
2476 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002477 pChannelList[j] = tempInt;
2478
2479 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2480 "Channel %d added to preferred channel list",
2481 pChannelList[j] );
2482 }
2483
Srinivas Girigowdade697412013-02-14 16:31:48 -08002484 return VOS_STATUS_SUCCESS;
2485}
2486
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002487
2488/**---------------------------------------------------------------------------
2489
2490 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2491
2492 This function parses the reasoc command data passed in the format
2493 REASSOC<space><bssid><space><channel>
2494
2495 \param - pValue Pointer to input country code revision
2496 \param - pTargetApBssid Pointer to target Ap bssid
2497 \param - pChannel Pointer to the Target AP channel
2498
2499 \return - 0 for success non-zero for failure
2500
2501 --------------------------------------------------------------------------*/
2502VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2503{
2504 tANI_U8 *inPtr = pValue;
2505 int tempInt;
2506 int v = 0;
2507 tANI_U8 tempBuf[32];
2508
2509 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2510 /*no argument after the command*/
2511 if (NULL == inPtr)
2512 {
2513 return -EINVAL;
2514 }
2515
2516 /*no space after the command*/
2517 else if (SPACE_ASCII_VALUE != *inPtr)
2518 {
2519 return -EINVAL;
2520 }
2521
2522 /*removing empty spaces*/
2523 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2524
2525 /*no argument followed by spaces*/
2526 if ('\0' == *inPtr)
2527 {
2528 return -EINVAL;
2529 }
2530
2531 /*getting the first argument ie the target AP bssid */
2532 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2533 {
2534 return -EINVAL;
2535 }
2536 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2537 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2538 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2539
2540 /* point to the next argument */
2541 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2542 /*no argument after the command*/
2543 if (NULL == inPtr) return -EINVAL;
2544
2545 /*removing empty spaces*/
2546 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2547
2548 /*no argument followed by spaces*/
2549 if ('\0' == *inPtr)
2550 {
2551 return -EINVAL;
2552 }
2553
2554 /*getting the next argument ie the channel number */
2555 sscanf(inPtr, "%s ", tempBuf);
2556 v = kstrtos32(tempBuf, 10, &tempInt);
2557 if ( v < 0) return -EINVAL;
2558
2559 *pChannel = tempInt;
2560 return VOS_STATUS_SUCCESS;
2561}
2562
2563#endif
2564
Jeff Johnson295189b2012-06-20 16:38:30 -07002565/**---------------------------------------------------------------------------
2566
2567 \brief hdd_open() - HDD Open function
2568
2569 This is called in response to ifconfig up
2570
2571 \param - dev Pointer to net_device structure
2572
2573 \return - 0 for success non-zero for failure
2574
2575 --------------------------------------------------------------------------*/
2576int hdd_open (struct net_device *dev)
2577{
2578 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2579 hdd_context_t *pHddCtx;
2580 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2581 VOS_STATUS status;
2582 v_BOOL_t in_standby = TRUE;
2583
2584 if (NULL == pAdapter)
2585 {
2586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002587 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002588 return -ENODEV;
2589 }
2590
2591 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2592 if (NULL == pHddCtx)
2593 {
2594 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002595 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002596 return -ENODEV;
2597 }
2598
2599 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2600 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2601 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002602 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2603 {
2604 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302605 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002606 in_standby = FALSE;
2607 break;
2608 }
2609 else
2610 {
2611 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2612 pAdapterNode = pNext;
2613 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002614 }
2615
2616 if (TRUE == in_standby)
2617 {
2618 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2619 {
2620 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2621 "wlan out of power save", __func__);
2622 return -EINVAL;
2623 }
2624 }
2625
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002626 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002627 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2628 {
2629 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002630 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002631 /* Enable TX queues only when we are connected */
2632 netif_tx_start_all_queues(dev);
2633 }
2634
2635 return 0;
2636}
2637
2638int hdd_mon_open (struct net_device *dev)
2639{
2640 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2641
2642 if(pAdapter == NULL) {
2643 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002644 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002645 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002646 }
2647
2648 netif_start_queue(dev);
2649
2650 return 0;
2651}
2652/**---------------------------------------------------------------------------
2653
2654 \brief hdd_stop() - HDD stop function
2655
2656 This is called in response to ifconfig down
2657
2658 \param - dev Pointer to net_device structure
2659
2660 \return - 0 for success non-zero for failure
2661
2662 --------------------------------------------------------------------------*/
2663
2664int hdd_stop (struct net_device *dev)
2665{
2666 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2667 hdd_context_t *pHddCtx;
2668 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2669 VOS_STATUS status;
2670 v_BOOL_t enter_standby = TRUE;
2671
2672 ENTER();
2673
2674 if (NULL == pAdapter)
2675 {
2676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002677 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002678 return -ENODEV;
2679 }
2680
2681 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2682 if (NULL == pHddCtx)
2683 {
2684 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002685 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002686 return -ENODEV;
2687 }
2688
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002689 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002690 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2691 netif_tx_disable(pAdapter->dev);
2692 netif_carrier_off(pAdapter->dev);
2693
2694
2695 /* SoftAP ifaces should never go in power save mode
2696 making sure same here. */
2697 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2698 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002699 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002700 )
2701 {
2702 /* SoftAP mode, so return from here */
2703 EXIT();
2704 return 0;
2705 }
2706
2707 /* Find if any iface is up then
2708 if any iface is up then can't put device to sleep/ power save mode. */
2709 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2710 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2711 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002712 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2713 {
2714 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302715 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002716 enter_standby = FALSE;
2717 break;
2718 }
2719 else
2720 {
2721 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2722 pAdapterNode = pNext;
2723 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002724 }
2725
2726 if (TRUE == enter_standby)
2727 {
2728 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2729 "entering standby", __func__);
2730 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2731 {
2732 /*log and return success*/
2733 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2734 "wlan in power save", __func__);
2735 }
2736 }
2737
2738 EXIT();
2739 return 0;
2740}
2741
2742/**---------------------------------------------------------------------------
2743
2744 \brief hdd_uninit() - HDD uninit function
2745
2746 This is called during the netdev unregister to uninitialize all data
2747associated with the device
2748
2749 \param - dev Pointer to net_device structure
2750
2751 \return - void
2752
2753 --------------------------------------------------------------------------*/
2754static void hdd_uninit (struct net_device *dev)
2755{
2756 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2757
2758 ENTER();
2759
2760 do
2761 {
2762 if (NULL == pAdapter)
2763 {
2764 hddLog(VOS_TRACE_LEVEL_FATAL,
2765 "%s: NULL pAdapter", __func__);
2766 break;
2767 }
2768
2769 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2770 {
2771 hddLog(VOS_TRACE_LEVEL_FATAL,
2772 "%s: Invalid magic", __func__);
2773 break;
2774 }
2775
2776 if (NULL == pAdapter->pHddCtx)
2777 {
2778 hddLog(VOS_TRACE_LEVEL_FATAL,
2779 "%s: NULL pHddCtx", __func__);
2780 break;
2781 }
2782
2783 if (dev != pAdapter->dev)
2784 {
2785 hddLog(VOS_TRACE_LEVEL_FATAL,
2786 "%s: Invalid device reference", __func__);
2787 /* we haven't validated all cases so let this go for now */
2788 }
2789
2790 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2791
2792 /* after uninit our adapter structure will no longer be valid */
2793 pAdapter->dev = NULL;
2794 pAdapter->magic = 0;
2795 } while (0);
2796
2797 EXIT();
2798}
2799
2800/**---------------------------------------------------------------------------
2801
2802 \brief hdd_release_firmware() -
2803
2804 This function calls the release firmware API to free the firmware buffer.
2805
2806 \param - pFileName Pointer to the File Name.
2807 pCtx - Pointer to the adapter .
2808
2809
2810 \return - 0 for success, non zero for failure
2811
2812 --------------------------------------------------------------------------*/
2813
2814VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2815{
2816 VOS_STATUS status = VOS_STATUS_SUCCESS;
2817 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2818 ENTER();
2819
2820
2821 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2822
2823 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2824
2825 if(pHddCtx->fw) {
2826 release_firmware(pHddCtx->fw);
2827 pHddCtx->fw = NULL;
2828 }
2829 else
2830 status = VOS_STATUS_E_FAILURE;
2831 }
2832 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2833 if(pHddCtx->nv) {
2834 release_firmware(pHddCtx->nv);
2835 pHddCtx->nv = NULL;
2836 }
2837 else
2838 status = VOS_STATUS_E_FAILURE;
2839
2840 }
2841
2842 EXIT();
2843 return status;
2844}
2845
2846/**---------------------------------------------------------------------------
2847
2848 \brief hdd_request_firmware() -
2849
2850 This function reads the firmware file using the request firmware
2851 API and returns the the firmware data and the firmware file size.
2852
2853 \param - pfileName - Pointer to the file name.
2854 - pCtx - Pointer to the adapter .
2855 - ppfw_data - Pointer to the pointer of the firmware data.
2856 - pSize - Pointer to the file size.
2857
2858 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2859
2860 --------------------------------------------------------------------------*/
2861
2862
2863VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2864{
2865 int status;
2866 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2867 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2868 ENTER();
2869
2870 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2871
2872 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2873
2874 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2875 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2876 __func__, pfileName);
2877 retval = VOS_STATUS_E_FAILURE;
2878 }
2879
2880 else {
2881 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2882 *pSize = pHddCtx->fw->size;
2883 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2884 __func__, *pSize);
2885 }
2886 }
2887 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2888
2889 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2890
2891 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2892 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2893 __func__, pfileName);
2894 retval = VOS_STATUS_E_FAILURE;
2895 }
2896
2897 else {
2898 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2899 *pSize = pHddCtx->nv->size;
2900 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2901 __func__, *pSize);
2902 }
2903 }
2904
2905 EXIT();
2906 return retval;
2907}
2908/**---------------------------------------------------------------------------
2909 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2910
2911 This is the function invoked by SME to inform the result of a full power
2912 request issued by HDD
2913
2914 \param - callbackcontext - Pointer to cookie
2915 status - result of request
2916
2917 \return - None
2918
2919--------------------------------------------------------------------------*/
2920void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2921{
2922 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2923
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002924 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002925 if(&pHddCtx->full_pwr_comp_var)
2926 {
2927 complete(&pHddCtx->full_pwr_comp_var);
2928 }
2929}
2930
2931/**---------------------------------------------------------------------------
2932
2933 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2934
2935 This is the function invoked by SME to inform the result of BMPS
2936 request issued by HDD
2937
2938 \param - callbackcontext - Pointer to cookie
2939 status - result of request
2940
2941 \return - None
2942
2943--------------------------------------------------------------------------*/
2944void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2945{
2946
2947 struct completion *completion_var = (struct completion*) callbackContext;
2948
2949 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2950 if(completion_var != NULL)
2951 {
2952 complete(completion_var);
2953 }
2954}
2955
2956/**---------------------------------------------------------------------------
2957
2958 \brief hdd_get_cfg_file_size() -
2959
2960 This function reads the configuration file using the request firmware
2961 API and returns the configuration file size.
2962
2963 \param - pCtx - Pointer to the adapter .
2964 - pFileName - Pointer to the file name.
2965 - pBufSize - Pointer to the buffer size.
2966
2967 \return - 0 for success, non zero for failure
2968
2969 --------------------------------------------------------------------------*/
2970
2971VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2972{
2973 int status;
2974 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2975
2976 ENTER();
2977
2978 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2979
2980 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2981 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2982 status = VOS_STATUS_E_FAILURE;
2983 }
2984 else {
2985 *pBufSize = pHddCtx->fw->size;
2986 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2987 release_firmware(pHddCtx->fw);
2988 pHddCtx->fw = NULL;
2989 }
2990
2991 EXIT();
2992 return VOS_STATUS_SUCCESS;
2993}
2994
2995/**---------------------------------------------------------------------------
2996
2997 \brief hdd_read_cfg_file() -
2998
2999 This function reads the configuration file using the request firmware
3000 API and returns the cfg data and the buffer size of the configuration file.
3001
3002 \param - pCtx - Pointer to the adapter .
3003 - pFileName - Pointer to the file name.
3004 - pBuffer - Pointer to the data buffer.
3005 - pBufSize - Pointer to the buffer size.
3006
3007 \return - 0 for success, non zero for failure
3008
3009 --------------------------------------------------------------------------*/
3010
3011VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
3012 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
3013{
3014 int status;
3015 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
3016
3017 ENTER();
3018
3019 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
3020
3021 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
3022 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
3023 return VOS_STATUS_E_FAILURE;
3024 }
3025 else {
3026 if(*pBufSize != pHddCtx->fw->size) {
3027 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
3028 "file size", __func__);
3029 release_firmware(pHddCtx->fw);
3030 pHddCtx->fw = NULL;
3031 return VOS_STATUS_E_FAILURE;
3032 }
3033 else {
3034 if(pBuffer) {
3035 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
3036 }
3037 release_firmware(pHddCtx->fw);
3038 pHddCtx->fw = NULL;
3039 }
3040 }
3041
3042 EXIT();
3043
3044 return VOS_STATUS_SUCCESS;
3045}
3046
3047/**---------------------------------------------------------------------------
3048
Jeff Johnson295189b2012-06-20 16:38:30 -07003049 \brief hdd_set_mac_address() -
3050
3051 This function sets the user specified mac address using
3052 the command ifconfig wlanX hw ether <mac adress>.
3053
3054 \param - dev - Pointer to the net device.
3055 - addr - Pointer to the sockaddr.
3056 \return - 0 for success, non zero for failure
3057
3058 --------------------------------------------------------------------------*/
3059
3060static int hdd_set_mac_address(struct net_device *dev, void *addr)
3061{
3062 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3063 struct sockaddr *psta_mac_addr = addr;
3064 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3065
3066 ENTER();
3067
3068 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
3069
3070#ifdef HDD_SESSIONIZE
3071 // set the MAC address though the STA ID CFG.
3072 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
3073 (v_U8_t *)&pAdapter->macAddressCurrent,
3074 sizeof( pAdapter->macAddressCurrent ),
3075 hdd_set_mac_addr_cb, VOS_FALSE );
3076#endif
3077
3078 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
3079
3080 EXIT();
3081 return halStatus;
3082}
3083
3084tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
3085{
3086 int i;
3087 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3088 {
3089 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
3090 break;
3091 }
3092
3093 if( VOS_MAX_CONCURRENCY_PERSONA == i)
3094 return NULL;
3095
3096 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
3097 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
3098}
3099
3100void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
3101{
3102 int i;
3103 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3104 {
3105 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
3106 {
3107 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
3108 break;
3109 }
3110 }
3111 return;
3112}
3113
3114#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3115 static struct net_device_ops wlan_drv_ops = {
3116 .ndo_open = hdd_open,
3117 .ndo_stop = hdd_stop,
3118 .ndo_uninit = hdd_uninit,
3119 .ndo_start_xmit = hdd_hard_start_xmit,
3120 .ndo_tx_timeout = hdd_tx_timeout,
3121 .ndo_get_stats = hdd_stats,
3122 .ndo_do_ioctl = hdd_ioctl,
3123 .ndo_set_mac_address = hdd_set_mac_address,
3124 .ndo_select_queue = hdd_select_queue,
3125#ifdef WLAN_FEATURE_PACKET_FILTERING
3126#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3127 .ndo_set_rx_mode = hdd_set_multicast_list,
3128#else
3129 .ndo_set_multicast_list = hdd_set_multicast_list,
3130#endif //LINUX_VERSION_CODE
3131#endif
3132 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003133 static struct net_device_ops wlan_mon_drv_ops = {
3134 .ndo_open = hdd_mon_open,
3135 .ndo_stop = hdd_stop,
3136 .ndo_uninit = hdd_uninit,
3137 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3138 .ndo_tx_timeout = hdd_tx_timeout,
3139 .ndo_get_stats = hdd_stats,
3140 .ndo_do_ioctl = hdd_ioctl,
3141 .ndo_set_mac_address = hdd_set_mac_address,
3142 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003143
3144#endif
3145
3146void hdd_set_station_ops( struct net_device *pWlanDev )
3147{
3148#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3149 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3150 pWlanDev->netdev_ops = &wlan_drv_ops;
3151#else
3152 pWlanDev->open = hdd_open;
3153 pWlanDev->stop = hdd_stop;
3154 pWlanDev->uninit = hdd_uninit;
3155 pWlanDev->hard_start_xmit = NULL;
3156 pWlanDev->tx_timeout = hdd_tx_timeout;
3157 pWlanDev->get_stats = hdd_stats;
3158 pWlanDev->do_ioctl = hdd_ioctl;
3159 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3160 pWlanDev->set_mac_address = hdd_set_mac_address;
3161#endif
3162}
3163
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003164static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003165{
3166 struct net_device *pWlanDev = NULL;
3167 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003168 /*
3169 * cfg80211 initialization and registration....
3170 */
3171 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3172
Jeff Johnson295189b2012-06-20 16:38:30 -07003173 if(pWlanDev != NULL)
3174 {
3175
3176 //Save the pointer to the net_device in the HDD adapter
3177 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3178
Jeff Johnson295189b2012-06-20 16:38:30 -07003179 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3180
3181 pAdapter->dev = pWlanDev;
3182 pAdapter->pHddCtx = pHddCtx;
3183 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3184
3185 init_completion(&pAdapter->session_open_comp_var);
3186 init_completion(&pAdapter->session_close_comp_var);
3187 init_completion(&pAdapter->disconnect_comp_var);
3188 init_completion(&pAdapter->linkup_event_var);
3189 init_completion(&pAdapter->cancel_rem_on_chan_var);
3190 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003191#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3192 init_completion(&pAdapter->offchannel_tx_event);
3193#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003194 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003195#ifdef FEATURE_WLAN_TDLS
3196 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003197 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003198 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303199 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003200#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003201 init_completion(&pHddCtx->mc_sus_event_var);
3202 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303203 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003204 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003205
Jeff Johnson295189b2012-06-20 16:38:30 -07003206 pAdapter->isLinkUpSvcNeeded = FALSE;
3207 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3208 //Init the net_device structure
3209 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3210
3211 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3212 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3213 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3214 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3215
3216 hdd_set_station_ops( pAdapter->dev );
3217
3218 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003219 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3220 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3221 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003222 /* set pWlanDev's parent to underlying device */
3223 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3224 }
3225
3226 return pAdapter;
3227}
3228
3229VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3230{
3231 struct net_device *pWlanDev = pAdapter->dev;
3232 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3233 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3234 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3235
3236 if( rtnl_lock_held )
3237 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003238 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003239 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3240 {
3241 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3242 return VOS_STATUS_E_FAILURE;
3243 }
3244 }
3245 if (register_netdevice(pWlanDev))
3246 {
3247 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3248 return VOS_STATUS_E_FAILURE;
3249 }
3250 }
3251 else
3252 {
3253 if(register_netdev(pWlanDev))
3254 {
3255 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3256 return VOS_STATUS_E_FAILURE;
3257 }
3258 }
3259 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3260
3261 return VOS_STATUS_SUCCESS;
3262}
3263
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003264static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003265{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003266 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003267
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003268 if (NULL == pAdapter)
3269 {
3270 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3271 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003272 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003273
3274 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3275 {
3276 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3277 return eHAL_STATUS_NOT_INITIALIZED;
3278 }
3279
3280 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3281
3282 /* need to make sure all of our scheduled work has completed.
3283 * This callback is called from MC thread context, so it is safe to
3284 * to call below flush workqueue API from here.
3285 */
3286 flush_scheduled_work();
3287
3288 /* We can be blocked while waiting for scheduled work to be
3289 * flushed, and the adapter structure can potentially be freed, in
3290 * which case the magic will have been reset. So make sure the
3291 * magic is still good, and hence the adapter structure is still
3292 * valid, before signaling completion */
3293 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3294 {
3295 complete(&pAdapter->session_close_comp_var);
3296 }
3297
Jeff Johnson295189b2012-06-20 16:38:30 -07003298 return eHAL_STATUS_SUCCESS;
3299}
3300
3301VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3302{
3303 struct net_device *pWlanDev = pAdapter->dev;
3304 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3305 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3306 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3307 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3308 int rc = 0;
3309
3310 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003311 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003312 //Open a SME session for future operation
3313 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003314 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003315 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3316 {
3317 hddLog(VOS_TRACE_LEVEL_FATAL,
3318 "sme_OpenSession() failed with status code %08d [x%08lx]",
3319 halStatus, halStatus );
3320 status = VOS_STATUS_E_FAILURE;
3321 goto error_sme_open;
3322 }
3323
3324 //Block on a completion variable. Can't wait forever though.
3325 rc = wait_for_completion_interruptible_timeout(
3326 &pAdapter->session_open_comp_var,
3327 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3328 if (!rc)
3329 {
3330 hddLog(VOS_TRACE_LEVEL_FATAL,
3331 "Session is not opened within timeout period code %08d", rc );
3332 status = VOS_STATUS_E_FAILURE;
3333 goto error_sme_open;
3334 }
3335
3336 // Register wireless extensions
3337 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3338 {
3339 hddLog(VOS_TRACE_LEVEL_FATAL,
3340 "hdd_register_wext() failed with status code %08d [x%08lx]",
3341 halStatus, halStatus );
3342 status = VOS_STATUS_E_FAILURE;
3343 goto error_register_wext;
3344 }
3345 //Safe to register the hard_start_xmit function again
3346#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3347 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3348#else
3349 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3350#endif
3351
3352 //Set the Connection State to Not Connected
3353 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3354
3355 //Set the default operation channel
3356 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3357
3358 /* Make the default Auth Type as OPEN*/
3359 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3360
3361 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3362 {
3363 hddLog(VOS_TRACE_LEVEL_FATAL,
3364 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3365 status, status );
3366 goto error_init_txrx;
3367 }
3368
3369 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3370
3371 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3372 {
3373 hddLog(VOS_TRACE_LEVEL_FATAL,
3374 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3375 status, status );
3376 goto error_wmm_init;
3377 }
3378
3379 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3380
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003381#ifdef FEATURE_WLAN_TDLS
3382 if(0 != wlan_hdd_tdls_init(pAdapter))
3383 {
3384 status = VOS_STATUS_E_FAILURE;
3385 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3386 goto error_tdls_init;
3387 }
3388 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3389#endif
3390
Jeff Johnson295189b2012-06-20 16:38:30 -07003391 return VOS_STATUS_SUCCESS;
3392
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003393#ifdef FEATURE_WLAN_TDLS
3394error_tdls_init:
3395 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3396 hdd_wmm_adapter_close(pAdapter);
3397#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003398error_wmm_init:
3399 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3400 hdd_deinit_tx_rx(pAdapter);
3401error_init_txrx:
3402 hdd_UnregisterWext(pWlanDev);
3403error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003404 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003405 {
3406 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003407 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003408 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003409 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003410 {
3411 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003412 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003413 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003414 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003415 }
3416}
3417error_sme_open:
3418 return status;
3419}
3420
Jeff Johnson295189b2012-06-20 16:38:30 -07003421void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3422{
3423 hdd_cfg80211_state_t *cfgState;
3424
3425 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3426
3427 if( NULL != cfgState->buf )
3428 {
3429 int rc;
3430 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3431 rc = wait_for_completion_interruptible_timeout(
3432 &pAdapter->tx_action_cnf_event,
3433 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3434 if(!rc)
3435 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003436 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003437 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3438 }
3439 }
3440 return;
3441}
Jeff Johnson295189b2012-06-20 16:38:30 -07003442
3443void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3444{
3445 ENTER();
3446 switch ( pAdapter->device_mode )
3447 {
3448 case WLAN_HDD_INFRA_STATION:
3449 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003450 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003451 {
3452 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3453 {
3454 hdd_deinit_tx_rx( pAdapter );
3455 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3456 }
3457
3458 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3459 {
3460 hdd_wmm_adapter_close( pAdapter );
3461 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3462 }
3463
Jeff Johnson295189b2012-06-20 16:38:30 -07003464 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003465#ifdef FEATURE_WLAN_TDLS
3466 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3467 {
3468 wlan_hdd_tdls_exit(pAdapter);
3469 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3470 }
3471#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003472
3473 break;
3474 }
3475
3476 case WLAN_HDD_SOFTAP:
3477 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003478 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003479 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003480
3481 hdd_unregister_hostapd(pAdapter);
3482 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003483 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003484 break;
3485 }
3486
3487 case WLAN_HDD_MONITOR:
3488 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003489 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003490 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3491 {
3492 hdd_deinit_tx_rx( pAdapter );
3493 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3494 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003495 if(NULL != pAdapterforTx)
3496 {
3497 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3498 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003499 break;
3500 }
3501
3502
3503 default:
3504 break;
3505 }
3506
3507 EXIT();
3508}
3509
3510void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3511{
3512 struct net_device *pWlanDev = pAdapter->dev;
3513
3514 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3515 if( rtnl_held )
3516 {
3517 unregister_netdevice(pWlanDev);
3518 }
3519 else
3520 {
3521 unregister_netdev(pWlanDev);
3522 }
3523 // note that the pAdapter is no longer valid at this point
3524 // since the memory has been reclaimed
3525 }
3526
3527}
3528
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003529void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3530{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303531 VOS_STATUS status;
3532 hdd_adapter_t *pAdapter = NULL;
3533 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003534
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303535 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003536
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303537 /*loop through all adapters.*/
3538 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003539 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303540 pAdapter = pAdapterNode->pAdapter;
3541 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3542 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003543
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303544 { // we skip this registration for modes other than STA and P2P client modes.
3545 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3546 pAdapterNode = pNext;
3547 continue;
3548 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003549
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303550 //Apply Dynamic DTIM For P2P
3551 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3552 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3553 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3554 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3555 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3556 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3557 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3558 (eConnectionState_Associated ==
3559 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3560 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3561 {
3562 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003563
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303564 powerRequest.uIgnoreDTIM = 1;
3565 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3566
3567 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3568 {
3569 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3570 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3571 }
3572 else
3573 {
3574 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3575 }
3576
3577 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3578 * specified during Enter/Exit BMPS when LCD off*/
3579 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3580 NULL, eANI_BOOLEAN_FALSE);
3581 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3582 NULL, eANI_BOOLEAN_FALSE);
3583
3584 /* switch to the DTIM specified in cfg.ini */
3585 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3586 "Switch to DTIM %d", powerRequest.uListenInterval);
3587 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3588 break;
3589
3590 }
3591
3592 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3593 pAdapterNode = pNext;
3594 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003595}
3596
3597void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3598{
3599 /*Switch back to DTIM 1*/
3600 tSirSetPowerParamsReq powerRequest = { 0 };
3601
3602 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3603 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003604 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003605
3606 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3607 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3608 NULL, eANI_BOOLEAN_FALSE);
3609 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3610 NULL, eANI_BOOLEAN_FALSE);
3611
3612 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3613 "Switch to DTIM%d",powerRequest.uListenInterval);
3614 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3615
3616}
3617
Jeff Johnson295189b2012-06-20 16:38:30 -07003618VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3619{
3620 VOS_STATUS status = VOS_STATUS_SUCCESS;
3621
3622 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3623 {
3624 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3625 }
3626
3627 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3628 {
3629 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3630 }
3631
3632 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3633 {
3634 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3635 }
3636
3637 return status;
3638}
3639
3640VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3641{
3642 hdd_adapter_t *pAdapter = NULL;
3643 eHalStatus halStatus;
3644 VOS_STATUS status = VOS_STATUS_E_INVAL;
3645 v_BOOL_t disableBmps = FALSE;
3646 v_BOOL_t disableImps = FALSE;
3647
3648 switch(session_type)
3649 {
3650 case WLAN_HDD_INFRA_STATION:
3651 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003652 case WLAN_HDD_P2P_CLIENT:
3653 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003654 //Exit BMPS -> Is Sta/P2P Client is already connected
3655 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3656 if((NULL != pAdapter)&&
3657 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3658 {
3659 disableBmps = TRUE;
3660 }
3661
3662 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3663 if((NULL != pAdapter)&&
3664 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3665 {
3666 disableBmps = TRUE;
3667 }
3668
3669 //Exit both Bmps and Imps incase of Go/SAP Mode
3670 if((WLAN_HDD_SOFTAP == session_type) ||
3671 (WLAN_HDD_P2P_GO == session_type))
3672 {
3673 disableBmps = TRUE;
3674 disableImps = TRUE;
3675 }
3676
3677 if(TRUE == disableImps)
3678 {
3679 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3680 {
3681 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3682 }
3683 }
3684
3685 if(TRUE == disableBmps)
3686 {
3687 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3688 {
3689 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3690
3691 if(eHAL_STATUS_SUCCESS != halStatus)
3692 {
3693 status = VOS_STATUS_E_FAILURE;
3694 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3695 VOS_ASSERT(0);
3696 return status;
3697 }
3698 }
3699
3700 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3701 {
3702 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3703
3704 if(eHAL_STATUS_SUCCESS != halStatus)
3705 {
3706 status = VOS_STATUS_E_FAILURE;
3707 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3708 VOS_ASSERT(0);
3709 return status;
3710 }
3711 }
3712 }
3713
3714 if((TRUE == disableBmps) ||
3715 (TRUE == disableImps))
3716 {
3717 /* Now, get the chip into Full Power now */
3718 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3719 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3720 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3721
3722 if(halStatus != eHAL_STATUS_SUCCESS)
3723 {
3724 if(halStatus == eHAL_STATUS_PMC_PENDING)
3725 {
3726 //Block on a completion variable. Can't wait forever though
3727 wait_for_completion_interruptible_timeout(
3728 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3729 }
3730 else
3731 {
3732 status = VOS_STATUS_E_FAILURE;
3733 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3734 VOS_ASSERT(0);
3735 return status;
3736 }
3737 }
3738
3739 status = VOS_STATUS_SUCCESS;
3740 }
3741
3742 break;
3743 }
3744 return status;
3745}
3746
3747hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003748 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003749 tANI_U8 rtnl_held )
3750{
3751 hdd_adapter_t *pAdapter = NULL;
3752 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3753 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3754 VOS_STATUS exitbmpsStatus;
3755
3756 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3757
3758 //Disable BMPS incase of Concurrency
3759 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3760
3761 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3762 {
3763 //Fail to Exit BMPS
3764 VOS_ASSERT(0);
3765 return NULL;
3766 }
3767
3768 switch(session_type)
3769 {
3770 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003771 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003772 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003773 {
3774 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3775
3776 if( NULL == pAdapter )
3777 return NULL;
3778
Jeff Johnsone7245742012-09-05 17:12:55 -07003779 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3780 NL80211_IFTYPE_P2P_CLIENT:
3781 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003782
Jeff Johnson295189b2012-06-20 16:38:30 -07003783 pAdapter->device_mode = session_type;
3784
3785 status = hdd_init_station_mode( pAdapter );
3786 if( VOS_STATUS_SUCCESS != status )
3787 goto err_free_netdev;
3788
3789 status = hdd_register_interface( pAdapter, rtnl_held );
3790 if( VOS_STATUS_SUCCESS != status )
3791 {
3792 hdd_deinit_adapter(pHddCtx, pAdapter);
3793 goto err_free_netdev;
3794 }
3795 //Stop the Interface TX queue.
3796 netif_tx_disable(pAdapter->dev);
3797 //netif_tx_disable(pWlanDev);
3798 netif_carrier_off(pAdapter->dev);
3799
3800 break;
3801 }
3802
Jeff Johnson295189b2012-06-20 16:38:30 -07003803 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003804 case WLAN_HDD_SOFTAP:
3805 {
3806 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3807 if( NULL == pAdapter )
3808 return NULL;
3809
Jeff Johnson295189b2012-06-20 16:38:30 -07003810 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3811 NL80211_IFTYPE_AP:
3812 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003813 pAdapter->device_mode = session_type;
3814
3815 status = hdd_init_ap_mode(pAdapter);
3816 if( VOS_STATUS_SUCCESS != status )
3817 goto err_free_netdev;
3818
3819 status = hdd_register_hostapd( pAdapter, rtnl_held );
3820 if( VOS_STATUS_SUCCESS != status )
3821 {
3822 hdd_deinit_adapter(pHddCtx, pAdapter);
3823 goto err_free_netdev;
3824 }
3825
3826 netif_tx_disable(pAdapter->dev);
3827 netif_carrier_off(pAdapter->dev);
3828
3829 hdd_set_conparam( 1 );
3830 break;
3831 }
3832 case WLAN_HDD_MONITOR:
3833 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003834 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3835 if( NULL == pAdapter )
3836 return NULL;
3837
3838 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3839 pAdapter->device_mode = session_type;
3840 status = hdd_register_interface( pAdapter, rtnl_held );
3841#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3842 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3843#else
3844 pAdapter->dev->open = hdd_mon_open;
3845 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3846#endif
3847 hdd_init_tx_rx( pAdapter );
3848 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3849 //Set adapter to be used for data tx. It will use either GO or softap.
3850 pAdapter->sessionCtx.monitor.pAdapterForTx =
3851 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003852 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3853 {
3854 pAdapter->sessionCtx.monitor.pAdapterForTx =
3855 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3856 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003857 /* This workqueue will be used to transmit management packet over
3858 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003859 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3860 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3861 return NULL;
3862 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003863
Jeff Johnson295189b2012-06-20 16:38:30 -07003864 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3865 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003866 }
3867 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003868 case WLAN_HDD_FTM:
3869 {
3870 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3871
3872 if( NULL == pAdapter )
3873 return NULL;
3874 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3875 * message while loading driver in FTM mode. */
3876 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3877 pAdapter->device_mode = session_type;
3878 status = hdd_register_interface( pAdapter, rtnl_held );
3879 }
3880 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003881 default:
3882 {
3883 VOS_ASSERT(0);
3884 return NULL;
3885 }
3886 }
3887
3888
3889 if( VOS_STATUS_SUCCESS == status )
3890 {
3891 //Add it to the hdd's session list.
3892 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3893 if( NULL == pHddAdapterNode )
3894 {
3895 status = VOS_STATUS_E_NOMEM;
3896 }
3897 else
3898 {
3899 pHddAdapterNode->pAdapter = pAdapter;
3900 status = hdd_add_adapter_back ( pHddCtx,
3901 pHddAdapterNode );
3902 }
3903 }
3904
3905 if( VOS_STATUS_SUCCESS != status )
3906 {
3907 if( NULL != pAdapter )
3908 {
3909 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3910 pAdapter = NULL;
3911 }
3912 if( NULL != pHddAdapterNode )
3913 {
3914 vos_mem_free( pHddAdapterNode );
3915 }
3916
3917 goto resume_bmps;
3918 }
3919
3920 if(VOS_STATUS_SUCCESS == status)
3921 {
3922 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3923
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003924 //Initialize the WoWL service
3925 if(!hdd_init_wowl(pAdapter))
3926 {
3927 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3928 goto err_free_netdev;
3929 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003930 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003931 return pAdapter;
3932
3933err_free_netdev:
3934 free_netdev(pAdapter->dev);
3935 wlan_hdd_release_intf_addr( pHddCtx,
3936 pAdapter->macAddressCurrent.bytes );
3937
3938resume_bmps:
3939 //If bmps disabled enable it
3940 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3941 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303942 if (pHddCtx->hdd_wlan_suspended)
3943 {
3944 hdd_set_pwrparams(pHddCtx);
3945 }
3946 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003947 }
3948 return NULL;
3949}
3950
3951VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3952 tANI_U8 rtnl_held )
3953{
3954 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3955 VOS_STATUS status;
3956
3957 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3958 if( VOS_STATUS_SUCCESS != status )
3959 return status;
3960
3961 while ( pCurrent->pAdapter != pAdapter )
3962 {
3963 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3964 if( VOS_STATUS_SUCCESS != status )
3965 break;
3966
3967 pCurrent = pNext;
3968 }
3969 pAdapterNode = pCurrent;
3970 if( VOS_STATUS_SUCCESS == status )
3971 {
3972 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3973 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3974 hdd_remove_adapter( pHddCtx, pAdapterNode );
3975 vos_mem_free( pAdapterNode );
3976
Jeff Johnson295189b2012-06-20 16:38:30 -07003977
3978 /* If there is a single session of STA/P2P client, re-enable BMPS */
3979 if ((!vos_concurrent_sessions_running()) &&
3980 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3981 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3982 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303983 if (pHddCtx->hdd_wlan_suspended)
3984 {
3985 hdd_set_pwrparams(pHddCtx);
3986 }
3987 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003988 }
3989
3990 return VOS_STATUS_SUCCESS;
3991 }
3992
3993 return VOS_STATUS_E_FAILURE;
3994}
3995
3996VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3997{
3998 hdd_adapter_list_node_t *pHddAdapterNode;
3999 VOS_STATUS status;
4000
4001 ENTER();
4002
4003 do
4004 {
4005 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
4006 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
4007 {
4008 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
4009 vos_mem_free( pHddAdapterNode );
4010 }
4011 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
4012
4013 EXIT();
4014
4015 return VOS_STATUS_SUCCESS;
4016}
4017
4018void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
4019{
4020 v_U8_t addIE[1] = {0};
4021
4022 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4023 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
4024 eANI_BOOLEAN_FALSE) )
4025 {
4026 hddLog(LOGE,
4027 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
4028 }
4029
4030 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4031 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
4032 eANI_BOOLEAN_FALSE) )
4033 {
4034 hddLog(LOGE,
4035 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
4036 }
4037
4038 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4039 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
4040 eANI_BOOLEAN_FALSE) )
4041 {
4042 hddLog(LOGE,
4043 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
4044 }
4045}
4046
4047VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4048{
4049 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4050 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4051 union iwreq_data wrqu;
4052
4053 ENTER();
4054
4055 switch(pAdapter->device_mode)
4056 {
4057 case WLAN_HDD_INFRA_STATION:
4058 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004059 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004060 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4061 {
4062 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
4063 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4064 pAdapter->sessionId,
4065 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
4066 else
4067 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4068 pAdapter->sessionId,
4069 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4070 //success implies disconnect command got queued up successfully
4071 if(halStatus == eHAL_STATUS_SUCCESS)
4072 {
4073 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
4074 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4075 }
4076 memset(&wrqu, '\0', sizeof(wrqu));
4077 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4078 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4079 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
4080 }
4081 else
4082 {
4083 hdd_abort_mac_scan(pHddCtx);
4084 }
4085
4086 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
4087 {
4088 INIT_COMPLETION(pAdapter->session_close_comp_var);
4089 if (eHAL_STATUS_SUCCESS ==
4090 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
4091 hdd_smeCloseSessionCallback, pAdapter))
4092 {
4093 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004094 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004095 &pAdapter->session_close_comp_var,
4096 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4097 }
4098 }
4099
4100 break;
4101
4102 case WLAN_HDD_SOFTAP:
4103 case WLAN_HDD_P2P_GO:
4104 //Any softap specific cleanup here...
4105 mutex_lock(&pHddCtx->sap_lock);
4106 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4107 {
4108 VOS_STATUS status;
4109 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4110
4111 //Stop Bss.
4112 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4113 if (VOS_IS_STATUS_SUCCESS(status))
4114 {
4115 hdd_hostapd_state_t *pHostapdState =
4116 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4117
4118 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4119
4120 if (!VOS_IS_STATUS_SUCCESS(status))
4121 {
4122 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004123 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004124 }
4125 }
4126 else
4127 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004128 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004129 }
4130 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4131
4132 if (eHAL_STATUS_FAILURE ==
4133 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4134 0, NULL, eANI_BOOLEAN_FALSE))
4135 {
4136 hddLog(LOGE,
4137 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004138 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004139 }
4140
4141 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4142 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4143 eANI_BOOLEAN_FALSE) )
4144 {
4145 hddLog(LOGE,
4146 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4147 }
4148
4149 // Reset WNI_CFG_PROBE_RSP Flags
4150 wlan_hdd_reset_prob_rspies(pAdapter);
4151 kfree(pAdapter->sessionCtx.ap.beacon);
4152 pAdapter->sessionCtx.ap.beacon = NULL;
4153 }
4154 mutex_unlock(&pHddCtx->sap_lock);
4155 break;
4156 case WLAN_HDD_MONITOR:
4157 break;
4158 default:
4159 break;
4160 }
4161
4162 EXIT();
4163 return VOS_STATUS_SUCCESS;
4164}
4165
4166VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4167{
4168 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4169 VOS_STATUS status;
4170 hdd_adapter_t *pAdapter;
4171
4172 ENTER();
4173
4174 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4175
4176 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4177 {
4178 pAdapter = pAdapterNode->pAdapter;
4179 netif_tx_disable(pAdapter->dev);
4180 netif_carrier_off(pAdapter->dev);
4181
4182 hdd_stop_adapter( pHddCtx, pAdapter );
4183
4184 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4185 pAdapterNode = pNext;
4186 }
4187
4188 EXIT();
4189
4190 return VOS_STATUS_SUCCESS;
4191}
4192
4193VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4194{
4195 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4196 VOS_STATUS status;
4197 hdd_adapter_t *pAdapter;
4198
4199 ENTER();
4200
4201 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4202
4203 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4204 {
4205 pAdapter = pAdapterNode->pAdapter;
4206 netif_tx_disable(pAdapter->dev);
4207 netif_carrier_off(pAdapter->dev);
4208
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004209 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
4210
Jeff Johnson295189b2012-06-20 16:38:30 -07004211 hdd_deinit_tx_rx(pAdapter);
4212 hdd_wmm_adapter_close(pAdapter);
4213
4214 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4215 pAdapterNode = pNext;
4216 }
4217
4218 EXIT();
4219
4220 return VOS_STATUS_SUCCESS;
4221}
4222
4223VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4224{
4225 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4226 VOS_STATUS status;
4227 hdd_adapter_t *pAdapter;
4228 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304229 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004230
4231 ENTER();
4232
4233 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4234
4235 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4236 {
4237 pAdapter = pAdapterNode->pAdapter;
4238
4239 switch(pAdapter->device_mode)
4240 {
4241 case WLAN_HDD_INFRA_STATION:
4242 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004243 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304244
4245 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4246
Jeff Johnson295189b2012-06-20 16:38:30 -07004247 hdd_init_station_mode(pAdapter);
4248 /* Open the gates for HDD to receive Wext commands */
4249 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004250 pHddCtx->scan_info.mScanPending = FALSE;
4251 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004252
4253 //Trigger the initial scan
4254 hdd_wlan_initial_scan(pAdapter);
4255
4256 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304257 if (eConnectionState_Associated == connState ||
4258 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004259 {
4260 union iwreq_data wrqu;
4261 memset(&wrqu, '\0', sizeof(wrqu));
4262 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4263 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4264 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004265 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004266
Jeff Johnson295189b2012-06-20 16:38:30 -07004267 /* indicate disconnected event to nl80211 */
4268 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4269 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004270 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304271 else if (eConnectionState_Connecting == connState)
4272 {
4273 /*
4274 * Indicate connect failure to supplicant if we were in the
4275 * process of connecting
4276 */
4277 cfg80211_connect_result(pAdapter->dev, NULL,
4278 NULL, 0, NULL, 0,
4279 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4280 GFP_KERNEL);
4281 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004282 break;
4283
4284 case WLAN_HDD_SOFTAP:
4285 /* softAP can handle SSR */
4286 break;
4287
4288 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004289 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4290 __func__);
4291 /* event supplicant to restart */
4292 cfg80211_del_sta(pAdapter->dev,
4293 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004294 break;
4295
4296 case WLAN_HDD_MONITOR:
4297 /* monitor interface start */
4298 break;
4299 default:
4300 break;
4301 }
4302
4303 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4304 pAdapterNode = pNext;
4305 }
4306
4307 EXIT();
4308
4309 return VOS_STATUS_SUCCESS;
4310}
4311
4312VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4313{
4314 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4315 hdd_adapter_t *pAdapter;
4316 VOS_STATUS status;
4317 v_U32_t roamId;
4318
4319 ENTER();
4320
4321 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4322
4323 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4324 {
4325 pAdapter = pAdapterNode->pAdapter;
4326
4327 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4328 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4329 {
4330 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4331 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4332
4333 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4334 init_completion(&pAdapter->disconnect_comp_var);
4335 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4336 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4337
4338 wait_for_completion_interruptible_timeout(
4339 &pAdapter->disconnect_comp_var,
4340 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4341
4342 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4343 pHddCtx->isAmpAllowed = VOS_FALSE;
4344 sme_RoamConnect(pHddCtx->hHal,
4345 pAdapter->sessionId, &(pWextState->roamProfile),
4346 &roamId);
4347 }
4348
4349 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4350 pAdapterNode = pNext;
4351 }
4352
4353 EXIT();
4354
4355 return VOS_STATUS_SUCCESS;
4356}
4357
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004358void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4359{
4360 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4361 VOS_STATUS status;
4362 hdd_adapter_t *pAdapter;
4363 hdd_station_ctx_t *pHddStaCtx;
4364 hdd_ap_ctx_t *pHddApCtx;
4365 hdd_hostapd_state_t * pHostapdState;
4366 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4367 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4368 const char *p2pMode = "DEV";
4369 const char *ccMode = "Standalone";
4370 int n;
4371
4372 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4373 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4374 {
4375 pAdapter = pAdapterNode->pAdapter;
4376 switch (pAdapter->device_mode) {
4377 case WLAN_HDD_INFRA_STATION:
4378 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4379 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4380 staChannel = pHddStaCtx->conn_info.operationChannel;
4381 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4382 }
4383 break;
4384 case WLAN_HDD_P2P_CLIENT:
4385 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4386 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4387 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4388 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4389 p2pMode = "CLI";
4390 }
4391 break;
4392 case WLAN_HDD_P2P_GO:
4393 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4394 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4395 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4396 p2pChannel = pHddApCtx->operatingChannel;
4397 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4398 }
4399 p2pMode = "GO";
4400 break;
4401 case WLAN_HDD_SOFTAP:
4402 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4403 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4404 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4405 apChannel = pHddApCtx->operatingChannel;
4406 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4407 }
4408 break;
4409 default:
4410 break;
4411 }
4412 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4413 pAdapterNode = pNext;
4414 }
4415 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4416 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4417 }
4418 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4419 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4420 if (p2pChannel > 0) {
4421 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4422 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4423 }
4424 if (apChannel > 0) {
4425 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4426 apChannel, MAC_ADDR_ARRAY(apBssid));
4427 }
4428
4429 if (p2pChannel > 0 && apChannel > 0) {
4430 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4431 }
4432}
4433
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004434bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004435{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004436 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004437}
4438
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004439/* Once SSR is disabled then it cannot be set. */
4440void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004441{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004442 if (HDD_SSR_DISABLED == isSsrRequired)
4443 return;
4444
Jeff Johnson295189b2012-06-20 16:38:30 -07004445 isSsrRequired = value;
4446}
4447
4448VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4449 hdd_adapter_list_node_t** ppAdapterNode)
4450{
4451 VOS_STATUS status;
4452 spin_lock(&pHddCtx->hddAdapters.lock);
4453 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4454 (hdd_list_node_t**) ppAdapterNode );
4455 spin_unlock(&pHddCtx->hddAdapters.lock);
4456 return status;
4457}
4458
4459VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4460 hdd_adapter_list_node_t* pAdapterNode,
4461 hdd_adapter_list_node_t** pNextAdapterNode)
4462{
4463 VOS_STATUS status;
4464 spin_lock(&pHddCtx->hddAdapters.lock);
4465 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4466 (hdd_list_node_t*) pAdapterNode,
4467 (hdd_list_node_t**)pNextAdapterNode );
4468
4469 spin_unlock(&pHddCtx->hddAdapters.lock);
4470 return status;
4471}
4472
4473VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4474 hdd_adapter_list_node_t* pAdapterNode)
4475{
4476 VOS_STATUS status;
4477 spin_lock(&pHddCtx->hddAdapters.lock);
4478 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4479 &pAdapterNode->node );
4480 spin_unlock(&pHddCtx->hddAdapters.lock);
4481 return status;
4482}
4483
4484VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4485 hdd_adapter_list_node_t** ppAdapterNode)
4486{
4487 VOS_STATUS status;
4488 spin_lock(&pHddCtx->hddAdapters.lock);
4489 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4490 (hdd_list_node_t**) ppAdapterNode );
4491 spin_unlock(&pHddCtx->hddAdapters.lock);
4492 return status;
4493}
4494
4495VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4496 hdd_adapter_list_node_t* pAdapterNode)
4497{
4498 VOS_STATUS status;
4499 spin_lock(&pHddCtx->hddAdapters.lock);
4500 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4501 (hdd_list_node_t*) pAdapterNode );
4502 spin_unlock(&pHddCtx->hddAdapters.lock);
4503 return status;
4504}
4505
4506VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4507 hdd_adapter_list_node_t* pAdapterNode)
4508{
4509 VOS_STATUS status;
4510 spin_lock(&pHddCtx->hddAdapters.lock);
4511 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4512 (hdd_list_node_t*) pAdapterNode );
4513 spin_unlock(&pHddCtx->hddAdapters.lock);
4514 return status;
4515}
4516
4517hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4518 tSirMacAddr macAddr )
4519{
4520 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4521 hdd_adapter_t *pAdapter;
4522 VOS_STATUS status;
4523
4524 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4525
4526 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4527 {
4528 pAdapter = pAdapterNode->pAdapter;
4529
4530 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4531 macAddr, sizeof(tSirMacAddr) ) )
4532 {
4533 return pAdapter;
4534 }
4535 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4536 pAdapterNode = pNext;
4537 }
4538
4539 return NULL;
4540
4541}
4542
4543hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4544{
4545 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4546 hdd_adapter_t *pAdapter;
4547 VOS_STATUS status;
4548
4549 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4550
4551 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4552 {
4553 pAdapter = pAdapterNode->pAdapter;
4554
4555 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4556 IFNAMSIZ ) )
4557 {
4558 return pAdapter;
4559 }
4560 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4561 pAdapterNode = pNext;
4562 }
4563
4564 return NULL;
4565
4566}
4567
4568hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4569{
4570 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4571 hdd_adapter_t *pAdapter;
4572 VOS_STATUS status;
4573
4574 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4575
4576 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4577 {
4578 pAdapter = pAdapterNode->pAdapter;
4579
4580 if( pAdapter && (mode == pAdapter->device_mode) )
4581 {
4582 return pAdapter;
4583 }
4584 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4585 pAdapterNode = pNext;
4586 }
4587
4588 return NULL;
4589
4590}
4591
4592//Remove this function later
4593hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4594{
4595 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4596 hdd_adapter_t *pAdapter;
4597 VOS_STATUS status;
4598
4599 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4600
4601 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4602 {
4603 pAdapter = pAdapterNode->pAdapter;
4604
4605 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4606 {
4607 return pAdapter;
4608 }
4609
4610 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4611 pAdapterNode = pNext;
4612 }
4613
4614 return NULL;
4615
4616}
4617
Jeff Johnson295189b2012-06-20 16:38:30 -07004618/**---------------------------------------------------------------------------
4619
4620 \brief hdd_set_monitor_tx_adapter() -
4621
4622 This API initializes the adapter to be used while transmitting on monitor
4623 adapter.
4624
4625 \param - pHddCtx - Pointer to the HDD context.
4626 pAdapter - Adapter that will used for TX. This can be NULL.
4627 \return - None.
4628 --------------------------------------------------------------------------*/
4629void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4630{
4631 hdd_adapter_t *pMonAdapter;
4632
4633 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4634
4635 if( NULL != pMonAdapter )
4636 {
4637 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4638 }
4639}
Jeff Johnson295189b2012-06-20 16:38:30 -07004640/**---------------------------------------------------------------------------
4641
4642 \brief hdd_select_queue() -
4643
4644 This API returns the operating channel of the requested device mode
4645
4646 \param - pHddCtx - Pointer to the HDD context.
4647 - mode - Device mode for which operating channel is required
4648 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4649 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4650 \return - channel number. "0" id the requested device is not found OR it is not connected.
4651 --------------------------------------------------------------------------*/
4652v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4653{
4654 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4655 VOS_STATUS status;
4656 hdd_adapter_t *pAdapter;
4657 v_U8_t operatingChannel = 0;
4658
4659 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4660
4661 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4662 {
4663 pAdapter = pAdapterNode->pAdapter;
4664
4665 if( mode == pAdapter->device_mode )
4666 {
4667 switch(pAdapter->device_mode)
4668 {
4669 case WLAN_HDD_INFRA_STATION:
4670 case WLAN_HDD_P2P_CLIENT:
4671 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4672 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4673 break;
4674 case WLAN_HDD_SOFTAP:
4675 case WLAN_HDD_P2P_GO:
4676 /*softap connection info */
4677 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4678 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4679 break;
4680 default:
4681 break;
4682 }
4683
4684 break; //Found the device of interest. break the loop
4685 }
4686
4687 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4688 pAdapterNode = pNext;
4689 }
4690 return operatingChannel;
4691}
4692
4693#ifdef WLAN_FEATURE_PACKET_FILTERING
4694/**---------------------------------------------------------------------------
4695
4696 \brief hdd_set_multicast_list() -
4697
4698 This used to set the multicast address list.
4699
4700 \param - dev - Pointer to the WLAN device.
4701 - skb - Pointer to OS packet (sk_buff).
4702 \return - success/fail
4703
4704 --------------------------------------------------------------------------*/
4705static void hdd_set_multicast_list(struct net_device *dev)
4706{
4707 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004708 int mc_count;
4709 int i = 0;
4710 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304711
4712 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004713 {
4714 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304715 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004716 return;
4717 }
4718
4719 if (dev->flags & IFF_ALLMULTI)
4720 {
4721 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004722 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304723 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004724 }
4725 else
4726 {
4727 mc_count = netdev_mc_count(dev);
4728 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004729 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004730 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4731 {
4732 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004733 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304734 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004735 return;
4736 }
4737
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304738 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004739
4740 netdev_for_each_mc_addr(ha, dev) {
4741 if (i == mc_count)
4742 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304743 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4744 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4745 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004746 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304747 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004748 i++;
4749 }
4750 }
4751 return;
4752}
4753#endif
4754
4755/**---------------------------------------------------------------------------
4756
4757 \brief hdd_select_queue() -
4758
4759 This function is registered with the Linux OS for network
4760 core to decide which queue to use first.
4761
4762 \param - dev - Pointer to the WLAN device.
4763 - skb - Pointer to OS packet (sk_buff).
4764 \return - ac, Queue Index/access category corresponding to UP in IP header
4765
4766 --------------------------------------------------------------------------*/
4767v_U16_t hdd_select_queue(struct net_device *dev,
4768 struct sk_buff *skb)
4769{
4770 return hdd_wmm_select_queue(dev, skb);
4771}
4772
4773
4774/**---------------------------------------------------------------------------
4775
4776 \brief hdd_wlan_initial_scan() -
4777
4778 This function triggers the initial scan
4779
4780 \param - pAdapter - Pointer to the HDD adapter.
4781
4782 --------------------------------------------------------------------------*/
4783void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4784{
4785 tCsrScanRequest scanReq;
4786 tCsrChannelInfo channelInfo;
4787 eHalStatus halStatus;
4788 unsigned long scanId;
4789 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4790
4791 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4792 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4793 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4794
4795 if(sme_Is11dSupported(pHddCtx->hHal))
4796 {
4797 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4798 if ( HAL_STATUS_SUCCESS( halStatus ) )
4799 {
4800 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4801 if( !scanReq.ChannelInfo.ChannelList )
4802 {
4803 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4804 vos_mem_free(channelInfo.ChannelList);
4805 return;
4806 }
4807 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4808 channelInfo.numOfChannels);
4809 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4810 vos_mem_free(channelInfo.ChannelList);
4811 }
4812
4813 scanReq.scanType = eSIR_PASSIVE_SCAN;
4814 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4815 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4816 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4817 }
4818 else
4819 {
4820 scanReq.scanType = eSIR_ACTIVE_SCAN;
4821 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4822 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4823 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4824 }
4825
4826 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4827 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4828 {
4829 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4830 __func__, halStatus );
4831 }
4832
4833 if(sme_Is11dSupported(pHddCtx->hHal))
4834 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4835}
4836
4837struct fullPowerContext
4838{
4839 struct completion completion;
4840 unsigned int magic;
4841};
4842#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4843
4844/**---------------------------------------------------------------------------
4845
4846 \brief hdd_full_power_callback() - HDD full power callback function
4847
4848 This is the function invoked by SME to inform the result of a full power
4849 request issued by HDD
4850
4851 \param - callbackcontext - Pointer to cookie
4852 \param - status - result of request
4853
4854 \return - None
4855
4856 --------------------------------------------------------------------------*/
4857static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4858{
4859 struct fullPowerContext *pContext = callbackContext;
4860
4861 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304862 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004863
4864 if (NULL == callbackContext)
4865 {
4866 hddLog(VOS_TRACE_LEVEL_ERROR,
4867 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004868 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004869 return;
4870 }
4871
4872 /* there is a race condition that exists between this callback function
4873 and the caller since the caller could time out either before or
4874 while this code is executing. we'll assume the timeout hasn't
4875 occurred, but we'll verify that right before we save our work */
4876
4877 if (POWER_CONTEXT_MAGIC != pContext->magic)
4878 {
4879 /* the caller presumably timed out so there is nothing we can do */
4880 hddLog(VOS_TRACE_LEVEL_WARN,
4881 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004882 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004883 return;
4884 }
4885
4886 /* the race is on. caller could have timed out immediately after
4887 we verified the magic, but if so, caller will wait a short time
4888 for us to notify the caller, so the context will stay valid */
4889 complete(&pContext->completion);
4890}
4891
4892/**---------------------------------------------------------------------------
4893
4894 \brief hdd_wlan_exit() - HDD WLAN exit function
4895
4896 This is the driver exit point (invoked during rmmod)
4897
4898 \param - pHddCtx - Pointer to the HDD Context
4899
4900 \return - None
4901
4902 --------------------------------------------------------------------------*/
4903void hdd_wlan_exit(hdd_context_t *pHddCtx)
4904{
4905 eHalStatus halStatus;
4906 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4907 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304908 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004909 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004910 struct fullPowerContext powerContext;
4911 long lrc;
4912
4913 ENTER();
4914
Jeff Johnson88ba7742013-02-27 14:36:02 -08004915 if (VOS_FTM_MODE != hdd_get_conparam())
4916 {
4917 // Unloading, restart logic is no more required.
4918 wlan_hdd_restart_deinit(pHddCtx);
4919 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004920
Jeff Johnson295189b2012-06-20 16:38:30 -07004921 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004922 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004923 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004924 {
4925 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4926 WLAN_HDD_INFRA_STATION);
4927 if (pAdapter == NULL)
4928 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4929
4930 if (pAdapter != NULL)
4931 {
4932 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4933 hdd_UnregisterWext(pAdapter->dev);
4934 }
4935 }
4936 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004937
Jeff Johnson295189b2012-06-20 16:38:30 -07004938 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004939 {
4940 wlan_hdd_ftm_close(pHddCtx);
4941 goto free_hdd_ctx;
4942 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004943 //Stop the Interface TX queue.
4944 //netif_tx_disable(pWlanDev);
4945 //netif_carrier_off(pWlanDev);
4946
Jeff Johnson295189b2012-06-20 16:38:30 -07004947 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4948 {
4949 pAdapter = hdd_get_adapter(pHddCtx,
4950 WLAN_HDD_SOFTAP);
4951 }
4952 else
4953 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004954 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004955 {
4956 pAdapter = hdd_get_adapter(pHddCtx,
4957 WLAN_HDD_INFRA_STATION);
4958 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004959 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004960 /* DeRegister with platform driver as client for Suspend/Resume */
4961 vosStatus = hddDeregisterPmOps(pHddCtx);
4962 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4963 {
4964 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4965 VOS_ASSERT(0);
4966 }
4967
4968 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4969 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4970 {
4971 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4972 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004973
4974 // Cancel any outstanding scan requests. We are about to close all
4975 // of our adapters, but an adapter structure is what SME passes back
4976 // to our callback function. Hence if there are any outstanding scan
4977 // requests then there is a race condition between when the adapter
4978 // is closed and when the callback is invoked. We try to resolve that
4979 // race condition here by canceling any outstanding scans before we
4980 // close the adapters.
4981 // Note that the scans may be cancelled in an asynchronous manner, so
4982 // ideally there needs to be some kind of synchronization. Rather than
4983 // introduce a new synchronization here, we will utilize the fact that
4984 // we are about to Request Full Power, and since that is synchronized,
4985 // the expectation is that by the time Request Full Power has completed,
4986 // all scans will be cancelled.
4987 hdd_abort_mac_scan( pHddCtx );
4988
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05304989 //Stop the timer if already running
4990 if (VOS_TIMER_STATE_RUNNING ==
4991 vos_timer_getCurrentState(&pHddCtx->hdd_p2p_go_conn_is_in_progress))
4992 {
4993 vos_timer_stop(&pHddCtx->hdd_p2p_go_conn_is_in_progress);
4994 }
4995
4996 // Destroy hdd_p2p_go_conn_is_in_progress timer
4997 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
4998 &pHddCtx->hdd_p2p_go_conn_is_in_progress)))
4999 {
5000 hddLog(VOS_TRACE_LEVEL_ERROR,
5001 "%s: Cannot deallocate p2p connection timer", __func__);
5002 }
5003
Jeff Johnson295189b2012-06-20 16:38:30 -07005004 //Disable IMPS/BMPS as we do not want the device to enter any power
5005 //save mode during shutdown
5006 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5007 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5008 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
5009
5010 //Ensure that device is in full power as we will touch H/W during vos_Stop
5011 init_completion(&powerContext.completion);
5012 powerContext.magic = POWER_CONTEXT_MAGIC;
5013
5014 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
5015 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
5016
5017 if (eHAL_STATUS_SUCCESS != halStatus)
5018 {
5019 if (eHAL_STATUS_PMC_PENDING == halStatus)
5020 {
5021 /* request was sent -- wait for the response */
5022 lrc = wait_for_completion_interruptible_timeout(
5023 &powerContext.completion,
5024 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
5025 /* either we have a response or we timed out
5026 either way, first invalidate our magic */
5027 powerContext.magic = 0;
5028 if (lrc <= 0)
5029 {
5030 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005031 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07005032 /* there is a race condition such that the callback
5033 function could be executing at the same time we are. of
5034 primary concern is if the callback function had already
5035 verified the "magic" but hasn't yet set the completion
5036 variable. Since the completion variable is on our
5037 stack, we'll delay just a bit to make sure the data is
5038 still valid if that is the case */
5039 msleep(50);
5040 }
5041 }
5042 else
5043 {
5044 hddLog(VOS_TRACE_LEVEL_ERROR,
5045 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005046 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07005047 VOS_ASSERT(0);
5048 /* continue -- need to clean up as much as possible */
5049 }
5050 }
5051
Yue Ma0d4891e2013-08-06 17:01:45 -07005052 hdd_debugfs_exit(pHddCtx);
5053
Jeff Johnson295189b2012-06-20 16:38:30 -07005054 // Unregister the Net Device Notifier
5055 unregister_netdevice_notifier(&hdd_netdev_notifier);
5056
Jeff Johnson295189b2012-06-20 16:38:30 -07005057 hdd_stop_all_adapters( pHddCtx );
5058
Jeff Johnson295189b2012-06-20 16:38:30 -07005059#ifdef WLAN_BTAMP_FEATURE
5060 vosStatus = WLANBAP_Stop(pVosContext);
5061 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5062 {
5063 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5064 "%s: Failed to stop BAP",__func__);
5065 }
5066#endif //WLAN_BTAMP_FEATURE
5067
5068 //Stop all the modules
5069 vosStatus = vos_stop( pVosContext );
5070 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5071 {
5072 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5073 "%s: Failed to stop VOSS",__func__);
5074 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5075 }
5076
Jeff Johnson295189b2012-06-20 16:38:30 -07005077 //Assert Deep sleep signal now to put Libra HW in lowest power state
5078 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5079 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5080
5081 //Vote off any PMIC voltage supplies
5082 vos_chipPowerDown(NULL, NULL, NULL);
5083
5084 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
5085
Leo Chang59cdc7e2013-07-10 10:08:21 -07005086
Jeff Johnson295189b2012-06-20 16:38:30 -07005087 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07005088 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005089
5090 //Close the scheduler before calling vos_close to make sure no thread is
5091 // scheduled after the each module close is called i.e after all the data
5092 // structures are freed.
5093 vosStatus = vos_sched_close( pVosContext );
5094 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
5095 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5096 "%s: Failed to close VOSS Scheduler",__func__);
5097 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5098 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005099#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005100#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5101 /* Destroy the wake lock */
5102 wake_lock_destroy(&pHddCtx->rx_wake_lock);
5103#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005104 /* Destroy the wake lock */
5105 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005106#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005107
5108 //Close VOSS
5109 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
5110 vos_close(pVosContext);
5111
Jeff Johnson295189b2012-06-20 16:38:30 -07005112 //Close Watchdog
5113 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5114 vos_watchdog_close(pVosContext);
5115
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305116 //Clean up HDD Nlink Service
5117 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07005118#ifdef WLAN_KD_READY_NOTIFIER
5119 nl_srv_exit(pHddCtx->ptt_pid);
5120#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305121 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005122#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305123
Jeff Johnson295189b2012-06-20 16:38:30 -07005124 /* Cancel the vote for XO Core ON.
5125 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5126 * exited at this point
5127 */
5128 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5129 " when WLAN is turned OFF\n");
5130 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5131 {
5132 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5133 " Not returning failure."
5134 " Power consumed will be high\n");
5135 }
5136
5137 hdd_close_all_adapters( pHddCtx );
5138
5139
5140 //Free up dynamically allocated members inside HDD Adapter
5141 kfree(pHddCtx->cfg_ini);
5142 pHddCtx->cfg_ini= NULL;
5143
5144 /* free the power on lock from platform driver */
5145 if (free_riva_power_on_lock("wlan"))
5146 {
5147 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5148 __func__);
5149 }
5150
Jeff Johnson88ba7742013-02-27 14:36:02 -08005151free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08005152 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005153 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005154 if (hdd_is_ssr_required())
5155 {
5156 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005157 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005158 msleep(5000);
5159 }
5160 hdd_set_ssr_required (VOS_FALSE);
5161}
5162
5163
5164/**---------------------------------------------------------------------------
5165
5166 \brief hdd_update_config_from_nv() - Function to update the contents of
5167 the running configuration with parameters taken from NV storage
5168
5169 \param - pHddCtx - Pointer to the HDD global context
5170
5171 \return - VOS_STATUS_SUCCESS if successful
5172
5173 --------------------------------------------------------------------------*/
5174static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5175{
Jeff Johnson295189b2012-06-20 16:38:30 -07005176 v_BOOL_t itemIsValid = VOS_FALSE;
5177 VOS_STATUS status;
5178 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5179 v_U8_t macLoop;
5180
5181 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5182 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5183 if(status != VOS_STATUS_SUCCESS)
5184 {
5185 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5186 return VOS_STATUS_E_FAILURE;
5187 }
5188
5189 if (itemIsValid == VOS_TRUE)
5190 {
5191 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5192 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5193 VOS_MAX_CONCURRENCY_PERSONA);
5194 if(status != VOS_STATUS_SUCCESS)
5195 {
5196 /* Get MAC from NV fail, not update CFG info
5197 * INI MAC value will be used for MAC setting */
5198 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5199 return VOS_STATUS_E_FAILURE;
5200 }
5201
5202 /* If first MAC is not valid, treat all others are not valid
5203 * Then all MACs will be got from ini file */
5204 if(vos_is_macaddr_zero(&macFromNV[0]))
5205 {
5206 /* MAC address in NV file is not configured yet */
5207 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5208 return VOS_STATUS_E_INVAL;
5209 }
5210
5211 /* Get MAC address from NV, update CFG info */
5212 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5213 {
5214 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5215 {
5216 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5217 /* This MAC is not valid, skip it
5218 * This MAC will be got from ini file */
5219 }
5220 else
5221 {
5222 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5223 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5224 VOS_MAC_ADDR_SIZE);
5225 }
5226 }
5227 }
5228 else
5229 {
5230 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5231 return VOS_STATUS_E_FAILURE;
5232 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005233
Jeff Johnson295189b2012-06-20 16:38:30 -07005234
5235 return VOS_STATUS_SUCCESS;
5236}
5237
5238/**---------------------------------------------------------------------------
5239
5240 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5241
5242 \param - pAdapter - Pointer to the HDD
5243
5244 \return - None
5245
5246 --------------------------------------------------------------------------*/
5247VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5248{
5249 eHalStatus halStatus;
5250 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305251 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005252
Jeff Johnson295189b2012-06-20 16:38:30 -07005253
5254 // Send ready indication to the HDD. This will kick off the MAC
5255 // into a 'running' state and should kick off an initial scan.
5256 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5257 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5258 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305259 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005260 "code %08d [x%08x]",__func__, halStatus, halStatus );
5261 return VOS_STATUS_E_FAILURE;
5262 }
5263
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305264 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005265 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5266 // And RIVA will crash
5267 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5268 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305269 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5270 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5271
5272
Jeff Johnson295189b2012-06-20 16:38:30 -07005273 return VOS_STATUS_SUCCESS;
5274}
5275
Jeff Johnson295189b2012-06-20 16:38:30 -07005276/* wake lock APIs for HDD */
5277void hdd_prevent_suspend(void)
5278{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005279#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005280 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005281#else
5282 wcnss_prevent_suspend();
5283#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005284}
5285
5286void hdd_allow_suspend(void)
5287{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005288#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005289 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005290#else
5291 wcnss_allow_suspend();
5292#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005293}
5294
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005295void hdd_allow_suspend_timeout(v_U32_t timeout)
5296{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005297#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005298 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005299#else
5300 /* Do nothing as there is no API in wcnss for timeout*/
5301#endif
5302}
5303
Jeff Johnson295189b2012-06-20 16:38:30 -07005304/**---------------------------------------------------------------------------
5305
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005306 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5307 information between Host and Riva
5308
5309 This function gets reported version of FW
5310 It also finds the version of Riva headers used to compile the host
5311 It compares the above two and prints a warning if they are different
5312 It gets the SW and HW version string
5313 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5314 indicating the features they support through a bitmap
5315
5316 \param - pHddCtx - Pointer to HDD context
5317
5318 \return - void
5319
5320 --------------------------------------------------------------------------*/
5321
5322void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5323{
5324
5325 tSirVersionType versionCompiled;
5326 tSirVersionType versionReported;
5327 tSirVersionString versionString;
5328 tANI_U8 fwFeatCapsMsgSupported = 0;
5329 VOS_STATUS vstatus;
5330
5331 /* retrieve and display WCNSS version information */
5332 do {
5333
5334 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5335 &versionCompiled);
5336 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5337 {
5338 hddLog(VOS_TRACE_LEVEL_FATAL,
5339 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005340 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005341 break;
5342 }
5343
5344 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5345 &versionReported);
5346 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5347 {
5348 hddLog(VOS_TRACE_LEVEL_FATAL,
5349 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005350 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005351 break;
5352 }
5353
5354 if ((versionCompiled.major != versionReported.major) ||
5355 (versionCompiled.minor != versionReported.minor) ||
5356 (versionCompiled.version != versionReported.version) ||
5357 (versionCompiled.revision != versionReported.revision))
5358 {
5359 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5360 "Host expected %u.%u.%u.%u\n",
5361 WLAN_MODULE_NAME,
5362 (int)versionReported.major,
5363 (int)versionReported.minor,
5364 (int)versionReported.version,
5365 (int)versionReported.revision,
5366 (int)versionCompiled.major,
5367 (int)versionCompiled.minor,
5368 (int)versionCompiled.version,
5369 (int)versionCompiled.revision);
5370 }
5371 else
5372 {
5373 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5374 WLAN_MODULE_NAME,
5375 (int)versionReported.major,
5376 (int)versionReported.minor,
5377 (int)versionReported.version,
5378 (int)versionReported.revision);
5379 }
5380
5381 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5382 versionString,
5383 sizeof(versionString));
5384 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5385 {
5386 hddLog(VOS_TRACE_LEVEL_FATAL,
5387 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005388 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005389 break;
5390 }
5391
5392 pr_info("%s: WCNSS software version %s\n",
5393 WLAN_MODULE_NAME, versionString);
5394
5395 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5396 versionString,
5397 sizeof(versionString));
5398 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5399 {
5400 hddLog(VOS_TRACE_LEVEL_FATAL,
5401 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005402 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005403 break;
5404 }
5405
5406 pr_info("%s: WCNSS hardware version %s\n",
5407 WLAN_MODULE_NAME, versionString);
5408
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005409 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5410 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005411 send the message only if it the riva is 1.1
5412 minor numbers for different riva branches:
5413 0 -> (1.0)Mainline Build
5414 1 -> (1.1)Mainline Build
5415 2->(1.04) Stability Build
5416 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005417 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005418 ((versionReported.minor>=1) && (versionReported.version>=1)))
5419 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5420 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005421
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005422 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005423 {
5424#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5425 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5426 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5427#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07005428 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
5429 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
5430 {
5431 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
5432 }
5433
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005434 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005435 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005436
5437 } while (0);
5438
5439}
5440
5441/**---------------------------------------------------------------------------
5442
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305443 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5444
5445 \param - pHddCtx - Pointer to the hdd context
5446
5447 \return - true if hardware supports 5GHz
5448
5449 --------------------------------------------------------------------------*/
5450static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5451{
5452 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5453 * then hardware support 5Ghz.
5454 */
5455 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5456 {
5457 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5458 return true;
5459 }
5460 else
5461 {
5462 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5463 __func__);
5464 return false;
5465 }
5466}
5467
5468
5469/**---------------------------------------------------------------------------
5470
Jeff Johnson295189b2012-06-20 16:38:30 -07005471 \brief hdd_wlan_startup() - HDD init function
5472
5473 This is the driver startup code executed once a WLAN device has been detected
5474
5475 \param - dev - Pointer to the underlying device
5476
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005477 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005478
5479 --------------------------------------------------------------------------*/
5480
5481int hdd_wlan_startup(struct device *dev )
5482{
5483 VOS_STATUS status;
5484 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005485 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005486 hdd_context_t *pHddCtx = NULL;
5487 v_CONTEXT_t pVosContext= NULL;
5488#ifdef WLAN_BTAMP_FEATURE
5489 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5490 WLANBAP_ConfigType btAmpConfig;
5491 hdd_config_t *pConfig;
5492#endif
5493 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005494 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005495
5496 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005497 /*
5498 * cfg80211: wiphy allocation
5499 */
5500 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5501
5502 if(wiphy == NULL)
5503 {
5504 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005505 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005506 }
5507
5508 pHddCtx = wiphy_priv(wiphy);
5509
Jeff Johnson295189b2012-06-20 16:38:30 -07005510 //Initialize the adapter context to zeros.
5511 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5512
Jeff Johnson295189b2012-06-20 16:38:30 -07005513 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005514 hdd_prevent_suspend();
5515 pHddCtx->isLoadUnloadInProgress = TRUE;
5516
5517 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5518
5519 /*Get vos context here bcoz vos_open requires it*/
5520 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5521
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005522 if(pVosContext == NULL)
5523 {
5524 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5525 goto err_free_hdd_context;
5526 }
5527
Jeff Johnson295189b2012-06-20 16:38:30 -07005528 //Save the Global VOSS context in adapter context for future.
5529 pHddCtx->pvosContext = pVosContext;
5530
5531 //Save the adapter context in global context for future.
5532 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5533
Jeff Johnson295189b2012-06-20 16:38:30 -07005534 pHddCtx->parent_dev = dev;
5535
5536 init_completion(&pHddCtx->full_pwr_comp_var);
5537 init_completion(&pHddCtx->standby_comp_var);
5538 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005539 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005540 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005541
5542 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5543
5544 // Load all config first as TL config is needed during vos_open
5545 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5546 if(pHddCtx->cfg_ini == NULL)
5547 {
5548 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5549 goto err_free_hdd_context;
5550 }
5551
5552 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5553
5554 // Read and parse the qcom_cfg.ini file
5555 status = hdd_parse_config_ini( pHddCtx );
5556 if ( VOS_STATUS_SUCCESS != status )
5557 {
5558 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5559 __func__, WLAN_INI_FILE);
5560 goto err_config;
5561 }
5562
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305563 /* INI has been read, initialise the configuredMcastBcastFilter with
5564 * INI value as this will serve as the default value
5565 */
5566 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5567 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5568 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305569
5570 if (false == hdd_is_5g_supported(pHddCtx))
5571 {
5572 //5Ghz is not supported.
5573 if (1 != pHddCtx->cfg_ini->nBandCapability)
5574 {
5575 hddLog(VOS_TRACE_LEVEL_INFO,
5576 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5577 pHddCtx->cfg_ini->nBandCapability = 1;
5578 }
5579 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005580 /*
5581 * cfg80211: Initialization and registration ...
5582 */
5583 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5584 {
5585 hddLog(VOS_TRACE_LEVEL_FATAL,
5586 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5587 goto err_wiphy_reg;
5588 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005589
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005590 // Update VOS trace levels based upon the cfg.ini
5591 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5592 pHddCtx->cfg_ini->vosTraceEnableBAP);
5593 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5594 pHddCtx->cfg_ini->vosTraceEnableTL);
5595 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5596 pHddCtx->cfg_ini->vosTraceEnableWDI);
5597 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5598 pHddCtx->cfg_ini->vosTraceEnableHDD);
5599 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5600 pHddCtx->cfg_ini->vosTraceEnableSME);
5601 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5602 pHddCtx->cfg_ini->vosTraceEnablePE);
5603 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5604 pHddCtx->cfg_ini->vosTraceEnableWDA);
5605 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5606 pHddCtx->cfg_ini->vosTraceEnableSYS);
5607 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5608 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005609 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5610 pHddCtx->cfg_ini->vosTraceEnableSAP);
5611 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5612 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005613
Jeff Johnson295189b2012-06-20 16:38:30 -07005614 // Update WDI trace levels based upon the cfg.ini
5615 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5616 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5617 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5618 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5619 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5620 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5621 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5622 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005623
Jeff Johnson88ba7742013-02-27 14:36:02 -08005624 if (VOS_FTM_MODE == hdd_get_conparam())
5625 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005626 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5627 {
5628 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5629 goto err_free_hdd_context;
5630 }
5631 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5632 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005633 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005634
Jeff Johnson88ba7742013-02-27 14:36:02 -08005635 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005636 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5637 {
5638 status = vos_watchdog_open(pVosContext,
5639 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5640
5641 if(!VOS_IS_STATUS_SUCCESS( status ))
5642 {
5643 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005644 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005645 }
5646 }
5647
5648 pHddCtx->isLogpInProgress = FALSE;
5649 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5650
Jeff Johnson295189b2012-06-20 16:38:30 -07005651 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5652 if(!VOS_IS_STATUS_SUCCESS(status))
5653 {
5654 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005655 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005656 }
5657
Jeff Johnson295189b2012-06-20 16:38:30 -07005658 status = vos_open( &pVosContext, 0);
5659 if ( !VOS_IS_STATUS_SUCCESS( status ))
5660 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005661 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5662 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005663 }
5664
Jeff Johnson295189b2012-06-20 16:38:30 -07005665 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5666
5667 if ( NULL == pHddCtx->hHal )
5668 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005669 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005670 goto err_vosclose;
5671 }
5672
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005673 status = vos_preStart( pHddCtx->pvosContext );
5674 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5675 {
5676 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5677 goto err_vosclose;
5678 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005679
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005680 /* Note that the vos_preStart() sequence triggers the cfg download.
5681 The cfg download must occur before we update the SME config
5682 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005683 status = hdd_set_sme_config( pHddCtx );
5684
5685 if ( VOS_STATUS_SUCCESS != status )
5686 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005687 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5688 goto err_vosclose;
5689 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005690
5691 //Initialize the WMM module
5692 status = hdd_wmm_init(pHddCtx);
5693 if (!VOS_IS_STATUS_SUCCESS(status))
5694 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005695 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005696 goto err_vosclose;
5697 }
5698
Jeff Johnson295189b2012-06-20 16:38:30 -07005699 /* In the integrated architecture we update the configuration from
5700 the INI file and from NV before vOSS has been started so that
5701 the final contents are available to send down to the cCPU */
5702
5703 // Apply the cfg.ini to cfg.dat
5704 if (FALSE == hdd_update_config_dat(pHddCtx))
5705 {
5706 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5707 goto err_vosclose;
5708 }
5709
5710 // Apply the NV to cfg.dat
5711 /* Prima Update MAC address only at here */
5712 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5713 {
5714#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5715 /* There was not a valid set of MAC Addresses in NV. See if the
5716 default addresses were modified by the cfg.ini settings. If so,
5717 we'll use them, but if not, we'll autogenerate a set of MAC
5718 addresses based upon the device serial number */
5719
5720 static const v_MACADDR_t default_address =
5721 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5722 unsigned int serialno;
5723 int i;
5724
5725 serialno = wcnss_get_serial_number();
5726 if ((0 != serialno) &&
5727 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5728 sizeof(default_address))))
5729 {
5730 /* cfg.ini has the default address, invoke autogen logic */
5731
5732 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5733 bytes of the serial number that can be used to generate
5734 the other 3 bytes of the MAC address. Mask off all but
5735 the lower 3 bytes (this will also make sure we don't
5736 overflow in the next step) */
5737 serialno &= 0x00FFFFFF;
5738
5739 /* we need a unique address for each session */
5740 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5741
5742 /* autogen all addresses */
5743 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5744 {
5745 /* start with the entire default address */
5746 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5747 /* then replace the lower 3 bytes */
5748 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5749 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5750 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5751
5752 serialno++;
5753 }
5754
5755 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5756 MAC_ADDRESS_STR,
5757 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5758 }
5759 else
5760#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5761 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005762 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005763 "%s: Invalid MAC address in NV, using MAC from ini file "
5764 MAC_ADDRESS_STR, __func__,
5765 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5766 }
5767 }
5768 {
5769 eHalStatus halStatus;
5770 // Set the MAC Address
5771 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5772 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5773 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5774 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5775
5776 if (!HAL_STATUS_SUCCESS( halStatus ))
5777 {
5778 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5779 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005780 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005781 }
5782 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005783
5784 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5785 Note: Firmware image will be read and downloaded inside vos_start API */
5786 status = vos_start( pHddCtx->pvosContext );
5787 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5788 {
5789 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5790 goto err_vosclose;
5791 }
5792
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005793 /* Exchange capability info between Host and FW and also get versioning info from FW */
5794 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005795
5796 status = hdd_post_voss_start_config( pHddCtx );
5797 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5798 {
5799 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5800 __func__);
5801 goto err_vosstop;
5802 }
5803
Jeff Johnson295189b2012-06-20 16:38:30 -07005804 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5805 {
5806 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5807 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5808 }
5809 else
5810 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005811 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5812 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5813 if (pAdapter != NULL)
5814 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305815 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005816 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305817 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5818 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5819 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005820
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305821 /* Generate the P2P Device Address. This consists of the device's
5822 * primary MAC address with the locally administered bit set.
5823 */
5824 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005825 }
5826 else
5827 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305828 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5829 if (p2p_dev_addr != NULL)
5830 {
5831 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5832 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5833 }
5834 else
5835 {
5836 hddLog(VOS_TRACE_LEVEL_FATAL,
5837 "%s: Failed to allocate mac_address for p2p_device",
5838 __func__);
5839 goto err_close_adapter;
5840 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005841 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005842
5843 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5844 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5845 if ( NULL == pP2pAdapter )
5846 {
5847 hddLog(VOS_TRACE_LEVEL_FATAL,
5848 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005849 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005850 goto err_close_adapter;
5851 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005852 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005853 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005854
5855 if( pAdapter == NULL )
5856 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005857 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5858 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005859 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005860
Jeff Johnson295189b2012-06-20 16:38:30 -07005861#ifdef WLAN_BTAMP_FEATURE
5862 vStatus = WLANBAP_Open(pVosContext);
5863 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5864 {
5865 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5866 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005867 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005868 }
5869
5870 vStatus = BSL_Init(pVosContext);
5871 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5872 {
5873 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5874 "%s: Failed to Init BSL",__func__);
5875 goto err_bap_close;
5876 }
5877 vStatus = WLANBAP_Start(pVosContext);
5878 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5879 {
5880 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5881 "%s: Failed to start TL",__func__);
5882 goto err_bap_close;
5883 }
5884
5885 pConfig = pHddCtx->cfg_ini;
5886 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5887 status = WLANBAP_SetConfig(&btAmpConfig);
5888
5889#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005890
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005891#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5892 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5893 {
5894 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5895 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5896 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5897 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5898 }
5899#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005900#ifdef FEATURE_WLAN_SCAN_PNO
5901 /*SME must send channel update configuration to RIVA*/
5902 sme_UpdateChannelConfig(pHddCtx->hHal);
5903#endif
5904
Jeff Johnson295189b2012-06-20 16:38:30 -07005905 /* Register with platform driver as client for Suspend/Resume */
5906 status = hddRegisterPmOps(pHddCtx);
5907 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5908 {
5909 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5910#ifdef WLAN_BTAMP_FEATURE
5911 goto err_bap_stop;
5912#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005913 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005914#endif //WLAN_BTAMP_FEATURE
5915 }
5916
Yue Ma0d4891e2013-08-06 17:01:45 -07005917 /* Open debugfs interface */
5918 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
5919 {
5920 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5921 "%s: hdd_debugfs_init failed!", __func__);
5922 goto err_close_debugfs;
5923 }
5924
Jeff Johnson295189b2012-06-20 16:38:30 -07005925 /* Register TM level change handler function to the platform */
5926 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5927 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5928 {
5929 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5930 goto err_unregister_pmops;
5931 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005932
5933 /* register for riva power on lock to platform driver */
5934 if (req_riva_power_on_lock("wlan"))
5935 {
5936 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5937 __func__);
5938 goto err_unregister_pmops;
5939 }
5940
Jeff Johnson295189b2012-06-20 16:38:30 -07005941 // register net device notifier for device change notification
5942 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5943
5944 if(ret < 0)
5945 {
5946 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5947 goto err_free_power_on_lock;
5948 }
5949
5950 //Initialize the nlink service
5951 if(nl_srv_init() != 0)
5952 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305953 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005954 goto err_reg_netdev;
5955 }
5956
5957 //Initialize the BTC service
5958 if(btc_activate_service(pHddCtx) != 0)
5959 {
5960 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5961 goto err_nl_srv;
5962 }
5963
5964#ifdef PTT_SOCK_SVC_ENABLE
5965 //Initialize the PTT service
5966 if(ptt_sock_activate_svc(pHddCtx) != 0)
5967 {
5968 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5969 goto err_nl_srv;
5970 }
5971#endif
5972
Jeff Johnson295189b2012-06-20 16:38:30 -07005973 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005974 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005975 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005976 /* Action frame registered in one adapter which will
5977 * applicable to all interfaces
5978 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005979 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005980 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005981
5982 mutex_init(&pHddCtx->sap_lock);
5983
5984 pHddCtx->isLoadUnloadInProgress = FALSE;
5985
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005986#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005987#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5988 /* Initialize the wake lcok */
5989 wake_lock_init(&pHddCtx->rx_wake_lock,
5990 WAKE_LOCK_SUSPEND,
5991 "qcom_rx_wakelock");
5992#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005993 /* Initialize the wake lcok */
5994 wake_lock_init(&pHddCtx->sap_wake_lock,
5995 WAKE_LOCK_SUSPEND,
5996 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005997#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005998
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005999 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
6000 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07006001
6002 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
6003 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05306004
Jeff Johnsone7245742012-09-05 17:12:55 -07006005 // Initialize the restart logic
6006 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05306007
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05306008 if (!VOS_IS_STATUS_SUCCESS( vos_timer_init( &pHddCtx->hdd_p2p_go_conn_is_in_progress,
6009 VOS_TIMER_TYPE_SW, wlan_hdd_p2p_go_connection_in_progresscb, pAdapter) ) )
6010 {
6011 hddLog(VOS_TRACE_LEVEL_ERROR,
6012 "%s: vos timer init failed for hdd_p2p_go_conn_is_in_progress", __func__);
6013 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006014 goto success;
6015
6016err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07006017#ifdef WLAN_KD_READY_NOTIFIER
6018 nl_srv_exit(pHddCtx->ptt_pid);
6019#else
Jeff Johnson295189b2012-06-20 16:38:30 -07006020 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07006021#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07006022err_reg_netdev:
6023 unregister_netdevice_notifier(&hdd_netdev_notifier);
6024
6025err_free_power_on_lock:
6026 free_riva_power_on_lock("wlan");
6027
6028err_unregister_pmops:
6029 hddDevTmUnregisterNotifyCallback(pHddCtx);
6030 hddDeregisterPmOps(pHddCtx);
6031
Yue Ma0d4891e2013-08-06 17:01:45 -07006032err_close_debugfs:
6033 hdd_debugfs_exit(pHddCtx);
6034
Jeff Johnson295189b2012-06-20 16:38:30 -07006035#ifdef WLAN_BTAMP_FEATURE
6036err_bap_stop:
6037 WLANBAP_Stop(pVosContext);
6038#endif
6039
6040#ifdef WLAN_BTAMP_FEATURE
6041err_bap_close:
6042 WLANBAP_Close(pVosContext);
6043#endif
6044
Jeff Johnson295189b2012-06-20 16:38:30 -07006045err_close_adapter:
6046 hdd_close_all_adapters( pHddCtx );
6047
6048err_vosstop:
6049 vos_stop(pVosContext);
6050
6051err_vosclose:
6052 status = vos_sched_close( pVosContext );
6053 if (!VOS_IS_STATUS_SUCCESS(status)) {
6054 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
6055 "%s: Failed to close VOSS Scheduler", __func__);
6056 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
6057 }
6058 vos_close(pVosContext );
6059
Jeff Johnson295189b2012-06-20 16:38:30 -07006060err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006061 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006062
6063err_wdclose:
6064 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6065 vos_watchdog_close(pVosContext);
6066
Jeff Johnson295189b2012-06-20 16:38:30 -07006067err_wiphy_reg:
6068 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006069
6070err_config:
6071 kfree(pHddCtx->cfg_ini);
6072 pHddCtx->cfg_ini= NULL;
6073
6074err_free_hdd_context:
6075 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07006076 wiphy_free(wiphy) ;
6077 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006078 VOS_BUG(1);
6079
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08006080 if (hdd_is_ssr_required())
6081 {
6082 /* WDI timeout had happened during load, so SSR is needed here */
6083 subsystem_restart("wcnss");
6084 msleep(5000);
6085 }
6086 hdd_set_ssr_required (VOS_FALSE);
6087
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006088 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006089
6090success:
6091 EXIT();
6092 return 0;
6093}
6094
6095/**---------------------------------------------------------------------------
6096
Jeff Johnson32d95a32012-09-10 13:15:23 -07006097 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07006098
Jeff Johnson32d95a32012-09-10 13:15:23 -07006099 This is the driver entry point - called in different timeline depending
6100 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07006101
6102 \param - None
6103
6104 \return - 0 for success, non zero for failure
6105
6106 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07006107static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006108{
6109 VOS_STATUS status;
6110 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006111 struct device *dev = NULL;
6112 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006113#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6114 int max_retries = 0;
6115#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006116
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306117#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6118 vos_wconn_trace_init();
6119#endif
6120
Jeff Johnson295189b2012-06-20 16:38:30 -07006121 ENTER();
6122
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006123#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006124 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07006125#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006126
6127 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
6128 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
6129
6130 //Power Up Libra WLAN card first if not already powered up
6131 status = vos_chipPowerUp(NULL,NULL,NULL);
6132 if (!VOS_IS_STATUS_SUCCESS(status))
6133 {
6134 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
6135 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306136#ifdef WLAN_OPEN_SOURCE
6137 wake_lock_destroy(&wlan_wake_lock);
6138#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006139 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006140 }
6141
Jeff Johnson295189b2012-06-20 16:38:30 -07006142#ifdef ANI_BUS_TYPE_PCI
6143
6144 dev = wcnss_wlan_get_device();
6145
6146#endif // ANI_BUS_TYPE_PCI
6147
6148#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006149
6150#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6151 /* wait until WCNSS driver downloads NV */
6152 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6153 msleep(1000);
6154 }
6155 if (max_retries >= 5) {
6156 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306157#ifdef WLAN_OPEN_SOURCE
6158 wake_lock_destroy(&wlan_wake_lock);
6159#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006160 return -ENODEV;
6161 }
6162#endif
6163
Jeff Johnson295189b2012-06-20 16:38:30 -07006164 dev = wcnss_wlan_get_device();
6165#endif // ANI_BUS_TYPE_PLATFORM
6166
6167
6168 do {
6169 if (NULL == dev) {
6170 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6171 ret_status = -1;
6172 break;
6173 }
6174
6175#ifdef MEMORY_DEBUG
6176 vos_mem_init();
6177#endif
6178
6179#ifdef TIMER_MANAGER
6180 vos_timer_manager_init();
6181#endif
6182
6183 /* Preopen VOSS so that it is ready to start at least SAL */
6184 status = vos_preOpen(&pVosContext);
6185
6186 if (!VOS_IS_STATUS_SUCCESS(status))
6187 {
6188 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6189 ret_status = -1;
6190 break;
6191 }
6192
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006193#ifndef MODULE
6194 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6195 */
6196 hdd_set_conparam((v_UINT_t)con_mode);
6197#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006198
6199 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006200 if (hdd_wlan_startup(dev))
6201 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006202 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006203 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006204 vos_preClose( &pVosContext );
6205 ret_status = -1;
6206 break;
6207 }
6208
6209 /* Cancel the vote for XO Core ON
6210 * This is done here for safety purposes in case we re-initialize without turning
6211 * it OFF in any error scenario.
6212 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006213 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006214 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006215 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006216 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6217 {
6218 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6219 " Power consumed will be high\n");
6220 }
6221 } while (0);
6222
6223 if (0 != ret_status)
6224 {
6225 //Assert Deep sleep signal now to put Libra HW in lowest power state
6226 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6227 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6228
6229 //Vote off any PMIC voltage supplies
6230 vos_chipPowerDown(NULL, NULL, NULL);
6231#ifdef TIMER_MANAGER
6232 vos_timer_exit();
6233#endif
6234#ifdef MEMORY_DEBUG
6235 vos_mem_exit();
6236#endif
6237
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006238#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006239 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006240#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006241 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6242 }
6243 else
6244 {
6245 //Send WLAN UP indication to Nlink Service
6246 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6247
6248 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07006249 }
6250
6251 EXIT();
6252
6253 return ret_status;
6254}
6255
Jeff Johnson32d95a32012-09-10 13:15:23 -07006256/**---------------------------------------------------------------------------
6257
6258 \brief hdd_module_init() - Init Function
6259
6260 This is the driver entry point (invoked when module is loaded using insmod)
6261
6262 \param - None
6263
6264 \return - 0 for success, non zero for failure
6265
6266 --------------------------------------------------------------------------*/
6267#ifdef MODULE
6268static int __init hdd_module_init ( void)
6269{
6270 return hdd_driver_init();
6271}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006272#else /* #ifdef MODULE */
6273static int __init hdd_module_init ( void)
6274{
6275 /* Driver initialization is delayed to fwpath_changed_handler */
6276 return 0;
6277}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006278#endif /* #ifdef MODULE */
6279
Jeff Johnson295189b2012-06-20 16:38:30 -07006280
6281/**---------------------------------------------------------------------------
6282
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006283 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006284
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006285 This is the driver exit point (invoked when module is unloaded using rmmod
6286 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006287
6288 \param - None
6289
6290 \return - None
6291
6292 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006293static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006294{
6295 hdd_context_t *pHddCtx = NULL;
6296 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006297 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006298
6299 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6300
6301 //Get the global vos context
6302 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6303
6304 if(!pVosContext)
6305 {
6306 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6307 goto done;
6308 }
6309
6310 //Get the HDD context.
6311 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6312
6313 if(!pHddCtx)
6314 {
6315 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6316 }
6317 else
6318 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006319 while(isWDresetInProgress()) {
6320 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6321 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006322 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006323
6324 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6325 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6326 "%s:SSR never completed, fatal error", __func__);
6327 VOS_BUG(0);
6328 }
6329 }
6330
Jeff Johnson295189b2012-06-20 16:38:30 -07006331
6332 pHddCtx->isLoadUnloadInProgress = TRUE;
6333 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6334
6335 //Do all the cleanup before deregistering the driver
6336 hdd_wlan_exit(pHddCtx);
6337 }
6338
Jeff Johnson295189b2012-06-20 16:38:30 -07006339 vos_preClose( &pVosContext );
6340
6341#ifdef TIMER_MANAGER
6342 vos_timer_exit();
6343#endif
6344#ifdef MEMORY_DEBUG
6345 vos_mem_exit();
6346#endif
6347
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306348#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6349 vos_wconn_trace_exit();
6350#endif
6351
Jeff Johnson295189b2012-06-20 16:38:30 -07006352done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006353#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006354 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006355#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006356 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6357}
6358
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006359/**---------------------------------------------------------------------------
6360
6361 \brief hdd_module_exit() - Exit function
6362
6363 This is the driver exit point (invoked when module is unloaded using rmmod)
6364
6365 \param - None
6366
6367 \return - None
6368
6369 --------------------------------------------------------------------------*/
6370static void __exit hdd_module_exit(void)
6371{
6372 hdd_driver_exit();
6373}
6374
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006375#ifdef MODULE
6376static int fwpath_changed_handler(const char *kmessage,
6377 struct kernel_param *kp)
6378{
Jeff Johnson76052702013-04-16 13:55:05 -07006379 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006380}
6381
6382static int con_mode_handler(const char *kmessage,
6383 struct kernel_param *kp)
6384{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006385 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006386}
6387#else /* #ifdef MODULE */
6388/**---------------------------------------------------------------------------
6389
Jeff Johnson76052702013-04-16 13:55:05 -07006390 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006391
Jeff Johnson76052702013-04-16 13:55:05 -07006392 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006393 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006394 - invoked when module parameter fwpath is modified from userspace to signal
6395 initializing the WLAN driver or when con_mode is modified from userspace
6396 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006397
6398 \return - 0 for success, non zero for failure
6399
6400 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006401static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006402{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006403 int ret_status;
6404
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006405 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006406 ret_status = hdd_driver_init();
6407 wlan_hdd_inited = ret_status ? 0 : 1;
6408 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006409 }
6410
6411 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006412
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006413 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006414
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006415 ret_status = hdd_driver_init();
6416 wlan_hdd_inited = ret_status ? 0 : 1;
6417 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006418}
6419
Jeff Johnson295189b2012-06-20 16:38:30 -07006420/**---------------------------------------------------------------------------
6421
Jeff Johnson76052702013-04-16 13:55:05 -07006422 \brief fwpath_changed_handler() - Handler Function
6423
6424 Handle changes to the fwpath parameter
6425
6426 \return - 0 for success, non zero for failure
6427
6428 --------------------------------------------------------------------------*/
6429static int fwpath_changed_handler(const char *kmessage,
6430 struct kernel_param *kp)
6431{
6432 int ret;
6433
6434 ret = param_set_copystring(kmessage, kp);
6435 if (0 == ret)
6436 ret = kickstart_driver();
6437 return ret;
6438}
6439
6440/**---------------------------------------------------------------------------
6441
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006442 \brief con_mode_handler() -
6443
6444 Handler function for module param con_mode when it is changed by userspace
6445 Dynamically linked - do nothing
6446 Statically linked - exit and init driver, as in rmmod and insmod
6447
Jeff Johnson76052702013-04-16 13:55:05 -07006448 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006449
Jeff Johnson76052702013-04-16 13:55:05 -07006450 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006451
6452 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006453static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006454{
Jeff Johnson76052702013-04-16 13:55:05 -07006455 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006456
Jeff Johnson76052702013-04-16 13:55:05 -07006457 ret = param_set_int(kmessage, kp);
6458 if (0 == ret)
6459 ret = kickstart_driver();
6460 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006461}
6462#endif /* #ifdef MODULE */
6463
6464/**---------------------------------------------------------------------------
6465
Jeff Johnson295189b2012-06-20 16:38:30 -07006466 \brief hdd_get_conparam() -
6467
6468 This is the driver exit point (invoked when module is unloaded using rmmod)
6469
6470 \param - None
6471
6472 \return - tVOS_CON_MODE
6473
6474 --------------------------------------------------------------------------*/
6475tVOS_CON_MODE hdd_get_conparam ( void )
6476{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006477#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006478 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006479#else
6480 return (tVOS_CON_MODE)curr_con_mode;
6481#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006482}
6483void hdd_set_conparam ( v_UINT_t newParam )
6484{
6485 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006486#ifndef MODULE
6487 curr_con_mode = con_mode;
6488#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006489}
6490/**---------------------------------------------------------------------------
6491
6492 \brief hdd_softap_sta_deauth() - function
6493
6494 This to take counter measure to handle deauth req from HDD
6495
6496 \param - pAdapter - Pointer to the HDD
6497
6498 \param - enable - boolean value
6499
6500 \return - None
6501
6502 --------------------------------------------------------------------------*/
6503
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006504VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006505{
Jeff Johnson295189b2012-06-20 16:38:30 -07006506 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006507 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006508
6509 ENTER();
6510
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306511 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006512
6513 //Ignore request to deauth bcmc station
6514 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006515 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006516
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006517 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006518
6519 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006520 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006521}
6522
6523/**---------------------------------------------------------------------------
6524
6525 \brief hdd_softap_sta_disassoc() - function
6526
6527 This to take counter measure to handle deauth req from HDD
6528
6529 \param - pAdapter - Pointer to the HDD
6530
6531 \param - enable - boolean value
6532
6533 \return - None
6534
6535 --------------------------------------------------------------------------*/
6536
6537void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6538{
6539 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6540
6541 ENTER();
6542
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306543 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006544
6545 //Ignore request to disassoc bcmc station
6546 if( pDestMacAddress[0] & 0x1 )
6547 return;
6548
6549 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6550}
6551
6552void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6553{
6554 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6555
6556 ENTER();
6557
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306558 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006559
6560 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6561}
6562
Jeff Johnson295189b2012-06-20 16:38:30 -07006563/**---------------------------------------------------------------------------
6564 *
6565 * \brief hdd_get__concurrency_mode() -
6566 *
6567 *
6568 * \param - None
6569 *
6570 * \return - CONCURRENCY MODE
6571 *
6572 * --------------------------------------------------------------------------*/
6573tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6574{
6575 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6576 hdd_context_t *pHddCtx;
6577
6578 if (NULL != pVosContext)
6579 {
6580 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6581 if (NULL != pHddCtx)
6582 {
6583 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6584 }
6585 }
6586
6587 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006588 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006589 return VOS_STA;
6590}
6591
6592/* Decide whether to allow/not the apps power collapse.
6593 * Allow apps power collapse if we are in connected state.
6594 * if not, allow only if we are in IMPS */
6595v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6596{
6597 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006598 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006599 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006600 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6601 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6602 hdd_adapter_t *pAdapter = NULL;
6603 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006604 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006605
Jeff Johnson295189b2012-06-20 16:38:30 -07006606 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6607 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006608
Yathish9f22e662012-12-10 14:21:35 -08006609 concurrent_state = hdd_get_concurrency_mode();
6610
6611#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6612 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6613 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6614 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6615 return TRUE;
6616#endif
6617
Jeff Johnson295189b2012-06-20 16:38:30 -07006618 /*loop through all adapters. TBD fix for Concurrency */
6619 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6620 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6621 {
6622 pAdapter = pAdapterNode->pAdapter;
6623 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6624 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6625 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006626 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006627 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006628 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006629 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6630 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006631 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006632 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006633 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6634 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006635 return FALSE;
6636 }
6637 }
6638 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6639 pAdapterNode = pNext;
6640 }
6641 return TRUE;
6642}
6643
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006644/* Decides whether to send suspend notification to Riva
6645 * if any adapter is in BMPS; then it is required */
6646v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6647{
6648 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6649 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6650
6651 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6652 {
6653 return TRUE;
6654 }
6655 return FALSE;
6656}
6657
Jeff Johnson295189b2012-06-20 16:38:30 -07006658void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6659{
6660 switch(mode)
6661 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006662 case VOS_STA_MODE:
6663 case VOS_P2P_CLIENT_MODE:
6664 case VOS_P2P_GO_MODE:
6665 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006666 pHddCtx->concurrency_mode |= (1 << mode);
6667 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006668 break;
6669 default:
6670 break;
6671
6672 }
6673 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6674 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6675}
6676
6677
6678void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6679{
6680 switch(mode)
6681 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006682 case VOS_STA_MODE:
6683 case VOS_P2P_CLIENT_MODE:
6684 case VOS_P2P_GO_MODE:
6685 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006686 pHddCtx->no_of_sessions[mode]--;
6687 if (!(pHddCtx->no_of_sessions[mode]))
6688 pHddCtx->concurrency_mode &= (~(1 << mode));
6689 break;
6690 default:
6691 break;
6692 }
6693 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6694 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6695}
6696
Jeff Johnsone7245742012-09-05 17:12:55 -07006697/**---------------------------------------------------------------------------
6698 *
6699 * \brief wlan_hdd_restart_init
6700 *
6701 * This function initalizes restart timer/flag. An internal function.
6702 *
6703 * \param - pHddCtx
6704 *
6705 * \return - None
6706 *
6707 * --------------------------------------------------------------------------*/
6708
6709static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6710{
6711 /* Initialize */
6712 pHddCtx->hdd_restart_retries = 0;
6713 atomic_set(&pHddCtx->isRestartInProgress, 0);
6714 vos_timer_init(&pHddCtx->hdd_restart_timer,
6715 VOS_TIMER_TYPE_SW,
6716 wlan_hdd_restart_timer_cb,
6717 pHddCtx);
6718}
6719/**---------------------------------------------------------------------------
6720 *
6721 * \brief wlan_hdd_restart_deinit
6722 *
6723 * This function cleans up the resources used. An internal function.
6724 *
6725 * \param - pHddCtx
6726 *
6727 * \return - None
6728 *
6729 * --------------------------------------------------------------------------*/
6730
6731static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6732{
6733
6734 VOS_STATUS vos_status;
6735 /* Block any further calls */
6736 atomic_set(&pHddCtx->isRestartInProgress, 1);
6737 /* Cleanup */
6738 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6739 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006740 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006741 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6742 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006743 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006744
6745}
6746
6747/**---------------------------------------------------------------------------
6748 *
6749 * \brief wlan_hdd_framework_restart
6750 *
6751 * This function uses a cfg80211 API to start a framework initiated WLAN
6752 * driver module unload/load.
6753 *
6754 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6755 *
6756 *
6757 * \param - pHddCtx
6758 *
6759 * \return - VOS_STATUS_SUCCESS: Success
6760 * VOS_STATUS_E_EMPTY: Adapter is Empty
6761 * VOS_STATUS_E_NOMEM: No memory
6762
6763 * --------------------------------------------------------------------------*/
6764
6765static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6766{
6767 VOS_STATUS status = VOS_STATUS_SUCCESS;
6768 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006769 int len = (sizeof (struct ieee80211_mgmt));
6770 struct ieee80211_mgmt *mgmt = NULL;
6771
6772 /* Prepare the DEAUTH managment frame with reason code */
6773 mgmt = kzalloc(len, GFP_KERNEL);
6774 if(mgmt == NULL)
6775 {
6776 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6777 "%s: memory allocation failed (%d bytes)", __func__, len);
6778 return VOS_STATUS_E_NOMEM;
6779 }
6780 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006781
6782 /* Iterate over all adapters/devices */
6783 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6784 do
6785 {
6786 if( (status == VOS_STATUS_SUCCESS) &&
6787 pAdapterNode &&
6788 pAdapterNode->pAdapter)
6789 {
6790 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6791 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6792 pAdapterNode->pAdapter->dev->name,
6793 pAdapterNode->pAdapter->device_mode,
6794 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006795 /*
6796 * CFG80211 event to restart the driver
6797 *
6798 * 'cfg80211_send_unprot_deauth' sends a
6799 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6800 * of SME(Linux Kernel) state machine.
6801 *
6802 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6803 * the driver.
6804 *
6805 */
6806
6807 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006808 }
6809 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6810 pAdapterNode = pNext;
6811 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6812
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006813
6814 /* Free the allocated management frame */
6815 kfree(mgmt);
6816
Jeff Johnsone7245742012-09-05 17:12:55 -07006817 /* Retry until we unload or reach max count */
6818 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6819 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6820
6821 return status;
6822
6823}
6824/**---------------------------------------------------------------------------
6825 *
6826 * \brief wlan_hdd_restart_timer_cb
6827 *
6828 * Restart timer callback. An internal function.
6829 *
6830 * \param - User data:
6831 *
6832 * \return - None
6833 *
6834 * --------------------------------------------------------------------------*/
6835
6836void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6837{
6838 hdd_context_t *pHddCtx = usrDataForCallback;
6839 wlan_hdd_framework_restart(pHddCtx);
6840 return;
6841
6842}
6843
6844
6845/**---------------------------------------------------------------------------
6846 *
6847 * \brief wlan_hdd_restart_driver
6848 *
6849 * This function sends an event to supplicant to restart the WLAN driver.
6850 *
6851 * This function is called from vos_wlanRestart.
6852 *
6853 * \param - pHddCtx
6854 *
6855 * \return - VOS_STATUS_SUCCESS: Success
6856 * VOS_STATUS_E_EMPTY: Adapter is Empty
6857 * VOS_STATUS_E_ALREADY: Request already in progress
6858
6859 * --------------------------------------------------------------------------*/
6860VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6861{
6862 VOS_STATUS status = VOS_STATUS_SUCCESS;
6863
6864 /* A tight check to make sure reentrancy */
6865 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6866 {
6867 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6868 "%s: WLAN restart is already in progress", __func__);
6869
6870 return VOS_STATUS_E_ALREADY;
6871 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006872 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006873#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006874 wcnss_reset_intr();
6875#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006876
Jeff Johnsone7245742012-09-05 17:12:55 -07006877 return status;
6878}
6879
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006880/*
6881 * API to find if there is any STA or P2P-Client is connected
6882 */
6883VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6884{
6885 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6886}
Jeff Johnsone7245742012-09-05 17:12:55 -07006887
Jeff Johnson295189b2012-06-20 16:38:30 -07006888//Register the module init/exit functions
6889module_init(hdd_module_init);
6890module_exit(hdd_module_exit);
6891
6892MODULE_LICENSE("Dual BSD/GPL");
6893MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6894MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6895
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006896module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6897 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006898
Jeff Johnson76052702013-04-16 13:55:05 -07006899module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006900 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);