blob: 64469e51627be4dca9244c933d8a28ba091c0a3d [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
Yue Maf49ba872013-08-19 12:04:25 -07001391 wlan_hdd_action( NULL,
1392#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1393 &(pAdapter->wdev),
1394#else
1395 dev,
1396#endif
1397 &chan, 0,
1398#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1399 NL80211_CHAN_HT20, 1,
1400#endif
1401 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001402 1, &cookie );
1403 vos_mem_free(finalBuf);
1404 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001405 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1406 {
1407 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1408 char extra[32];
1409 tANI_U8 len = 0;
1410
1411 /* value is interms of msec */
1412 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1413 if (copy_to_user(priv_data.buf, &extra, len + 1))
1414 {
1415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1416 "%s: failed to copy data to user buffer", __func__);
1417 ret = -EFAULT;
1418 goto exit;
1419 }
1420 }
1421 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1422 {
1423 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001424 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001425 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001426
1427 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1428 value = value + 19;
1429 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001430 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001431 if (ret < 0)
1432 {
1433 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001434 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001435 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001436 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001437 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1438 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1439 ret = -EINVAL;
1440 goto exit;
1441 }
1442
1443 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1444 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1445 {
1446 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1447 "lfr mode value %d is out of range"
1448 " (Min: %d Max: %d)", maxTime,
1449 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1450 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1451 ret = -EINVAL;
1452 goto exit;
1453 }
1454
1455 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1456 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1457
1458 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001459
1460 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1461 * where RFS is the RF Switching time. It is twice RFS to consider the
1462 * time to go off channel and return to the home channel. */
1463 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1464 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1465 {
1466 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1467 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1468 " Hence enforcing home away time to disable (0)",
1469 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1470 homeAwayTime = 0;
1471 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1472 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
1473 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001474 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1475 }
1476 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1477 {
1478 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1479 char extra[32];
1480 tANI_U8 len = 0;
1481
1482 /* value is interms of msec */
1483 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1484 if (copy_to_user(priv_data.buf, &extra, len + 1))
1485 {
1486 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1487 "%s: failed to copy data to user buffer", __func__);
1488 ret = -EFAULT;
1489 goto exit;
1490 }
1491 }
1492 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1493 {
1494 tANI_U8 *value = command;
1495 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1496
1497 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1498 value = value + 16;
1499 /* Convert the value from ascii to integer */
1500 ret = kstrtou16(value, 10, &val);
1501 if (ret < 0)
1502 {
1503 /* If the input value is greater than max value of datatype, then also
1504 kstrtou16 fails */
1505 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1506 "%s: kstrtou16 failed range [%d - %d]", __func__,
1507 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1508 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1509 ret = -EINVAL;
1510 goto exit;
1511 }
1512
1513 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1514 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1515 {
1516 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1517 "scan home time value %d is out of range"
1518 " (Min: %d Max: %d)", val,
1519 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1520 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1521 ret = -EINVAL;
1522 goto exit;
1523 }
1524
1525 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1526 "%s: Received Command to change scan home time = %d", __func__, val);
1527
1528 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1529 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1530 }
1531 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1532 {
1533 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1534 char extra[32];
1535 tANI_U8 len = 0;
1536
1537 /* value is interms of msec */
1538 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1539 if (copy_to_user(priv_data.buf, &extra, len + 1))
1540 {
1541 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1542 "%s: failed to copy data to user buffer", __func__);
1543 ret = -EFAULT;
1544 goto exit;
1545 }
1546 }
1547 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1548 {
1549 tANI_U8 *value = command;
1550 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1551
1552 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1553 value = value + 17;
1554 /* Convert the value from ascii to integer */
1555 ret = kstrtou8(value, 10, &val);
1556 if (ret < 0)
1557 {
1558 /* If the input value is greater than max value of datatype, then also
1559 kstrtou8 fails */
1560 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1561 "%s: kstrtou8 failed range [%d - %d]", __func__,
1562 CFG_ROAM_INTRA_BAND_MIN,
1563 CFG_ROAM_INTRA_BAND_MAX);
1564 ret = -EINVAL;
1565 goto exit;
1566 }
1567
1568 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1569 (val > CFG_ROAM_INTRA_BAND_MAX))
1570 {
1571 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1572 "intra band mode value %d is out of range"
1573 " (Min: %d Max: %d)", val,
1574 CFG_ROAM_INTRA_BAND_MIN,
1575 CFG_ROAM_INTRA_BAND_MAX);
1576 ret = -EINVAL;
1577 goto exit;
1578 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1580 "%s: Received Command to change intra band = %d", __func__, val);
1581
1582 pHddCtx->cfg_ini->nRoamIntraBand = val;
1583 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1584 }
1585 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1586 {
1587 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1588 char extra[32];
1589 tANI_U8 len = 0;
1590
1591 /* value is interms of msec */
1592 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1593 if (copy_to_user(priv_data.buf, &extra, len + 1))
1594 {
1595 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1596 "%s: failed to copy data to user buffer", __func__);
1597 ret = -EFAULT;
1598 goto exit;
1599 }
1600 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001601 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1602 {
1603 tANI_U8 *value = command;
1604 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1605
1606 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1607 value = value + 15;
1608 /* Convert the value from ascii to integer */
1609 ret = kstrtou8(value, 10, &nProbes);
1610 if (ret < 0)
1611 {
1612 /* If the input value is greater than max value of datatype, then also
1613 kstrtou8 fails */
1614 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1615 "%s: kstrtou8 failed range [%d - %d]", __func__,
1616 CFG_ROAM_SCAN_N_PROBES_MIN,
1617 CFG_ROAM_SCAN_N_PROBES_MAX);
1618 ret = -EINVAL;
1619 goto exit;
1620 }
1621
1622 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1623 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1624 {
1625 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1626 "NProbes value %d is out of range"
1627 " (Min: %d Max: %d)", nProbes,
1628 CFG_ROAM_SCAN_N_PROBES_MIN,
1629 CFG_ROAM_SCAN_N_PROBES_MAX);
1630 ret = -EINVAL;
1631 goto exit;
1632 }
1633
1634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1635 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1636
1637 pHddCtx->cfg_ini->nProbes = nProbes;
1638 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1639 }
1640 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1641 {
1642 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1643 char extra[32];
1644 tANI_U8 len = 0;
1645
1646 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1647 if (copy_to_user(priv_data.buf, &extra, len + 1))
1648 {
1649 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1650 "%s: failed to copy data to user buffer", __func__);
1651 ret = -EFAULT;
1652 goto exit;
1653 }
1654 }
1655 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1656 {
1657 tANI_U8 *value = command;
1658 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001659 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001660
1661 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1662 /* input value is in units of msec */
1663 value = value + 20;
1664 /* Convert the value from ascii to integer */
1665 ret = kstrtou16(value, 10, &homeAwayTime);
1666 if (ret < 0)
1667 {
1668 /* If the input value is greater than max value of datatype, then also
1669 kstrtou8 fails */
1670 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1671 "%s: kstrtou8 failed range [%d - %d]", __func__,
1672 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1673 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1674 ret = -EINVAL;
1675 goto exit;
1676 }
1677
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001678 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1679 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1680 {
1681 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1682 "homeAwayTime value %d is out of range"
1683 " (Min: %d Max: %d)", homeAwayTime,
1684 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1685 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1686 ret = -EINVAL;
1687 goto exit;
1688 }
1689
1690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1691 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1692
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001693 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1694 * where RFS is the RF Switching time. It is twice RFS to consider the
1695 * time to go off channel and return to the home channel. */
1696 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1697 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1698 {
1699 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1700 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1701 " Hence enforcing home away time to disable (0)",
1702 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1703 homeAwayTime = 0;
1704 }
1705
1706 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
1707 {
1708 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1709 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
1710 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001711 }
1712 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1713 {
1714 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1715 char extra[32];
1716 tANI_U8 len = 0;
1717
1718 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1719 if (copy_to_user(priv_data.buf, &extra, len + 1))
1720 {
1721 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1722 "%s: failed to copy data to user buffer", __func__);
1723 ret = -EFAULT;
1724 goto exit;
1725 }
1726 }
1727 else if (strncmp(command, "REASSOC", 7) == 0)
1728 {
1729 tANI_U8 *value = command;
1730 tANI_U8 channel = 0;
1731 tSirMacAddr targetApBssid;
1732 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001733#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1734 tCsrHandoffRequest handoffInfo;
1735#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001736 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001737 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1738
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001739 /* if not associated, no need to proceed with reassoc */
1740 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1741 {
1742 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1743 ret = -EINVAL;
1744 goto exit;
1745 }
1746
1747 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1748 if (eHAL_STATUS_SUCCESS != status)
1749 {
1750 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1751 "%s: Failed to parse reassoc command data", __func__);
1752 ret = -EINVAL;
1753 goto exit;
1754 }
1755
1756 /* if the target bssid is same as currently associated AP,
1757 then no need to proceed with reassoc */
1758 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1759 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1760 {
1761 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1762 ret = -EINVAL;
1763 goto exit;
1764 }
1765
1766 /* Check channel number is a valid channel number */
1767 if(VOS_STATUS_SUCCESS !=
1768 wlan_hdd_validate_operation_channel(pAdapter, channel))
1769 {
1770 hddLog(VOS_TRACE_LEVEL_ERROR,
1771 "%s: Invalid Channel [%d] \n", __func__, channel);
1772 return -EINVAL;
1773 }
1774
1775 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001776#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1777 handoffInfo.channel = channel;
1778 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1779 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1780#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001781 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001782#endif
1783#ifdef FEATURE_WLAN_LFR
1784 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1785 {
1786 tANI_U8 *value = command;
1787 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1788
1789 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1790 value = value + 12;
1791 /* Convert the value from ascii to integer */
1792 ret = kstrtou8(value, 10, &lfrMode);
1793 if (ret < 0)
1794 {
1795 /* If the input value is greater than max value of datatype, then also
1796 kstrtou8 fails */
1797 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1798 "%s: kstrtou8 failed range [%d - %d]", __func__,
1799 CFG_LFR_FEATURE_ENABLED_MIN,
1800 CFG_LFR_FEATURE_ENABLED_MAX);
1801 ret = -EINVAL;
1802 goto exit;
1803 }
1804
1805 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1806 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1807 {
1808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1809 "lfr mode value %d is out of range"
1810 " (Min: %d Max: %d)", lfrMode,
1811 CFG_LFR_FEATURE_ENABLED_MIN,
1812 CFG_LFR_FEATURE_ENABLED_MAX);
1813 ret = -EINVAL;
1814 goto exit;
1815 }
1816
1817 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1818 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1819
1820 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1821 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1822 }
1823#endif
1824#ifdef WLAN_FEATURE_VOWIFI_11R
1825 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1826 {
1827 tANI_U8 *value = command;
1828 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1829
1830 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1831 value = value + 18;
1832 /* Convert the value from ascii to integer */
1833 ret = kstrtou8(value, 10, &ft);
1834 if (ret < 0)
1835 {
1836 /* If the input value is greater than max value of datatype, then also
1837 kstrtou8 fails */
1838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1839 "%s: kstrtou8 failed range [%d - %d]", __func__,
1840 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1841 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1842 ret = -EINVAL;
1843 goto exit;
1844 }
1845
1846 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1847 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1848 {
1849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1850 "ft mode value %d is out of range"
1851 " (Min: %d Max: %d)", ft,
1852 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1853 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1854 ret = -EINVAL;
1855 goto exit;
1856 }
1857
1858 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1859 "%s: Received Command to change ft mode = %d", __func__, ft);
1860
1861 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1862 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1863 }
1864#endif
1865#ifdef FEATURE_WLAN_CCX
1866 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1867 {
1868 tANI_U8 *value = command;
1869 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1870
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001871 /* Check if the features OKC/CCX/11R are supported simultaneously,
1872 then this operation is not permitted (return FAILURE) */
1873 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1874 hdd_is_okc_mode_enabled(pHddCtx) &&
1875 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1876 {
1877 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1878 "%s: OKC/CCX/11R are supported simultaneously"
1879 " hence this operation is not permitted!", __func__);
1880 ret = -EPERM;
1881 goto exit;
1882 }
1883
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001884 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1885 value = value + 11;
1886 /* Convert the value from ascii to integer */
1887 ret = kstrtou8(value, 10, &ccxMode);
1888 if (ret < 0)
1889 {
1890 /* If the input value is greater than max value of datatype, then also
1891 kstrtou8 fails */
1892 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1893 "%s: kstrtou8 failed range [%d - %d]", __func__,
1894 CFG_CCX_FEATURE_ENABLED_MIN,
1895 CFG_CCX_FEATURE_ENABLED_MAX);
1896 ret = -EINVAL;
1897 goto exit;
1898 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001899 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1900 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1901 {
1902 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1903 "Ccx mode value %d is out of range"
1904 " (Min: %d Max: %d)", ccxMode,
1905 CFG_CCX_FEATURE_ENABLED_MIN,
1906 CFG_CCX_FEATURE_ENABLED_MAX);
1907 ret = -EINVAL;
1908 goto exit;
1909 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001910 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1911 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1912
1913 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1914 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1915 }
1916#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001917 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1918 {
1919 tANI_U8 *value = command;
1920 tANI_BOOLEAN roamScanControl = 0;
1921
1922 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1923 value = value + 19;
1924 /* Convert the value from ascii to integer */
1925 ret = kstrtou8(value, 10, &roamScanControl);
1926 if (ret < 0)
1927 {
1928 /* If the input value is greater than max value of datatype, then also
1929 kstrtou8 fails */
1930 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1931 "%s: kstrtou8 failed ", __func__);
1932 ret = -EINVAL;
1933 goto exit;
1934 }
1935
1936 if (0 != roamScanControl)
1937 {
1938 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1939 "roam scan control invalid value = %d",
1940 roamScanControl);
1941 ret = -EINVAL;
1942 goto exit;
1943 }
1944 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1945 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1946
1947 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1948 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001949#ifdef FEATURE_WLAN_OKC
1950 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1951 {
1952 tANI_U8 *value = command;
1953 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1954
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001955 /* Check if the features OKC/CCX/11R are supported simultaneously,
1956 then this operation is not permitted (return FAILURE) */
1957 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1958 hdd_is_okc_mode_enabled(pHddCtx) &&
1959 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1960 {
1961 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1962 "%s: OKC/CCX/11R are supported simultaneously"
1963 " hence this operation is not permitted!", __func__);
1964 ret = -EPERM;
1965 goto exit;
1966 }
1967
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001968 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1969 value = value + 11;
1970 /* Convert the value from ascii to integer */
1971 ret = kstrtou8(value, 10, &okcMode);
1972 if (ret < 0)
1973 {
1974 /* If the input value is greater than max value of datatype, then also
1975 kstrtou8 fails */
1976 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1977 "%s: kstrtou8 failed range [%d - %d]", __func__,
1978 CFG_OKC_FEATURE_ENABLED_MIN,
1979 CFG_OKC_FEATURE_ENABLED_MAX);
1980 ret = -EINVAL;
1981 goto exit;
1982 }
1983
1984 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1985 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1986 {
1987 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1988 "Okc mode value %d is out of range"
1989 " (Min: %d Max: %d)", okcMode,
1990 CFG_OKC_FEATURE_ENABLED_MIN,
1991 CFG_OKC_FEATURE_ENABLED_MAX);
1992 ret = -EINVAL;
1993 goto exit;
1994 }
1995
1996 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1997 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1998
1999 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
2000 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002001 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
2002 {
2003 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
2004 char extra[32];
2005 tANI_U8 len = 0;
2006
2007 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
2008 if (copy_to_user(priv_data.buf, &extra, len + 1))
2009 {
2010 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2011 "%s: failed to copy data to user buffer", __func__);
2012 ret = -EFAULT;
2013 goto exit;
2014 }
2015 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002016#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05302017#ifdef WLAN_FEATURE_PACKET_FILTERING
2018 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
2019 {
2020 tANI_U8 filterType = 0;
2021 tANI_U8 *value = command;
2022
2023 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
2024 value = value + 22;
2025
2026 /* Convert the value from ascii to integer */
2027 ret = kstrtou8(value, 10, &filterType);
2028 if (ret < 0)
2029 {
2030 /* If the input value is greater than max value of datatype,
2031 * then also kstrtou8 fails
2032 */
2033 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2034 "%s: kstrtou8 failed range ", __func__);
2035 ret = -EINVAL;
2036 goto exit;
2037 }
2038
2039 if (filterType != 0 && filterType != 1)
2040 {
2041 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2042 "%s: Accepted Values are 0 and 1 ", __func__);
2043 ret = -EINVAL;
2044 goto exit;
2045 }
2046 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
2047 pAdapter->sessionId);
2048 }
2049#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05302050 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
2051 {
2052 char *dhcpPhase;
2053 dhcpPhase = command + 12;
2054 if ('1' == *dhcpPhase)
2055 {
2056 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
2057 pAdapter->macAddressCurrent.bytes);
2058 }
2059 else if ('2' == *dhcpPhase)
2060 {
2061 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
2062 pAdapter->macAddressCurrent.bytes);
2063 }
2064 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07002065 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
2066 {
2067 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
2068 }
2069 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
2070 {
2071 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
2072 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05302073 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2074 {
2075 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
2076 char extra[32];
2077 tANI_U8 len = 0;
2078
2079 len = snprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
2080 (int)pCfg->nActiveMaxChnTime);
2081 if (copy_to_user(priv_data.buf, &extra, len + 1))
2082 {
2083 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2084 "%s: failed to copy data to user buffer", __func__);
2085 ret = -EFAULT;
2086 goto exit;
2087 }
2088 ret = len;
2089 }
2090 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2091 {
2092 tANI_U8 *value = command;
2093 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
2094 int val = 0, temp;
2095
2096 value = value + 13;
2097 temp = kstrtou32(value, 10, &val);
2098 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2099 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2100 {
2101 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2102 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2103 ret = -EFAULT;
2104 goto exit;
2105 }
2106 pCfg->nActiveMaxChnTime = val;
2107 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002108 else {
2109 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2110 __func__, command);
2111 }
2112
Jeff Johnson295189b2012-06-20 16:38:30 -07002113 }
2114exit:
2115 if (command)
2116 {
2117 kfree(command);
2118 }
2119 return ret;
2120}
2121
Srinivas Girigowdade697412013-02-14 16:31:48 -08002122#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2123void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2124{
2125 eCsrBand band = -1;
2126 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2127 switch (band)
2128 {
2129 case eCSR_BAND_ALL:
2130 *pBand = WLAN_HDD_UI_BAND_AUTO;
2131 break;
2132
2133 case eCSR_BAND_24:
2134 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2135 break;
2136
2137 case eCSR_BAND_5G:
2138 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2139 break;
2140
2141 default:
2142 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2143 *pBand = -1;
2144 break;
2145 }
2146}
2147
2148/**---------------------------------------------------------------------------
2149
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002150 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2151
2152 This function parses the send action frame data passed in the format
2153 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2154
2155 \param - pValue Pointer to input country code revision
2156 \param - pTargetApBssid Pointer to target Ap bssid
2157 \param - pChannel Pointer to the Target AP channel
2158 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2159 \param - pBuf Pointer to data
2160 \param - pBufLen Pointer to data length
2161
2162 \return - 0 for success non-zero for failure
2163
2164 --------------------------------------------------------------------------*/
2165VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2166 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2167{
2168 tANI_U8 *inPtr = pValue;
2169 tANI_U8 *dataEnd;
2170 int tempInt;
2171 int j = 0;
2172 int i = 0;
2173 int v = 0;
2174 tANI_U8 tempBuf[32];
2175 tANI_U8 tempByte = 0;
2176
2177 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2178 /*no argument after the command*/
2179 if (NULL == inPtr)
2180 {
2181 return -EINVAL;
2182 }
2183
2184 /*no space after the command*/
2185 else if (SPACE_ASCII_VALUE != *inPtr)
2186 {
2187 return -EINVAL;
2188 }
2189
2190 /*removing empty spaces*/
2191 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2192
2193 /*no argument followed by spaces*/
2194 if ('\0' == *inPtr)
2195 {
2196 return -EINVAL;
2197 }
2198
2199 /*getting the first argument ie the target AP bssid */
2200 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2201 {
2202 return -EINVAL;
2203 }
2204 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2205 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2206 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2207
2208 /* point to the next argument */
2209 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2210 /*no argument after the command*/
2211 if (NULL == inPtr) return -EINVAL;
2212
2213 /*removing empty spaces*/
2214 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2215
2216 /*no argument followed by spaces*/
2217 if ('\0' == *inPtr)
2218 {
2219 return -EINVAL;
2220 }
2221
2222 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002223 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002224 v = kstrtos32(tempBuf, 10, &tempInt);
2225 if ( v < 0) return -EINVAL;
2226
2227 *pChannel = tempInt;
2228
2229 /* point to the next argument */
2230 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2231 /*no argument after the command*/
2232 if (NULL == inPtr) return -EINVAL;
2233 /*removing empty spaces*/
2234 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2235
2236 /*no argument followed by spaces*/
2237 if ('\0' == *inPtr)
2238 {
2239 return -EINVAL;
2240 }
2241
2242 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002243 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002244 v = kstrtos32(tempBuf, 10, &tempInt);
2245 if ( v < 0) return -EINVAL;
2246
2247 *pDwellTime = tempInt;
2248
2249 /* point to the next argument */
2250 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2251 /*no argument after the command*/
2252 if (NULL == inPtr) return -EINVAL;
2253 /*removing empty spaces*/
2254 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2255
2256 /*no argument followed by spaces*/
2257 if ('\0' == *inPtr)
2258 {
2259 return -EINVAL;
2260 }
2261
2262 /* find the length of data */
2263 dataEnd = inPtr;
2264 while(('\0' != *dataEnd) )
2265 {
2266 dataEnd++;
2267 ++(*pBufLen);
2268 }
2269 if ( *pBufLen <= 0) return -EINVAL;
2270
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002271 /* Allocate the number of bytes based on the number of input characters
2272 whether it is even or odd.
2273 if the number of input characters are even, then we need N/2 byte.
2274 if the number of input characters are odd, then we need do (N+1)/2 to
2275 compensate rounding off.
2276 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2277 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2278 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002279 if (NULL == *pBuf)
2280 {
2281 hddLog(VOS_TRACE_LEVEL_FATAL,
2282 "%s: vos_mem_alloc failed ", __func__);
2283 return -EINVAL;
2284 }
2285
2286 /* the buffer received from the upper layer is character buffer,
2287 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2288 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2289 and f0 in 3rd location */
2290 for (i = 0, j = 0; j < *pBufLen; j += 2)
2291 {
2292 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2293 (*pBuf)[i++] = tempByte;
2294 }
2295 *pBufLen = i;
2296 return VOS_STATUS_SUCCESS;
2297}
2298
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002299/**---------------------------------------------------------------------------
2300
Srinivas Girigowdade697412013-02-14 16:31:48 -08002301 \brief hdd_parse_countryrev() - HDD Parse country code revision
2302
2303 This function parses the country code revision passed in the format
2304 SETCOUNTRYREV<space><Country code><space>revision
2305
2306 \param - pValue Pointer to input country code revision
2307 \param - pCountryCode Pointer to local output array to record country code
2308 \param - pRevision Pointer to store revision integer number
2309
2310 \return - 0 for success non-zero for failure
2311
2312 --------------------------------------------------------------------------*/
2313VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
2314{
2315 tANI_U8 *inPtr = pValue;
2316 int tempInt;
2317
2318 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2319 /*no argument after the command*/
2320 if (NULL == inPtr)
2321 {
2322 return -EINVAL;
2323 }
2324
2325 /*no space after the command*/
2326 else if (SPACE_ASCII_VALUE != *inPtr)
2327 {
2328 return -EINVAL;
2329 }
2330
2331 /*removing empty spaces*/
2332 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
2333
2334 /*no argument followed by spaces*/
2335 if ('\0' == *inPtr)
2336 {
2337 return -EINVAL;
2338 }
2339
2340 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07002341 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002342
2343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2344 "Country code is : %s", pCountryCode);
2345
2346 /*inPtr pointing to the beginning of first space after country code */
2347 inPtr = strpbrk( inPtr, " " );
2348 /*no revision number after the country code argument */
2349 if (NULL == inPtr)
2350 {
2351 return -EINVAL;
2352 }
2353
2354 inPtr++;
2355
2356 /*removing empty space*/
2357 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2358
2359 /*no channel list after the number of channels argument and spaces*/
2360 if (0 == strncmp(pCountryCode, "KR", 2))
2361 {
2362 if ('\0' == *inPtr)
2363 {
2364 return -EINVAL;
2365 }
2366
2367 sscanf(inPtr, "%d", &tempInt);
2368 *pRevision = tempInt;
2369 }
2370 else
2371 {
2372 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2373 "Revision input is required only for Country KR");
2374 return -EINVAL;
2375 }
2376 return VOS_STATUS_SUCCESS;
2377}
2378
2379/**---------------------------------------------------------------------------
2380
2381 \brief hdd_parse_channellist() - HDD Parse channel list
2382
2383 This function parses the channel list passed in the format
2384 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002385 if the Number of channels (N) does not match with the actual number of channels passed
2386 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2387 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2388 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2389 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002390
2391 \param - pValue Pointer to input channel list
2392 \param - ChannelList Pointer to local output array to record channel list
2393 \param - pNumChannels Pointer to number of roam scan channels
2394
2395 \return - 0 for success non-zero for failure
2396
2397 --------------------------------------------------------------------------*/
2398VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2399{
2400 tANI_U8 *inPtr = pValue;
2401 int tempInt;
2402 int j = 0;
2403 int v = 0;
2404 char buf[32];
2405
2406 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2407 /*no argument after the command*/
2408 if (NULL == inPtr)
2409 {
2410 return -EINVAL;
2411 }
2412
2413 /*no space after the command*/
2414 else if (SPACE_ASCII_VALUE != *inPtr)
2415 {
2416 return -EINVAL;
2417 }
2418
2419 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002420 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002421
2422 /*no argument followed by spaces*/
2423 if ('\0' == *inPtr)
2424 {
2425 return -EINVAL;
2426 }
2427
2428 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002429 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002430 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002431 if ((v < 0) ||
2432 (tempInt <= 0) ||
2433 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2434 {
2435 return -EINVAL;
2436 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002437
2438 *pNumChannels = tempInt;
2439
2440 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2441 "Number of channels are: %d", *pNumChannels);
2442
2443 for (j = 0; j < (*pNumChannels); j++)
2444 {
2445 /*inPtr pointing to the beginning of first space after number of channels*/
2446 inPtr = strpbrk( inPtr, " " );
2447 /*no channel list after the number of channels argument*/
2448 if (NULL == inPtr)
2449 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002450 if (0 != j)
2451 {
2452 *pNumChannels = j;
2453 return VOS_STATUS_SUCCESS;
2454 }
2455 else
2456 {
2457 return -EINVAL;
2458 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002459 }
2460
2461 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002462 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002463
2464 /*no channel list after the number of channels argument and spaces*/
2465 if ( '\0' == *inPtr )
2466 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002467 if (0 != j)
2468 {
2469 *pNumChannels = j;
2470 return VOS_STATUS_SUCCESS;
2471 }
2472 else
2473 {
2474 return -EINVAL;
2475 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002476 }
2477
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002478 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002479 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002480 if ((v < 0) ||
2481 (tempInt <= 0) ||
2482 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2483 {
2484 return -EINVAL;
2485 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002486 pChannelList[j] = tempInt;
2487
2488 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2489 "Channel %d added to preferred channel list",
2490 pChannelList[j] );
2491 }
2492
Srinivas Girigowdade697412013-02-14 16:31:48 -08002493 return VOS_STATUS_SUCCESS;
2494}
2495
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002496
2497/**---------------------------------------------------------------------------
2498
2499 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2500
2501 This function parses the reasoc command data passed in the format
2502 REASSOC<space><bssid><space><channel>
2503
2504 \param - pValue Pointer to input country code revision
2505 \param - pTargetApBssid Pointer to target Ap bssid
2506 \param - pChannel Pointer to the Target AP channel
2507
2508 \return - 0 for success non-zero for failure
2509
2510 --------------------------------------------------------------------------*/
2511VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2512{
2513 tANI_U8 *inPtr = pValue;
2514 int tempInt;
2515 int v = 0;
2516 tANI_U8 tempBuf[32];
2517
2518 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2519 /*no argument after the command*/
2520 if (NULL == inPtr)
2521 {
2522 return -EINVAL;
2523 }
2524
2525 /*no space after the command*/
2526 else if (SPACE_ASCII_VALUE != *inPtr)
2527 {
2528 return -EINVAL;
2529 }
2530
2531 /*removing empty spaces*/
2532 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2533
2534 /*no argument followed by spaces*/
2535 if ('\0' == *inPtr)
2536 {
2537 return -EINVAL;
2538 }
2539
2540 /*getting the first argument ie the target AP bssid */
2541 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2542 {
2543 return -EINVAL;
2544 }
2545 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2546 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2547 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2548
2549 /* point to the next argument */
2550 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2551 /*no argument after the command*/
2552 if (NULL == inPtr) return -EINVAL;
2553
2554 /*removing empty spaces*/
2555 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2556
2557 /*no argument followed by spaces*/
2558 if ('\0' == *inPtr)
2559 {
2560 return -EINVAL;
2561 }
2562
2563 /*getting the next argument ie the channel number */
2564 sscanf(inPtr, "%s ", tempBuf);
2565 v = kstrtos32(tempBuf, 10, &tempInt);
2566 if ( v < 0) return -EINVAL;
2567
2568 *pChannel = tempInt;
2569 return VOS_STATUS_SUCCESS;
2570}
2571
2572#endif
2573
Jeff Johnson295189b2012-06-20 16:38:30 -07002574/**---------------------------------------------------------------------------
2575
2576 \brief hdd_open() - HDD Open function
2577
2578 This is called in response to ifconfig up
2579
2580 \param - dev Pointer to net_device structure
2581
2582 \return - 0 for success non-zero for failure
2583
2584 --------------------------------------------------------------------------*/
2585int hdd_open (struct net_device *dev)
2586{
2587 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2588 hdd_context_t *pHddCtx;
2589 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2590 VOS_STATUS status;
2591 v_BOOL_t in_standby = TRUE;
2592
2593 if (NULL == pAdapter)
2594 {
2595 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002596 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002597 return -ENODEV;
2598 }
2599
2600 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2601 if (NULL == pHddCtx)
2602 {
2603 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002604 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002605 return -ENODEV;
2606 }
2607
2608 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2609 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2610 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002611 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2612 {
2613 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302614 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002615 in_standby = FALSE;
2616 break;
2617 }
2618 else
2619 {
2620 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2621 pAdapterNode = pNext;
2622 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002623 }
2624
2625 if (TRUE == in_standby)
2626 {
2627 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2628 {
2629 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2630 "wlan out of power save", __func__);
2631 return -EINVAL;
2632 }
2633 }
2634
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002635 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002636 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2637 {
2638 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002639 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002640 /* Enable TX queues only when we are connected */
2641 netif_tx_start_all_queues(dev);
2642 }
2643
2644 return 0;
2645}
2646
2647int hdd_mon_open (struct net_device *dev)
2648{
2649 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2650
2651 if(pAdapter == NULL) {
2652 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002653 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002654 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002655 }
2656
2657 netif_start_queue(dev);
2658
2659 return 0;
2660}
2661/**---------------------------------------------------------------------------
2662
2663 \brief hdd_stop() - HDD stop function
2664
2665 This is called in response to ifconfig down
2666
2667 \param - dev Pointer to net_device structure
2668
2669 \return - 0 for success non-zero for failure
2670
2671 --------------------------------------------------------------------------*/
2672
2673int hdd_stop (struct net_device *dev)
2674{
2675 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2676 hdd_context_t *pHddCtx;
2677 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2678 VOS_STATUS status;
2679 v_BOOL_t enter_standby = TRUE;
2680
2681 ENTER();
2682
2683 if (NULL == pAdapter)
2684 {
2685 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002686 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002687 return -ENODEV;
2688 }
2689
2690 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2691 if (NULL == pHddCtx)
2692 {
2693 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002694 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002695 return -ENODEV;
2696 }
2697
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002698 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002699 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2700 netif_tx_disable(pAdapter->dev);
2701 netif_carrier_off(pAdapter->dev);
2702
2703
2704 /* SoftAP ifaces should never go in power save mode
2705 making sure same here. */
2706 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2707 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002708 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002709 )
2710 {
2711 /* SoftAP mode, so return from here */
2712 EXIT();
2713 return 0;
2714 }
2715
2716 /* Find if any iface is up then
2717 if any iface is up then can't put device to sleep/ power save mode. */
2718 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2719 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2720 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002721 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2722 {
2723 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302724 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002725 enter_standby = FALSE;
2726 break;
2727 }
2728 else
2729 {
2730 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2731 pAdapterNode = pNext;
2732 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002733 }
2734
2735 if (TRUE == enter_standby)
2736 {
2737 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2738 "entering standby", __func__);
2739 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2740 {
2741 /*log and return success*/
2742 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2743 "wlan in power save", __func__);
2744 }
2745 }
2746
2747 EXIT();
2748 return 0;
2749}
2750
2751/**---------------------------------------------------------------------------
2752
2753 \brief hdd_uninit() - HDD uninit function
2754
2755 This is called during the netdev unregister to uninitialize all data
2756associated with the device
2757
2758 \param - dev Pointer to net_device structure
2759
2760 \return - void
2761
2762 --------------------------------------------------------------------------*/
2763static void hdd_uninit (struct net_device *dev)
2764{
2765 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2766
2767 ENTER();
2768
2769 do
2770 {
2771 if (NULL == pAdapter)
2772 {
2773 hddLog(VOS_TRACE_LEVEL_FATAL,
2774 "%s: NULL pAdapter", __func__);
2775 break;
2776 }
2777
2778 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2779 {
2780 hddLog(VOS_TRACE_LEVEL_FATAL,
2781 "%s: Invalid magic", __func__);
2782 break;
2783 }
2784
2785 if (NULL == pAdapter->pHddCtx)
2786 {
2787 hddLog(VOS_TRACE_LEVEL_FATAL,
2788 "%s: NULL pHddCtx", __func__);
2789 break;
2790 }
2791
2792 if (dev != pAdapter->dev)
2793 {
2794 hddLog(VOS_TRACE_LEVEL_FATAL,
2795 "%s: Invalid device reference", __func__);
2796 /* we haven't validated all cases so let this go for now */
2797 }
2798
2799 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2800
2801 /* after uninit our adapter structure will no longer be valid */
2802 pAdapter->dev = NULL;
2803 pAdapter->magic = 0;
2804 } while (0);
2805
2806 EXIT();
2807}
2808
2809/**---------------------------------------------------------------------------
2810
2811 \brief hdd_release_firmware() -
2812
2813 This function calls the release firmware API to free the firmware buffer.
2814
2815 \param - pFileName Pointer to the File Name.
2816 pCtx - Pointer to the adapter .
2817
2818
2819 \return - 0 for success, non zero for failure
2820
2821 --------------------------------------------------------------------------*/
2822
2823VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2824{
2825 VOS_STATUS status = VOS_STATUS_SUCCESS;
2826 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2827 ENTER();
2828
2829
2830 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2831
2832 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2833
2834 if(pHddCtx->fw) {
2835 release_firmware(pHddCtx->fw);
2836 pHddCtx->fw = NULL;
2837 }
2838 else
2839 status = VOS_STATUS_E_FAILURE;
2840 }
2841 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2842 if(pHddCtx->nv) {
2843 release_firmware(pHddCtx->nv);
2844 pHddCtx->nv = NULL;
2845 }
2846 else
2847 status = VOS_STATUS_E_FAILURE;
2848
2849 }
2850
2851 EXIT();
2852 return status;
2853}
2854
2855/**---------------------------------------------------------------------------
2856
2857 \brief hdd_request_firmware() -
2858
2859 This function reads the firmware file using the request firmware
2860 API and returns the the firmware data and the firmware file size.
2861
2862 \param - pfileName - Pointer to the file name.
2863 - pCtx - Pointer to the adapter .
2864 - ppfw_data - Pointer to the pointer of the firmware data.
2865 - pSize - Pointer to the file size.
2866
2867 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2868
2869 --------------------------------------------------------------------------*/
2870
2871
2872VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2873{
2874 int status;
2875 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2876 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2877 ENTER();
2878
2879 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2880
2881 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2882
2883 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2884 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2885 __func__, pfileName);
2886 retval = VOS_STATUS_E_FAILURE;
2887 }
2888
2889 else {
2890 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2891 *pSize = pHddCtx->fw->size;
2892 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2893 __func__, *pSize);
2894 }
2895 }
2896 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2897
2898 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2899
2900 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2901 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2902 __func__, pfileName);
2903 retval = VOS_STATUS_E_FAILURE;
2904 }
2905
2906 else {
2907 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2908 *pSize = pHddCtx->nv->size;
2909 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2910 __func__, *pSize);
2911 }
2912 }
2913
2914 EXIT();
2915 return retval;
2916}
2917/**---------------------------------------------------------------------------
2918 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2919
2920 This is the function invoked by SME to inform the result of a full power
2921 request issued by HDD
2922
2923 \param - callbackcontext - Pointer to cookie
2924 status - result of request
2925
2926 \return - None
2927
2928--------------------------------------------------------------------------*/
2929void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2930{
2931 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2932
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002933 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002934 if(&pHddCtx->full_pwr_comp_var)
2935 {
2936 complete(&pHddCtx->full_pwr_comp_var);
2937 }
2938}
2939
2940/**---------------------------------------------------------------------------
2941
2942 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2943
2944 This is the function invoked by SME to inform the result of BMPS
2945 request issued by HDD
2946
2947 \param - callbackcontext - Pointer to cookie
2948 status - result of request
2949
2950 \return - None
2951
2952--------------------------------------------------------------------------*/
2953void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2954{
2955
2956 struct completion *completion_var = (struct completion*) callbackContext;
2957
2958 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2959 if(completion_var != NULL)
2960 {
2961 complete(completion_var);
2962 }
2963}
2964
2965/**---------------------------------------------------------------------------
2966
2967 \brief hdd_get_cfg_file_size() -
2968
2969 This function reads the configuration file using the request firmware
2970 API and returns the configuration file size.
2971
2972 \param - pCtx - Pointer to the adapter .
2973 - pFileName - Pointer to the file name.
2974 - pBufSize - Pointer to the buffer size.
2975
2976 \return - 0 for success, non zero for failure
2977
2978 --------------------------------------------------------------------------*/
2979
2980VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2981{
2982 int status;
2983 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2984
2985 ENTER();
2986
2987 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2988
2989 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2990 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2991 status = VOS_STATUS_E_FAILURE;
2992 }
2993 else {
2994 *pBufSize = pHddCtx->fw->size;
2995 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2996 release_firmware(pHddCtx->fw);
2997 pHddCtx->fw = NULL;
2998 }
2999
3000 EXIT();
3001 return VOS_STATUS_SUCCESS;
3002}
3003
3004/**---------------------------------------------------------------------------
3005
3006 \brief hdd_read_cfg_file() -
3007
3008 This function reads the configuration file using the request firmware
3009 API and returns the cfg data and the buffer size of the configuration file.
3010
3011 \param - pCtx - Pointer to the adapter .
3012 - pFileName - Pointer to the file name.
3013 - pBuffer - Pointer to the data buffer.
3014 - pBufSize - Pointer to the buffer size.
3015
3016 \return - 0 for success, non zero for failure
3017
3018 --------------------------------------------------------------------------*/
3019
3020VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
3021 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
3022{
3023 int status;
3024 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
3025
3026 ENTER();
3027
3028 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
3029
3030 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
3031 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
3032 return VOS_STATUS_E_FAILURE;
3033 }
3034 else {
3035 if(*pBufSize != pHddCtx->fw->size) {
3036 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
3037 "file size", __func__);
3038 release_firmware(pHddCtx->fw);
3039 pHddCtx->fw = NULL;
3040 return VOS_STATUS_E_FAILURE;
3041 }
3042 else {
3043 if(pBuffer) {
3044 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
3045 }
3046 release_firmware(pHddCtx->fw);
3047 pHddCtx->fw = NULL;
3048 }
3049 }
3050
3051 EXIT();
3052
3053 return VOS_STATUS_SUCCESS;
3054}
3055
3056/**---------------------------------------------------------------------------
3057
Jeff Johnson295189b2012-06-20 16:38:30 -07003058 \brief hdd_set_mac_address() -
3059
3060 This function sets the user specified mac address using
3061 the command ifconfig wlanX hw ether <mac adress>.
3062
3063 \param - dev - Pointer to the net device.
3064 - addr - Pointer to the sockaddr.
3065 \return - 0 for success, non zero for failure
3066
3067 --------------------------------------------------------------------------*/
3068
3069static int hdd_set_mac_address(struct net_device *dev, void *addr)
3070{
3071 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3072 struct sockaddr *psta_mac_addr = addr;
3073 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3074
3075 ENTER();
3076
3077 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
3078
3079#ifdef HDD_SESSIONIZE
3080 // set the MAC address though the STA ID CFG.
3081 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
3082 (v_U8_t *)&pAdapter->macAddressCurrent,
3083 sizeof( pAdapter->macAddressCurrent ),
3084 hdd_set_mac_addr_cb, VOS_FALSE );
3085#endif
3086
3087 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
3088
3089 EXIT();
3090 return halStatus;
3091}
3092
3093tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
3094{
3095 int i;
3096 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3097 {
3098 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
3099 break;
3100 }
3101
3102 if( VOS_MAX_CONCURRENCY_PERSONA == i)
3103 return NULL;
3104
3105 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
3106 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
3107}
3108
3109void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
3110{
3111 int i;
3112 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3113 {
3114 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
3115 {
3116 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
3117 break;
3118 }
3119 }
3120 return;
3121}
3122
3123#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3124 static struct net_device_ops wlan_drv_ops = {
3125 .ndo_open = hdd_open,
3126 .ndo_stop = hdd_stop,
3127 .ndo_uninit = hdd_uninit,
3128 .ndo_start_xmit = hdd_hard_start_xmit,
3129 .ndo_tx_timeout = hdd_tx_timeout,
3130 .ndo_get_stats = hdd_stats,
3131 .ndo_do_ioctl = hdd_ioctl,
3132 .ndo_set_mac_address = hdd_set_mac_address,
3133 .ndo_select_queue = hdd_select_queue,
3134#ifdef WLAN_FEATURE_PACKET_FILTERING
3135#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3136 .ndo_set_rx_mode = hdd_set_multicast_list,
3137#else
3138 .ndo_set_multicast_list = hdd_set_multicast_list,
3139#endif //LINUX_VERSION_CODE
3140#endif
3141 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003142 static struct net_device_ops wlan_mon_drv_ops = {
3143 .ndo_open = hdd_mon_open,
3144 .ndo_stop = hdd_stop,
3145 .ndo_uninit = hdd_uninit,
3146 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3147 .ndo_tx_timeout = hdd_tx_timeout,
3148 .ndo_get_stats = hdd_stats,
3149 .ndo_do_ioctl = hdd_ioctl,
3150 .ndo_set_mac_address = hdd_set_mac_address,
3151 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003152
3153#endif
3154
3155void hdd_set_station_ops( struct net_device *pWlanDev )
3156{
3157#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3158 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3159 pWlanDev->netdev_ops = &wlan_drv_ops;
3160#else
3161 pWlanDev->open = hdd_open;
3162 pWlanDev->stop = hdd_stop;
3163 pWlanDev->uninit = hdd_uninit;
3164 pWlanDev->hard_start_xmit = NULL;
3165 pWlanDev->tx_timeout = hdd_tx_timeout;
3166 pWlanDev->get_stats = hdd_stats;
3167 pWlanDev->do_ioctl = hdd_ioctl;
3168 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3169 pWlanDev->set_mac_address = hdd_set_mac_address;
3170#endif
3171}
3172
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003173static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003174{
3175 struct net_device *pWlanDev = NULL;
3176 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003177 /*
3178 * cfg80211 initialization and registration....
3179 */
3180 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3181
Jeff Johnson295189b2012-06-20 16:38:30 -07003182 if(pWlanDev != NULL)
3183 {
3184
3185 //Save the pointer to the net_device in the HDD adapter
3186 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3187
Jeff Johnson295189b2012-06-20 16:38:30 -07003188 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3189
3190 pAdapter->dev = pWlanDev;
3191 pAdapter->pHddCtx = pHddCtx;
3192 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3193
3194 init_completion(&pAdapter->session_open_comp_var);
3195 init_completion(&pAdapter->session_close_comp_var);
3196 init_completion(&pAdapter->disconnect_comp_var);
3197 init_completion(&pAdapter->linkup_event_var);
3198 init_completion(&pAdapter->cancel_rem_on_chan_var);
3199 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003200#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3201 init_completion(&pAdapter->offchannel_tx_event);
3202#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003203 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003204#ifdef FEATURE_WLAN_TDLS
3205 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003206 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003207 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303208 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003209#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003210 init_completion(&pHddCtx->mc_sus_event_var);
3211 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303212 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003213 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003214
Jeff Johnson295189b2012-06-20 16:38:30 -07003215 pAdapter->isLinkUpSvcNeeded = FALSE;
3216 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3217 //Init the net_device structure
3218 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3219
3220 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3221 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3222 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3223 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3224
3225 hdd_set_station_ops( pAdapter->dev );
3226
3227 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003228 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3229 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3230 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003231 /* set pWlanDev's parent to underlying device */
3232 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3233 }
3234
3235 return pAdapter;
3236}
3237
3238VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3239{
3240 struct net_device *pWlanDev = pAdapter->dev;
3241 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3242 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3243 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3244
3245 if( rtnl_lock_held )
3246 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003247 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003248 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3249 {
3250 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3251 return VOS_STATUS_E_FAILURE;
3252 }
3253 }
3254 if (register_netdevice(pWlanDev))
3255 {
3256 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3257 return VOS_STATUS_E_FAILURE;
3258 }
3259 }
3260 else
3261 {
3262 if(register_netdev(pWlanDev))
3263 {
3264 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3265 return VOS_STATUS_E_FAILURE;
3266 }
3267 }
3268 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3269
3270 return VOS_STATUS_SUCCESS;
3271}
3272
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003273static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003274{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003275 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003276
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003277 if (NULL == pAdapter)
3278 {
3279 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3280 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003281 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003282
3283 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3284 {
3285 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3286 return eHAL_STATUS_NOT_INITIALIZED;
3287 }
3288
3289 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3290
3291 /* need to make sure all of our scheduled work has completed.
3292 * This callback is called from MC thread context, so it is safe to
3293 * to call below flush workqueue API from here.
3294 */
3295 flush_scheduled_work();
3296
3297 /* We can be blocked while waiting for scheduled work to be
3298 * flushed, and the adapter structure can potentially be freed, in
3299 * which case the magic will have been reset. So make sure the
3300 * magic is still good, and hence the adapter structure is still
3301 * valid, before signaling completion */
3302 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3303 {
3304 complete(&pAdapter->session_close_comp_var);
3305 }
3306
Jeff Johnson295189b2012-06-20 16:38:30 -07003307 return eHAL_STATUS_SUCCESS;
3308}
3309
3310VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3311{
3312 struct net_device *pWlanDev = pAdapter->dev;
3313 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3314 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3315 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3316 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3317 int rc = 0;
3318
3319 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003320 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003321 //Open a SME session for future operation
3322 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003323 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003324 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3325 {
3326 hddLog(VOS_TRACE_LEVEL_FATAL,
3327 "sme_OpenSession() failed with status code %08d [x%08lx]",
3328 halStatus, halStatus );
3329 status = VOS_STATUS_E_FAILURE;
3330 goto error_sme_open;
3331 }
3332
3333 //Block on a completion variable. Can't wait forever though.
3334 rc = wait_for_completion_interruptible_timeout(
3335 &pAdapter->session_open_comp_var,
3336 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3337 if (!rc)
3338 {
3339 hddLog(VOS_TRACE_LEVEL_FATAL,
3340 "Session is not opened within timeout period code %08d", rc );
3341 status = VOS_STATUS_E_FAILURE;
3342 goto error_sme_open;
3343 }
3344
3345 // Register wireless extensions
3346 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3347 {
3348 hddLog(VOS_TRACE_LEVEL_FATAL,
3349 "hdd_register_wext() failed with status code %08d [x%08lx]",
3350 halStatus, halStatus );
3351 status = VOS_STATUS_E_FAILURE;
3352 goto error_register_wext;
3353 }
3354 //Safe to register the hard_start_xmit function again
3355#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3356 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3357#else
3358 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3359#endif
3360
3361 //Set the Connection State to Not Connected
3362 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3363
3364 //Set the default operation channel
3365 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3366
3367 /* Make the default Auth Type as OPEN*/
3368 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3369
3370 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3371 {
3372 hddLog(VOS_TRACE_LEVEL_FATAL,
3373 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3374 status, status );
3375 goto error_init_txrx;
3376 }
3377
3378 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3379
3380 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3381 {
3382 hddLog(VOS_TRACE_LEVEL_FATAL,
3383 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3384 status, status );
3385 goto error_wmm_init;
3386 }
3387
3388 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3389
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003390#ifdef FEATURE_WLAN_TDLS
3391 if(0 != wlan_hdd_tdls_init(pAdapter))
3392 {
3393 status = VOS_STATUS_E_FAILURE;
3394 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3395 goto error_tdls_init;
3396 }
3397 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3398#endif
3399
Jeff Johnson295189b2012-06-20 16:38:30 -07003400 return VOS_STATUS_SUCCESS;
3401
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003402#ifdef FEATURE_WLAN_TDLS
3403error_tdls_init:
3404 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3405 hdd_wmm_adapter_close(pAdapter);
3406#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003407error_wmm_init:
3408 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3409 hdd_deinit_tx_rx(pAdapter);
3410error_init_txrx:
3411 hdd_UnregisterWext(pWlanDev);
3412error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003413 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003414 {
3415 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003416 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003417 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003418 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003419 {
3420 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003421 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003422 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003423 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003424 }
3425}
3426error_sme_open:
3427 return status;
3428}
3429
Jeff Johnson295189b2012-06-20 16:38:30 -07003430void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3431{
3432 hdd_cfg80211_state_t *cfgState;
3433
3434 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3435
3436 if( NULL != cfgState->buf )
3437 {
3438 int rc;
3439 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3440 rc = wait_for_completion_interruptible_timeout(
3441 &pAdapter->tx_action_cnf_event,
3442 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3443 if(!rc)
3444 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003445 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003446 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3447 }
3448 }
3449 return;
3450}
Jeff Johnson295189b2012-06-20 16:38:30 -07003451
3452void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3453{
3454 ENTER();
3455 switch ( pAdapter->device_mode )
3456 {
3457 case WLAN_HDD_INFRA_STATION:
3458 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003459 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003460 {
3461 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3462 {
3463 hdd_deinit_tx_rx( pAdapter );
3464 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3465 }
3466
3467 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3468 {
3469 hdd_wmm_adapter_close( pAdapter );
3470 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3471 }
3472
Jeff Johnson295189b2012-06-20 16:38:30 -07003473 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003474#ifdef FEATURE_WLAN_TDLS
3475 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3476 {
3477 wlan_hdd_tdls_exit(pAdapter);
3478 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3479 }
3480#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003481
3482 break;
3483 }
3484
3485 case WLAN_HDD_SOFTAP:
3486 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003487 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003488 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003489
3490 hdd_unregister_hostapd(pAdapter);
3491 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003492 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003493 break;
3494 }
3495
3496 case WLAN_HDD_MONITOR:
3497 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003498 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003499 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3500 {
3501 hdd_deinit_tx_rx( pAdapter );
3502 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3503 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003504 if(NULL != pAdapterforTx)
3505 {
3506 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3507 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003508 break;
3509 }
3510
3511
3512 default:
3513 break;
3514 }
3515
3516 EXIT();
3517}
3518
3519void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3520{
3521 struct net_device *pWlanDev = pAdapter->dev;
3522
3523 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3524 if( rtnl_held )
3525 {
3526 unregister_netdevice(pWlanDev);
3527 }
3528 else
3529 {
3530 unregister_netdev(pWlanDev);
3531 }
3532 // note that the pAdapter is no longer valid at this point
3533 // since the memory has been reclaimed
3534 }
3535
3536}
3537
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003538void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3539{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303540 VOS_STATUS status;
3541 hdd_adapter_t *pAdapter = NULL;
3542 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003543
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303544 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003545
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303546 /*loop through all adapters.*/
3547 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003548 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303549 pAdapter = pAdapterNode->pAdapter;
3550 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3551 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003552
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303553 { // we skip this registration for modes other than STA and P2P client modes.
3554 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3555 pAdapterNode = pNext;
3556 continue;
3557 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003558
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303559 //Apply Dynamic DTIM For P2P
3560 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3561 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3562 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3563 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3564 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3565 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3566 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3567 (eConnectionState_Associated ==
3568 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3569 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3570 {
3571 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003572
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303573 powerRequest.uIgnoreDTIM = 1;
3574 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3575
3576 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3577 {
3578 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3579 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3580 }
3581 else
3582 {
3583 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3584 }
3585
3586 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3587 * specified during Enter/Exit BMPS when LCD off*/
3588 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3589 NULL, eANI_BOOLEAN_FALSE);
3590 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3591 NULL, eANI_BOOLEAN_FALSE);
3592
3593 /* switch to the DTIM specified in cfg.ini */
3594 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3595 "Switch to DTIM %d", powerRequest.uListenInterval);
3596 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3597 break;
3598
3599 }
3600
3601 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3602 pAdapterNode = pNext;
3603 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003604}
3605
3606void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3607{
3608 /*Switch back to DTIM 1*/
3609 tSirSetPowerParamsReq powerRequest = { 0 };
3610
3611 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3612 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003613 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003614
3615 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3616 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3617 NULL, eANI_BOOLEAN_FALSE);
3618 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3619 NULL, eANI_BOOLEAN_FALSE);
3620
3621 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3622 "Switch to DTIM%d",powerRequest.uListenInterval);
3623 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3624
3625}
3626
Jeff Johnson295189b2012-06-20 16:38:30 -07003627VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3628{
3629 VOS_STATUS status = VOS_STATUS_SUCCESS;
3630
3631 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3632 {
3633 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3634 }
3635
3636 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3637 {
3638 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3639 }
3640
3641 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3642 {
3643 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3644 }
3645
3646 return status;
3647}
3648
3649VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3650{
3651 hdd_adapter_t *pAdapter = NULL;
3652 eHalStatus halStatus;
3653 VOS_STATUS status = VOS_STATUS_E_INVAL;
3654 v_BOOL_t disableBmps = FALSE;
3655 v_BOOL_t disableImps = FALSE;
3656
3657 switch(session_type)
3658 {
3659 case WLAN_HDD_INFRA_STATION:
3660 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003661 case WLAN_HDD_P2P_CLIENT:
3662 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003663 //Exit BMPS -> Is Sta/P2P Client is already connected
3664 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3665 if((NULL != pAdapter)&&
3666 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3667 {
3668 disableBmps = TRUE;
3669 }
3670
3671 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3672 if((NULL != pAdapter)&&
3673 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3674 {
3675 disableBmps = TRUE;
3676 }
3677
3678 //Exit both Bmps and Imps incase of Go/SAP Mode
3679 if((WLAN_HDD_SOFTAP == session_type) ||
3680 (WLAN_HDD_P2P_GO == session_type))
3681 {
3682 disableBmps = TRUE;
3683 disableImps = TRUE;
3684 }
3685
3686 if(TRUE == disableImps)
3687 {
3688 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3689 {
3690 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3691 }
3692 }
3693
3694 if(TRUE == disableBmps)
3695 {
3696 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3697 {
3698 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3699
3700 if(eHAL_STATUS_SUCCESS != halStatus)
3701 {
3702 status = VOS_STATUS_E_FAILURE;
3703 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3704 VOS_ASSERT(0);
3705 return status;
3706 }
3707 }
3708
3709 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3710 {
3711 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3712
3713 if(eHAL_STATUS_SUCCESS != halStatus)
3714 {
3715 status = VOS_STATUS_E_FAILURE;
3716 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3717 VOS_ASSERT(0);
3718 return status;
3719 }
3720 }
3721 }
3722
3723 if((TRUE == disableBmps) ||
3724 (TRUE == disableImps))
3725 {
3726 /* Now, get the chip into Full Power now */
3727 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3728 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3729 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3730
3731 if(halStatus != eHAL_STATUS_SUCCESS)
3732 {
3733 if(halStatus == eHAL_STATUS_PMC_PENDING)
3734 {
3735 //Block on a completion variable. Can't wait forever though
3736 wait_for_completion_interruptible_timeout(
3737 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3738 }
3739 else
3740 {
3741 status = VOS_STATUS_E_FAILURE;
3742 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3743 VOS_ASSERT(0);
3744 return status;
3745 }
3746 }
3747
3748 status = VOS_STATUS_SUCCESS;
3749 }
3750
3751 break;
3752 }
3753 return status;
3754}
3755
3756hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003757 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003758 tANI_U8 rtnl_held )
3759{
3760 hdd_adapter_t *pAdapter = NULL;
3761 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3762 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3763 VOS_STATUS exitbmpsStatus;
3764
3765 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3766
3767 //Disable BMPS incase of Concurrency
3768 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3769
3770 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3771 {
3772 //Fail to Exit BMPS
3773 VOS_ASSERT(0);
3774 return NULL;
3775 }
3776
3777 switch(session_type)
3778 {
3779 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003780 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003781 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003782 {
3783 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3784
3785 if( NULL == pAdapter )
3786 return NULL;
3787
Jeff Johnsone7245742012-09-05 17:12:55 -07003788 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3789 NL80211_IFTYPE_P2P_CLIENT:
3790 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003791
Jeff Johnson295189b2012-06-20 16:38:30 -07003792 pAdapter->device_mode = session_type;
3793
3794 status = hdd_init_station_mode( pAdapter );
3795 if( VOS_STATUS_SUCCESS != status )
3796 goto err_free_netdev;
3797
3798 status = hdd_register_interface( pAdapter, rtnl_held );
3799 if( VOS_STATUS_SUCCESS != status )
3800 {
3801 hdd_deinit_adapter(pHddCtx, pAdapter);
3802 goto err_free_netdev;
3803 }
3804 //Stop the Interface TX queue.
3805 netif_tx_disable(pAdapter->dev);
3806 //netif_tx_disable(pWlanDev);
3807 netif_carrier_off(pAdapter->dev);
3808
3809 break;
3810 }
3811
Jeff Johnson295189b2012-06-20 16:38:30 -07003812 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003813 case WLAN_HDD_SOFTAP:
3814 {
3815 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3816 if( NULL == pAdapter )
3817 return NULL;
3818
Jeff Johnson295189b2012-06-20 16:38:30 -07003819 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3820 NL80211_IFTYPE_AP:
3821 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003822 pAdapter->device_mode = session_type;
3823
3824 status = hdd_init_ap_mode(pAdapter);
3825 if( VOS_STATUS_SUCCESS != status )
3826 goto err_free_netdev;
3827
3828 status = hdd_register_hostapd( pAdapter, rtnl_held );
3829 if( VOS_STATUS_SUCCESS != status )
3830 {
3831 hdd_deinit_adapter(pHddCtx, pAdapter);
3832 goto err_free_netdev;
3833 }
3834
3835 netif_tx_disable(pAdapter->dev);
3836 netif_carrier_off(pAdapter->dev);
3837
3838 hdd_set_conparam( 1 );
3839 break;
3840 }
3841 case WLAN_HDD_MONITOR:
3842 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003843 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3844 if( NULL == pAdapter )
3845 return NULL;
3846
3847 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3848 pAdapter->device_mode = session_type;
3849 status = hdd_register_interface( pAdapter, rtnl_held );
3850#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3851 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3852#else
3853 pAdapter->dev->open = hdd_mon_open;
3854 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3855#endif
3856 hdd_init_tx_rx( pAdapter );
3857 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3858 //Set adapter to be used for data tx. It will use either GO or softap.
3859 pAdapter->sessionCtx.monitor.pAdapterForTx =
3860 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003861 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3862 {
3863 pAdapter->sessionCtx.monitor.pAdapterForTx =
3864 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3865 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003866 /* This workqueue will be used to transmit management packet over
3867 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003868 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3869 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3870 return NULL;
3871 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003872
Jeff Johnson295189b2012-06-20 16:38:30 -07003873 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3874 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003875 }
3876 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003877 case WLAN_HDD_FTM:
3878 {
3879 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3880
3881 if( NULL == pAdapter )
3882 return NULL;
3883 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3884 * message while loading driver in FTM mode. */
3885 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3886 pAdapter->device_mode = session_type;
3887 status = hdd_register_interface( pAdapter, rtnl_held );
3888 }
3889 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003890 default:
3891 {
3892 VOS_ASSERT(0);
3893 return NULL;
3894 }
3895 }
3896
3897
3898 if( VOS_STATUS_SUCCESS == status )
3899 {
3900 //Add it to the hdd's session list.
3901 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3902 if( NULL == pHddAdapterNode )
3903 {
3904 status = VOS_STATUS_E_NOMEM;
3905 }
3906 else
3907 {
3908 pHddAdapterNode->pAdapter = pAdapter;
3909 status = hdd_add_adapter_back ( pHddCtx,
3910 pHddAdapterNode );
3911 }
3912 }
3913
3914 if( VOS_STATUS_SUCCESS != status )
3915 {
3916 if( NULL != pAdapter )
3917 {
3918 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3919 pAdapter = NULL;
3920 }
3921 if( NULL != pHddAdapterNode )
3922 {
3923 vos_mem_free( pHddAdapterNode );
3924 }
3925
3926 goto resume_bmps;
3927 }
3928
3929 if(VOS_STATUS_SUCCESS == status)
3930 {
3931 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3932
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003933 //Initialize the WoWL service
3934 if(!hdd_init_wowl(pAdapter))
3935 {
3936 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3937 goto err_free_netdev;
3938 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003939 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003940 return pAdapter;
3941
3942err_free_netdev:
3943 free_netdev(pAdapter->dev);
3944 wlan_hdd_release_intf_addr( pHddCtx,
3945 pAdapter->macAddressCurrent.bytes );
3946
3947resume_bmps:
3948 //If bmps disabled enable it
3949 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3950 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303951 if (pHddCtx->hdd_wlan_suspended)
3952 {
3953 hdd_set_pwrparams(pHddCtx);
3954 }
3955 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003956 }
3957 return NULL;
3958}
3959
3960VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3961 tANI_U8 rtnl_held )
3962{
3963 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3964 VOS_STATUS status;
3965
3966 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3967 if( VOS_STATUS_SUCCESS != status )
3968 return status;
3969
3970 while ( pCurrent->pAdapter != pAdapter )
3971 {
3972 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3973 if( VOS_STATUS_SUCCESS != status )
3974 break;
3975
3976 pCurrent = pNext;
3977 }
3978 pAdapterNode = pCurrent;
3979 if( VOS_STATUS_SUCCESS == status )
3980 {
3981 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3982 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3983 hdd_remove_adapter( pHddCtx, pAdapterNode );
3984 vos_mem_free( pAdapterNode );
3985
Jeff Johnson295189b2012-06-20 16:38:30 -07003986
3987 /* If there is a single session of STA/P2P client, re-enable BMPS */
3988 if ((!vos_concurrent_sessions_running()) &&
3989 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3990 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3991 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303992 if (pHddCtx->hdd_wlan_suspended)
3993 {
3994 hdd_set_pwrparams(pHddCtx);
3995 }
3996 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003997 }
3998
3999 return VOS_STATUS_SUCCESS;
4000 }
4001
4002 return VOS_STATUS_E_FAILURE;
4003}
4004
4005VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
4006{
4007 hdd_adapter_list_node_t *pHddAdapterNode;
4008 VOS_STATUS status;
4009
4010 ENTER();
4011
4012 do
4013 {
4014 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
4015 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
4016 {
4017 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
4018 vos_mem_free( pHddAdapterNode );
4019 }
4020 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
4021
4022 EXIT();
4023
4024 return VOS_STATUS_SUCCESS;
4025}
4026
4027void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
4028{
4029 v_U8_t addIE[1] = {0};
4030
4031 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4032 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
4033 eANI_BOOLEAN_FALSE) )
4034 {
4035 hddLog(LOGE,
4036 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
4037 }
4038
4039 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4040 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
4041 eANI_BOOLEAN_FALSE) )
4042 {
4043 hddLog(LOGE,
4044 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
4045 }
4046
4047 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4048 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
4049 eANI_BOOLEAN_FALSE) )
4050 {
4051 hddLog(LOGE,
4052 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
4053 }
4054}
4055
4056VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4057{
4058 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4059 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4060 union iwreq_data wrqu;
4061
4062 ENTER();
4063
4064 switch(pAdapter->device_mode)
4065 {
4066 case WLAN_HDD_INFRA_STATION:
4067 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004068 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004069 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4070 {
4071 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
4072 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4073 pAdapter->sessionId,
4074 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
4075 else
4076 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4077 pAdapter->sessionId,
4078 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4079 //success implies disconnect command got queued up successfully
4080 if(halStatus == eHAL_STATUS_SUCCESS)
4081 {
4082 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
4083 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4084 }
4085 memset(&wrqu, '\0', sizeof(wrqu));
4086 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4087 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4088 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
4089 }
4090 else
4091 {
4092 hdd_abort_mac_scan(pHddCtx);
4093 }
4094
4095 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
4096 {
4097 INIT_COMPLETION(pAdapter->session_close_comp_var);
4098 if (eHAL_STATUS_SUCCESS ==
4099 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
4100 hdd_smeCloseSessionCallback, pAdapter))
4101 {
4102 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004103 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004104 &pAdapter->session_close_comp_var,
4105 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4106 }
4107 }
4108
4109 break;
4110
4111 case WLAN_HDD_SOFTAP:
4112 case WLAN_HDD_P2P_GO:
4113 //Any softap specific cleanup here...
4114 mutex_lock(&pHddCtx->sap_lock);
4115 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4116 {
4117 VOS_STATUS status;
4118 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4119
4120 //Stop Bss.
4121 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4122 if (VOS_IS_STATUS_SUCCESS(status))
4123 {
4124 hdd_hostapd_state_t *pHostapdState =
4125 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4126
4127 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4128
4129 if (!VOS_IS_STATUS_SUCCESS(status))
4130 {
4131 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004132 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004133 }
4134 }
4135 else
4136 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004137 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004138 }
4139 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4140
4141 if (eHAL_STATUS_FAILURE ==
4142 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4143 0, NULL, eANI_BOOLEAN_FALSE))
4144 {
4145 hddLog(LOGE,
4146 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004147 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004148 }
4149
4150 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4151 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4152 eANI_BOOLEAN_FALSE) )
4153 {
4154 hddLog(LOGE,
4155 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4156 }
4157
4158 // Reset WNI_CFG_PROBE_RSP Flags
4159 wlan_hdd_reset_prob_rspies(pAdapter);
4160 kfree(pAdapter->sessionCtx.ap.beacon);
4161 pAdapter->sessionCtx.ap.beacon = NULL;
4162 }
4163 mutex_unlock(&pHddCtx->sap_lock);
4164 break;
4165 case WLAN_HDD_MONITOR:
4166 break;
4167 default:
4168 break;
4169 }
4170
4171 EXIT();
4172 return VOS_STATUS_SUCCESS;
4173}
4174
4175VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4176{
4177 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4178 VOS_STATUS status;
4179 hdd_adapter_t *pAdapter;
4180
4181 ENTER();
4182
4183 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4184
4185 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4186 {
4187 pAdapter = pAdapterNode->pAdapter;
4188 netif_tx_disable(pAdapter->dev);
4189 netif_carrier_off(pAdapter->dev);
4190
4191 hdd_stop_adapter( pHddCtx, pAdapter );
4192
4193 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4194 pAdapterNode = pNext;
4195 }
4196
4197 EXIT();
4198
4199 return VOS_STATUS_SUCCESS;
4200}
4201
4202VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4203{
4204 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4205 VOS_STATUS status;
4206 hdd_adapter_t *pAdapter;
4207
4208 ENTER();
4209
4210 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4211
4212 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4213 {
4214 pAdapter = pAdapterNode->pAdapter;
4215 netif_tx_disable(pAdapter->dev);
4216 netif_carrier_off(pAdapter->dev);
4217
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004218 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
4219
Jeff Johnson295189b2012-06-20 16:38:30 -07004220 hdd_deinit_tx_rx(pAdapter);
4221 hdd_wmm_adapter_close(pAdapter);
4222
4223 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4224 pAdapterNode = pNext;
4225 }
4226
4227 EXIT();
4228
4229 return VOS_STATUS_SUCCESS;
4230}
4231
4232VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4233{
4234 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4235 VOS_STATUS status;
4236 hdd_adapter_t *pAdapter;
4237 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304238 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004239
4240 ENTER();
4241
4242 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4243
4244 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4245 {
4246 pAdapter = pAdapterNode->pAdapter;
4247
4248 switch(pAdapter->device_mode)
4249 {
4250 case WLAN_HDD_INFRA_STATION:
4251 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004252 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304253
4254 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4255
Jeff Johnson295189b2012-06-20 16:38:30 -07004256 hdd_init_station_mode(pAdapter);
4257 /* Open the gates for HDD to receive Wext commands */
4258 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004259 pHddCtx->scan_info.mScanPending = FALSE;
4260 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004261
4262 //Trigger the initial scan
4263 hdd_wlan_initial_scan(pAdapter);
4264
4265 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304266 if (eConnectionState_Associated == connState ||
4267 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004268 {
4269 union iwreq_data wrqu;
4270 memset(&wrqu, '\0', sizeof(wrqu));
4271 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4272 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4273 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004274 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004275
Jeff Johnson295189b2012-06-20 16:38:30 -07004276 /* indicate disconnected event to nl80211 */
4277 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4278 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004279 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304280 else if (eConnectionState_Connecting == connState)
4281 {
4282 /*
4283 * Indicate connect failure to supplicant if we were in the
4284 * process of connecting
4285 */
4286 cfg80211_connect_result(pAdapter->dev, NULL,
4287 NULL, 0, NULL, 0,
4288 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4289 GFP_KERNEL);
4290 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004291 break;
4292
4293 case WLAN_HDD_SOFTAP:
4294 /* softAP can handle SSR */
4295 break;
4296
4297 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004298 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4299 __func__);
4300 /* event supplicant to restart */
4301 cfg80211_del_sta(pAdapter->dev,
4302 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004303 break;
4304
4305 case WLAN_HDD_MONITOR:
4306 /* monitor interface start */
4307 break;
4308 default:
4309 break;
4310 }
4311
4312 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4313 pAdapterNode = pNext;
4314 }
4315
4316 EXIT();
4317
4318 return VOS_STATUS_SUCCESS;
4319}
4320
4321VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4322{
4323 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4324 hdd_adapter_t *pAdapter;
4325 VOS_STATUS status;
4326 v_U32_t roamId;
4327
4328 ENTER();
4329
4330 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4331
4332 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4333 {
4334 pAdapter = pAdapterNode->pAdapter;
4335
4336 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4337 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4338 {
4339 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4340 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4341
4342 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4343 init_completion(&pAdapter->disconnect_comp_var);
4344 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4345 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4346
4347 wait_for_completion_interruptible_timeout(
4348 &pAdapter->disconnect_comp_var,
4349 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4350
4351 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4352 pHddCtx->isAmpAllowed = VOS_FALSE;
4353 sme_RoamConnect(pHddCtx->hHal,
4354 pAdapter->sessionId, &(pWextState->roamProfile),
4355 &roamId);
4356 }
4357
4358 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4359 pAdapterNode = pNext;
4360 }
4361
4362 EXIT();
4363
4364 return VOS_STATUS_SUCCESS;
4365}
4366
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004367void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4368{
4369 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4370 VOS_STATUS status;
4371 hdd_adapter_t *pAdapter;
4372 hdd_station_ctx_t *pHddStaCtx;
4373 hdd_ap_ctx_t *pHddApCtx;
4374 hdd_hostapd_state_t * pHostapdState;
4375 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4376 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4377 const char *p2pMode = "DEV";
4378 const char *ccMode = "Standalone";
4379 int n;
4380
4381 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4382 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4383 {
4384 pAdapter = pAdapterNode->pAdapter;
4385 switch (pAdapter->device_mode) {
4386 case WLAN_HDD_INFRA_STATION:
4387 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4388 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4389 staChannel = pHddStaCtx->conn_info.operationChannel;
4390 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4391 }
4392 break;
4393 case WLAN_HDD_P2P_CLIENT:
4394 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4395 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4396 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4397 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4398 p2pMode = "CLI";
4399 }
4400 break;
4401 case WLAN_HDD_P2P_GO:
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 p2pChannel = pHddApCtx->operatingChannel;
4406 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4407 }
4408 p2pMode = "GO";
4409 break;
4410 case WLAN_HDD_SOFTAP:
4411 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4412 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4413 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4414 apChannel = pHddApCtx->operatingChannel;
4415 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4416 }
4417 break;
4418 default:
4419 break;
4420 }
4421 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4422 pAdapterNode = pNext;
4423 }
4424 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4425 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4426 }
4427 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4428 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4429 if (p2pChannel > 0) {
4430 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4431 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4432 }
4433 if (apChannel > 0) {
4434 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4435 apChannel, MAC_ADDR_ARRAY(apBssid));
4436 }
4437
4438 if (p2pChannel > 0 && apChannel > 0) {
4439 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4440 }
4441}
4442
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004443bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004444{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004445 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004446}
4447
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004448/* Once SSR is disabled then it cannot be set. */
4449void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004450{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004451 if (HDD_SSR_DISABLED == isSsrRequired)
4452 return;
4453
Jeff Johnson295189b2012-06-20 16:38:30 -07004454 isSsrRequired = value;
4455}
4456
4457VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4458 hdd_adapter_list_node_t** ppAdapterNode)
4459{
4460 VOS_STATUS status;
4461 spin_lock(&pHddCtx->hddAdapters.lock);
4462 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4463 (hdd_list_node_t**) ppAdapterNode );
4464 spin_unlock(&pHddCtx->hddAdapters.lock);
4465 return status;
4466}
4467
4468VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4469 hdd_adapter_list_node_t* pAdapterNode,
4470 hdd_adapter_list_node_t** pNextAdapterNode)
4471{
4472 VOS_STATUS status;
4473 spin_lock(&pHddCtx->hddAdapters.lock);
4474 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4475 (hdd_list_node_t*) pAdapterNode,
4476 (hdd_list_node_t**)pNextAdapterNode );
4477
4478 spin_unlock(&pHddCtx->hddAdapters.lock);
4479 return status;
4480}
4481
4482VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4483 hdd_adapter_list_node_t* pAdapterNode)
4484{
4485 VOS_STATUS status;
4486 spin_lock(&pHddCtx->hddAdapters.lock);
4487 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4488 &pAdapterNode->node );
4489 spin_unlock(&pHddCtx->hddAdapters.lock);
4490 return status;
4491}
4492
4493VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4494 hdd_adapter_list_node_t** ppAdapterNode)
4495{
4496 VOS_STATUS status;
4497 spin_lock(&pHddCtx->hddAdapters.lock);
4498 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4499 (hdd_list_node_t**) ppAdapterNode );
4500 spin_unlock(&pHddCtx->hddAdapters.lock);
4501 return status;
4502}
4503
4504VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4505 hdd_adapter_list_node_t* pAdapterNode)
4506{
4507 VOS_STATUS status;
4508 spin_lock(&pHddCtx->hddAdapters.lock);
4509 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4510 (hdd_list_node_t*) pAdapterNode );
4511 spin_unlock(&pHddCtx->hddAdapters.lock);
4512 return status;
4513}
4514
4515VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4516 hdd_adapter_list_node_t* pAdapterNode)
4517{
4518 VOS_STATUS status;
4519 spin_lock(&pHddCtx->hddAdapters.lock);
4520 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4521 (hdd_list_node_t*) pAdapterNode );
4522 spin_unlock(&pHddCtx->hddAdapters.lock);
4523 return status;
4524}
4525
4526hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4527 tSirMacAddr macAddr )
4528{
4529 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4530 hdd_adapter_t *pAdapter;
4531 VOS_STATUS status;
4532
4533 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4534
4535 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4536 {
4537 pAdapter = pAdapterNode->pAdapter;
4538
4539 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4540 macAddr, sizeof(tSirMacAddr) ) )
4541 {
4542 return pAdapter;
4543 }
4544 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4545 pAdapterNode = pNext;
4546 }
4547
4548 return NULL;
4549
4550}
4551
4552hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4553{
4554 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4555 hdd_adapter_t *pAdapter;
4556 VOS_STATUS status;
4557
4558 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4559
4560 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4561 {
4562 pAdapter = pAdapterNode->pAdapter;
4563
4564 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4565 IFNAMSIZ ) )
4566 {
4567 return pAdapter;
4568 }
4569 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4570 pAdapterNode = pNext;
4571 }
4572
4573 return NULL;
4574
4575}
4576
4577hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4578{
4579 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4580 hdd_adapter_t *pAdapter;
4581 VOS_STATUS status;
4582
4583 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4584
4585 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4586 {
4587 pAdapter = pAdapterNode->pAdapter;
4588
4589 if( pAdapter && (mode == pAdapter->device_mode) )
4590 {
4591 return pAdapter;
4592 }
4593 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4594 pAdapterNode = pNext;
4595 }
4596
4597 return NULL;
4598
4599}
4600
4601//Remove this function later
4602hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4603{
4604 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4605 hdd_adapter_t *pAdapter;
4606 VOS_STATUS status;
4607
4608 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4609
4610 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4611 {
4612 pAdapter = pAdapterNode->pAdapter;
4613
4614 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4615 {
4616 return pAdapter;
4617 }
4618
4619 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4620 pAdapterNode = pNext;
4621 }
4622
4623 return NULL;
4624
4625}
4626
Jeff Johnson295189b2012-06-20 16:38:30 -07004627/**---------------------------------------------------------------------------
4628
4629 \brief hdd_set_monitor_tx_adapter() -
4630
4631 This API initializes the adapter to be used while transmitting on monitor
4632 adapter.
4633
4634 \param - pHddCtx - Pointer to the HDD context.
4635 pAdapter - Adapter that will used for TX. This can be NULL.
4636 \return - None.
4637 --------------------------------------------------------------------------*/
4638void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4639{
4640 hdd_adapter_t *pMonAdapter;
4641
4642 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4643
4644 if( NULL != pMonAdapter )
4645 {
4646 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4647 }
4648}
Jeff Johnson295189b2012-06-20 16:38:30 -07004649/**---------------------------------------------------------------------------
4650
4651 \brief hdd_select_queue() -
4652
4653 This API returns the operating channel of the requested device mode
4654
4655 \param - pHddCtx - Pointer to the HDD context.
4656 - mode - Device mode for which operating channel is required
4657 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4658 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4659 \return - channel number. "0" id the requested device is not found OR it is not connected.
4660 --------------------------------------------------------------------------*/
4661v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4662{
4663 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4664 VOS_STATUS status;
4665 hdd_adapter_t *pAdapter;
4666 v_U8_t operatingChannel = 0;
4667
4668 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4669
4670 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4671 {
4672 pAdapter = pAdapterNode->pAdapter;
4673
4674 if( mode == pAdapter->device_mode )
4675 {
4676 switch(pAdapter->device_mode)
4677 {
4678 case WLAN_HDD_INFRA_STATION:
4679 case WLAN_HDD_P2P_CLIENT:
4680 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4681 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4682 break;
4683 case WLAN_HDD_SOFTAP:
4684 case WLAN_HDD_P2P_GO:
4685 /*softap connection info */
4686 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4687 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4688 break;
4689 default:
4690 break;
4691 }
4692
4693 break; //Found the device of interest. break the loop
4694 }
4695
4696 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4697 pAdapterNode = pNext;
4698 }
4699 return operatingChannel;
4700}
4701
4702#ifdef WLAN_FEATURE_PACKET_FILTERING
4703/**---------------------------------------------------------------------------
4704
4705 \brief hdd_set_multicast_list() -
4706
4707 This used to set the multicast address list.
4708
4709 \param - dev - Pointer to the WLAN device.
4710 - skb - Pointer to OS packet (sk_buff).
4711 \return - success/fail
4712
4713 --------------------------------------------------------------------------*/
4714static void hdd_set_multicast_list(struct net_device *dev)
4715{
4716 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004717 int mc_count;
4718 int i = 0;
4719 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304720
4721 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004722 {
4723 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304724 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004725 return;
4726 }
4727
4728 if (dev->flags & IFF_ALLMULTI)
4729 {
4730 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004731 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304732 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004733 }
4734 else
4735 {
4736 mc_count = netdev_mc_count(dev);
4737 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004738 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004739 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4740 {
4741 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004742 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304743 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004744 return;
4745 }
4746
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304747 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004748
4749 netdev_for_each_mc_addr(ha, dev) {
4750 if (i == mc_count)
4751 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304752 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4753 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4754 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004755 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304756 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004757 i++;
4758 }
4759 }
4760 return;
4761}
4762#endif
4763
4764/**---------------------------------------------------------------------------
4765
4766 \brief hdd_select_queue() -
4767
4768 This function is registered with the Linux OS for network
4769 core to decide which queue to use first.
4770
4771 \param - dev - Pointer to the WLAN device.
4772 - skb - Pointer to OS packet (sk_buff).
4773 \return - ac, Queue Index/access category corresponding to UP in IP header
4774
4775 --------------------------------------------------------------------------*/
4776v_U16_t hdd_select_queue(struct net_device *dev,
4777 struct sk_buff *skb)
4778{
4779 return hdd_wmm_select_queue(dev, skb);
4780}
4781
4782
4783/**---------------------------------------------------------------------------
4784
4785 \brief hdd_wlan_initial_scan() -
4786
4787 This function triggers the initial scan
4788
4789 \param - pAdapter - Pointer to the HDD adapter.
4790
4791 --------------------------------------------------------------------------*/
4792void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4793{
4794 tCsrScanRequest scanReq;
4795 tCsrChannelInfo channelInfo;
4796 eHalStatus halStatus;
4797 unsigned long scanId;
4798 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4799
4800 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4801 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4802 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4803
4804 if(sme_Is11dSupported(pHddCtx->hHal))
4805 {
4806 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4807 if ( HAL_STATUS_SUCCESS( halStatus ) )
4808 {
4809 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4810 if( !scanReq.ChannelInfo.ChannelList )
4811 {
4812 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4813 vos_mem_free(channelInfo.ChannelList);
4814 return;
4815 }
4816 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4817 channelInfo.numOfChannels);
4818 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4819 vos_mem_free(channelInfo.ChannelList);
4820 }
4821
4822 scanReq.scanType = eSIR_PASSIVE_SCAN;
4823 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4824 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4825 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4826 }
4827 else
4828 {
4829 scanReq.scanType = eSIR_ACTIVE_SCAN;
4830 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4831 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4832 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4833 }
4834
4835 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4836 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4837 {
4838 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4839 __func__, halStatus );
4840 }
4841
4842 if(sme_Is11dSupported(pHddCtx->hHal))
4843 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4844}
4845
4846struct fullPowerContext
4847{
4848 struct completion completion;
4849 unsigned int magic;
4850};
4851#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4852
4853/**---------------------------------------------------------------------------
4854
4855 \brief hdd_full_power_callback() - HDD full power callback function
4856
4857 This is the function invoked by SME to inform the result of a full power
4858 request issued by HDD
4859
4860 \param - callbackcontext - Pointer to cookie
4861 \param - status - result of request
4862
4863 \return - None
4864
4865 --------------------------------------------------------------------------*/
4866static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4867{
4868 struct fullPowerContext *pContext = callbackContext;
4869
4870 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304871 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004872
4873 if (NULL == callbackContext)
4874 {
4875 hddLog(VOS_TRACE_LEVEL_ERROR,
4876 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004877 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004878 return;
4879 }
4880
4881 /* there is a race condition that exists between this callback function
4882 and the caller since the caller could time out either before or
4883 while this code is executing. we'll assume the timeout hasn't
4884 occurred, but we'll verify that right before we save our work */
4885
4886 if (POWER_CONTEXT_MAGIC != pContext->magic)
4887 {
4888 /* the caller presumably timed out so there is nothing we can do */
4889 hddLog(VOS_TRACE_LEVEL_WARN,
4890 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004891 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004892 return;
4893 }
4894
4895 /* the race is on. caller could have timed out immediately after
4896 we verified the magic, but if so, caller will wait a short time
4897 for us to notify the caller, so the context will stay valid */
4898 complete(&pContext->completion);
4899}
4900
4901/**---------------------------------------------------------------------------
4902
4903 \brief hdd_wlan_exit() - HDD WLAN exit function
4904
4905 This is the driver exit point (invoked during rmmod)
4906
4907 \param - pHddCtx - Pointer to the HDD Context
4908
4909 \return - None
4910
4911 --------------------------------------------------------------------------*/
4912void hdd_wlan_exit(hdd_context_t *pHddCtx)
4913{
4914 eHalStatus halStatus;
4915 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4916 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304917 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004918 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004919 struct fullPowerContext powerContext;
4920 long lrc;
4921
4922 ENTER();
4923
Jeff Johnson88ba7742013-02-27 14:36:02 -08004924 if (VOS_FTM_MODE != hdd_get_conparam())
4925 {
4926 // Unloading, restart logic is no more required.
4927 wlan_hdd_restart_deinit(pHddCtx);
4928 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004929
Jeff Johnson295189b2012-06-20 16:38:30 -07004930 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004931 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004932 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004933 {
4934 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4935 WLAN_HDD_INFRA_STATION);
4936 if (pAdapter == NULL)
4937 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4938
4939 if (pAdapter != NULL)
4940 {
4941 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4942 hdd_UnregisterWext(pAdapter->dev);
4943 }
4944 }
4945 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004946
Jeff Johnson295189b2012-06-20 16:38:30 -07004947 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004948 {
4949 wlan_hdd_ftm_close(pHddCtx);
4950 goto free_hdd_ctx;
4951 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004952 //Stop the Interface TX queue.
4953 //netif_tx_disable(pWlanDev);
4954 //netif_carrier_off(pWlanDev);
4955
Jeff Johnson295189b2012-06-20 16:38:30 -07004956 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4957 {
4958 pAdapter = hdd_get_adapter(pHddCtx,
4959 WLAN_HDD_SOFTAP);
4960 }
4961 else
4962 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004963 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004964 {
4965 pAdapter = hdd_get_adapter(pHddCtx,
4966 WLAN_HDD_INFRA_STATION);
4967 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004968 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004969 /* DeRegister with platform driver as client for Suspend/Resume */
4970 vosStatus = hddDeregisterPmOps(pHddCtx);
4971 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4972 {
4973 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4974 VOS_ASSERT(0);
4975 }
4976
4977 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4978 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4979 {
4980 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4981 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004982
4983 // Cancel any outstanding scan requests. We are about to close all
4984 // of our adapters, but an adapter structure is what SME passes back
4985 // to our callback function. Hence if there are any outstanding scan
4986 // requests then there is a race condition between when the adapter
4987 // is closed and when the callback is invoked. We try to resolve that
4988 // race condition here by canceling any outstanding scans before we
4989 // close the adapters.
4990 // Note that the scans may be cancelled in an asynchronous manner, so
4991 // ideally there needs to be some kind of synchronization. Rather than
4992 // introduce a new synchronization here, we will utilize the fact that
4993 // we are about to Request Full Power, and since that is synchronized,
4994 // the expectation is that by the time Request Full Power has completed,
4995 // all scans will be cancelled.
4996 hdd_abort_mac_scan( pHddCtx );
4997
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05304998 //Stop the timer if already running
4999 if (VOS_TIMER_STATE_RUNNING ==
5000 vos_timer_getCurrentState(&pHddCtx->hdd_p2p_go_conn_is_in_progress))
5001 {
5002 vos_timer_stop(&pHddCtx->hdd_p2p_go_conn_is_in_progress);
5003 }
5004
5005 // Destroy hdd_p2p_go_conn_is_in_progress timer
5006 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
5007 &pHddCtx->hdd_p2p_go_conn_is_in_progress)))
5008 {
5009 hddLog(VOS_TRACE_LEVEL_ERROR,
5010 "%s: Cannot deallocate p2p connection timer", __func__);
5011 }
5012
Jeff Johnson295189b2012-06-20 16:38:30 -07005013 //Disable IMPS/BMPS as we do not want the device to enter any power
5014 //save mode during shutdown
5015 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5016 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5017 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
5018
5019 //Ensure that device is in full power as we will touch H/W during vos_Stop
5020 init_completion(&powerContext.completion);
5021 powerContext.magic = POWER_CONTEXT_MAGIC;
5022
5023 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
5024 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
5025
5026 if (eHAL_STATUS_SUCCESS != halStatus)
5027 {
5028 if (eHAL_STATUS_PMC_PENDING == halStatus)
5029 {
5030 /* request was sent -- wait for the response */
5031 lrc = wait_for_completion_interruptible_timeout(
5032 &powerContext.completion,
5033 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
5034 /* either we have a response or we timed out
5035 either way, first invalidate our magic */
5036 powerContext.magic = 0;
5037 if (lrc <= 0)
5038 {
5039 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005040 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07005041 /* there is a race condition such that the callback
5042 function could be executing at the same time we are. of
5043 primary concern is if the callback function had already
5044 verified the "magic" but hasn't yet set the completion
5045 variable. Since the completion variable is on our
5046 stack, we'll delay just a bit to make sure the data is
5047 still valid if that is the case */
5048 msleep(50);
5049 }
5050 }
5051 else
5052 {
5053 hddLog(VOS_TRACE_LEVEL_ERROR,
5054 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005055 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07005056 VOS_ASSERT(0);
5057 /* continue -- need to clean up as much as possible */
5058 }
5059 }
5060
Yue Ma0d4891e2013-08-06 17:01:45 -07005061 hdd_debugfs_exit(pHddCtx);
5062
Jeff Johnson295189b2012-06-20 16:38:30 -07005063 // Unregister the Net Device Notifier
5064 unregister_netdevice_notifier(&hdd_netdev_notifier);
5065
Jeff Johnson295189b2012-06-20 16:38:30 -07005066 hdd_stop_all_adapters( pHddCtx );
5067
Jeff Johnson295189b2012-06-20 16:38:30 -07005068#ifdef WLAN_BTAMP_FEATURE
5069 vosStatus = WLANBAP_Stop(pVosContext);
5070 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5071 {
5072 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5073 "%s: Failed to stop BAP",__func__);
5074 }
5075#endif //WLAN_BTAMP_FEATURE
5076
5077 //Stop all the modules
5078 vosStatus = vos_stop( pVosContext );
5079 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5080 {
5081 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5082 "%s: Failed to stop VOSS",__func__);
5083 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5084 }
5085
Jeff Johnson295189b2012-06-20 16:38:30 -07005086 //Assert Deep sleep signal now to put Libra HW in lowest power state
5087 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5088 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5089
5090 //Vote off any PMIC voltage supplies
5091 vos_chipPowerDown(NULL, NULL, NULL);
5092
5093 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
5094
Leo Chang59cdc7e2013-07-10 10:08:21 -07005095
Jeff Johnson295189b2012-06-20 16:38:30 -07005096 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07005097 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005098
5099 //Close the scheduler before calling vos_close to make sure no thread is
5100 // scheduled after the each module close is called i.e after all the data
5101 // structures are freed.
5102 vosStatus = vos_sched_close( pVosContext );
5103 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
5104 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5105 "%s: Failed to close VOSS Scheduler",__func__);
5106 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5107 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005108#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005109#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5110 /* Destroy the wake lock */
5111 wake_lock_destroy(&pHddCtx->rx_wake_lock);
5112#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005113 /* Destroy the wake lock */
5114 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005115#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005116
5117 //Close VOSS
5118 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
5119 vos_close(pVosContext);
5120
Jeff Johnson295189b2012-06-20 16:38:30 -07005121 //Close Watchdog
5122 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5123 vos_watchdog_close(pVosContext);
5124
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305125 //Clean up HDD Nlink Service
5126 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07005127#ifdef WLAN_KD_READY_NOTIFIER
5128 nl_srv_exit(pHddCtx->ptt_pid);
5129#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305130 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005131#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305132
Jeff Johnson295189b2012-06-20 16:38:30 -07005133 /* Cancel the vote for XO Core ON.
5134 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5135 * exited at this point
5136 */
5137 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5138 " when WLAN is turned OFF\n");
5139 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5140 {
5141 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5142 " Not returning failure."
5143 " Power consumed will be high\n");
5144 }
5145
5146 hdd_close_all_adapters( pHddCtx );
5147
5148
5149 //Free up dynamically allocated members inside HDD Adapter
5150 kfree(pHddCtx->cfg_ini);
5151 pHddCtx->cfg_ini= NULL;
5152
5153 /* free the power on lock from platform driver */
5154 if (free_riva_power_on_lock("wlan"))
5155 {
5156 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5157 __func__);
5158 }
5159
Jeff Johnson88ba7742013-02-27 14:36:02 -08005160free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08005161 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005162 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005163 if (hdd_is_ssr_required())
5164 {
5165 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005166 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005167 msleep(5000);
5168 }
5169 hdd_set_ssr_required (VOS_FALSE);
5170}
5171
5172
5173/**---------------------------------------------------------------------------
5174
5175 \brief hdd_update_config_from_nv() - Function to update the contents of
5176 the running configuration with parameters taken from NV storage
5177
5178 \param - pHddCtx - Pointer to the HDD global context
5179
5180 \return - VOS_STATUS_SUCCESS if successful
5181
5182 --------------------------------------------------------------------------*/
5183static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5184{
Jeff Johnson295189b2012-06-20 16:38:30 -07005185 v_BOOL_t itemIsValid = VOS_FALSE;
5186 VOS_STATUS status;
5187 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5188 v_U8_t macLoop;
5189
5190 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5191 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5192 if(status != VOS_STATUS_SUCCESS)
5193 {
5194 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5195 return VOS_STATUS_E_FAILURE;
5196 }
5197
5198 if (itemIsValid == VOS_TRUE)
5199 {
5200 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5201 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5202 VOS_MAX_CONCURRENCY_PERSONA);
5203 if(status != VOS_STATUS_SUCCESS)
5204 {
5205 /* Get MAC from NV fail, not update CFG info
5206 * INI MAC value will be used for MAC setting */
5207 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5208 return VOS_STATUS_E_FAILURE;
5209 }
5210
5211 /* If first MAC is not valid, treat all others are not valid
5212 * Then all MACs will be got from ini file */
5213 if(vos_is_macaddr_zero(&macFromNV[0]))
5214 {
5215 /* MAC address in NV file is not configured yet */
5216 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5217 return VOS_STATUS_E_INVAL;
5218 }
5219
5220 /* Get MAC address from NV, update CFG info */
5221 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5222 {
5223 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5224 {
5225 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5226 /* This MAC is not valid, skip it
5227 * This MAC will be got from ini file */
5228 }
5229 else
5230 {
5231 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5232 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5233 VOS_MAC_ADDR_SIZE);
5234 }
5235 }
5236 }
5237 else
5238 {
5239 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5240 return VOS_STATUS_E_FAILURE;
5241 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005242
Jeff Johnson295189b2012-06-20 16:38:30 -07005243
5244 return VOS_STATUS_SUCCESS;
5245}
5246
5247/**---------------------------------------------------------------------------
5248
5249 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5250
5251 \param - pAdapter - Pointer to the HDD
5252
5253 \return - None
5254
5255 --------------------------------------------------------------------------*/
5256VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5257{
5258 eHalStatus halStatus;
5259 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305260 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005261
Jeff Johnson295189b2012-06-20 16:38:30 -07005262
5263 // Send ready indication to the HDD. This will kick off the MAC
5264 // into a 'running' state and should kick off an initial scan.
5265 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5266 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5267 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305268 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005269 "code %08d [x%08x]",__func__, halStatus, halStatus );
5270 return VOS_STATUS_E_FAILURE;
5271 }
5272
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305273 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005274 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5275 // And RIVA will crash
5276 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5277 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305278 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5279 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5280
5281
Jeff Johnson295189b2012-06-20 16:38:30 -07005282 return VOS_STATUS_SUCCESS;
5283}
5284
Jeff Johnson295189b2012-06-20 16:38:30 -07005285/* wake lock APIs for HDD */
5286void hdd_prevent_suspend(void)
5287{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005288#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005289 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005290#else
5291 wcnss_prevent_suspend();
5292#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005293}
5294
5295void hdd_allow_suspend(void)
5296{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005297#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005298 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005299#else
5300 wcnss_allow_suspend();
5301#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005302}
5303
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005304void hdd_allow_suspend_timeout(v_U32_t timeout)
5305{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005306#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005307 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005308#else
5309 /* Do nothing as there is no API in wcnss for timeout*/
5310#endif
5311}
5312
Jeff Johnson295189b2012-06-20 16:38:30 -07005313/**---------------------------------------------------------------------------
5314
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005315 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5316 information between Host and Riva
5317
5318 This function gets reported version of FW
5319 It also finds the version of Riva headers used to compile the host
5320 It compares the above two and prints a warning if they are different
5321 It gets the SW and HW version string
5322 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5323 indicating the features they support through a bitmap
5324
5325 \param - pHddCtx - Pointer to HDD context
5326
5327 \return - void
5328
5329 --------------------------------------------------------------------------*/
5330
5331void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5332{
5333
5334 tSirVersionType versionCompiled;
5335 tSirVersionType versionReported;
5336 tSirVersionString versionString;
5337 tANI_U8 fwFeatCapsMsgSupported = 0;
5338 VOS_STATUS vstatus;
5339
5340 /* retrieve and display WCNSS version information */
5341 do {
5342
5343 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5344 &versionCompiled);
5345 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5346 {
5347 hddLog(VOS_TRACE_LEVEL_FATAL,
5348 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005349 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005350 break;
5351 }
5352
5353 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5354 &versionReported);
5355 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5356 {
5357 hddLog(VOS_TRACE_LEVEL_FATAL,
5358 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005359 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005360 break;
5361 }
5362
5363 if ((versionCompiled.major != versionReported.major) ||
5364 (versionCompiled.minor != versionReported.minor) ||
5365 (versionCompiled.version != versionReported.version) ||
5366 (versionCompiled.revision != versionReported.revision))
5367 {
5368 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5369 "Host expected %u.%u.%u.%u\n",
5370 WLAN_MODULE_NAME,
5371 (int)versionReported.major,
5372 (int)versionReported.minor,
5373 (int)versionReported.version,
5374 (int)versionReported.revision,
5375 (int)versionCompiled.major,
5376 (int)versionCompiled.minor,
5377 (int)versionCompiled.version,
5378 (int)versionCompiled.revision);
5379 }
5380 else
5381 {
5382 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5383 WLAN_MODULE_NAME,
5384 (int)versionReported.major,
5385 (int)versionReported.minor,
5386 (int)versionReported.version,
5387 (int)versionReported.revision);
5388 }
5389
5390 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5391 versionString,
5392 sizeof(versionString));
5393 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5394 {
5395 hddLog(VOS_TRACE_LEVEL_FATAL,
5396 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005397 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005398 break;
5399 }
5400
5401 pr_info("%s: WCNSS software version %s\n",
5402 WLAN_MODULE_NAME, versionString);
5403
5404 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5405 versionString,
5406 sizeof(versionString));
5407 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5408 {
5409 hddLog(VOS_TRACE_LEVEL_FATAL,
5410 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005411 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005412 break;
5413 }
5414
5415 pr_info("%s: WCNSS hardware version %s\n",
5416 WLAN_MODULE_NAME, versionString);
5417
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005418 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5419 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005420 send the message only if it the riva is 1.1
5421 minor numbers for different riva branches:
5422 0 -> (1.0)Mainline Build
5423 1 -> (1.1)Mainline Build
5424 2->(1.04) Stability Build
5425 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005426 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005427 ((versionReported.minor>=1) && (versionReported.version>=1)))
5428 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5429 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005430
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005431 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005432 {
5433#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5434 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5435 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5436#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07005437 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
5438 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
5439 {
5440 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
5441 }
5442
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005443 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005444 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005445
5446 } while (0);
5447
5448}
5449
5450/**---------------------------------------------------------------------------
5451
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305452 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5453
5454 \param - pHddCtx - Pointer to the hdd context
5455
5456 \return - true if hardware supports 5GHz
5457
5458 --------------------------------------------------------------------------*/
5459static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5460{
5461 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5462 * then hardware support 5Ghz.
5463 */
5464 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5465 {
5466 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5467 return true;
5468 }
5469 else
5470 {
5471 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5472 __func__);
5473 return false;
5474 }
5475}
5476
5477
5478/**---------------------------------------------------------------------------
5479
Jeff Johnson295189b2012-06-20 16:38:30 -07005480 \brief hdd_wlan_startup() - HDD init function
5481
5482 This is the driver startup code executed once a WLAN device has been detected
5483
5484 \param - dev - Pointer to the underlying device
5485
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005486 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005487
5488 --------------------------------------------------------------------------*/
5489
5490int hdd_wlan_startup(struct device *dev )
5491{
5492 VOS_STATUS status;
5493 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005494 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005495 hdd_context_t *pHddCtx = NULL;
5496 v_CONTEXT_t pVosContext= NULL;
5497#ifdef WLAN_BTAMP_FEATURE
5498 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5499 WLANBAP_ConfigType btAmpConfig;
5500 hdd_config_t *pConfig;
5501#endif
5502 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005503 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005504
5505 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005506 /*
5507 * cfg80211: wiphy allocation
5508 */
5509 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5510
5511 if(wiphy == NULL)
5512 {
5513 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005514 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005515 }
5516
5517 pHddCtx = wiphy_priv(wiphy);
5518
Jeff Johnson295189b2012-06-20 16:38:30 -07005519 //Initialize the adapter context to zeros.
5520 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5521
Jeff Johnson295189b2012-06-20 16:38:30 -07005522 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005523 hdd_prevent_suspend();
5524 pHddCtx->isLoadUnloadInProgress = TRUE;
5525
5526 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5527
5528 /*Get vos context here bcoz vos_open requires it*/
5529 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5530
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005531 if(pVosContext == NULL)
5532 {
5533 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5534 goto err_free_hdd_context;
5535 }
5536
Jeff Johnson295189b2012-06-20 16:38:30 -07005537 //Save the Global VOSS context in adapter context for future.
5538 pHddCtx->pvosContext = pVosContext;
5539
5540 //Save the adapter context in global context for future.
5541 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5542
Jeff Johnson295189b2012-06-20 16:38:30 -07005543 pHddCtx->parent_dev = dev;
5544
5545 init_completion(&pHddCtx->full_pwr_comp_var);
5546 init_completion(&pHddCtx->standby_comp_var);
5547 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005548 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005549 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudi113ac742013-08-06 22:45:43 +05305550 init_completion(&pHddCtx->driver_crda_req);
Jeff Johnson295189b2012-06-20 16:38:30 -07005551
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05305552 spin_lock_init(&pHddCtx->schedScan_lock);
5553
Jeff Johnson295189b2012-06-20 16:38:30 -07005554 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5555
5556 // Load all config first as TL config is needed during vos_open
5557 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5558 if(pHddCtx->cfg_ini == NULL)
5559 {
5560 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5561 goto err_free_hdd_context;
5562 }
5563
5564 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5565
5566 // Read and parse the qcom_cfg.ini file
5567 status = hdd_parse_config_ini( pHddCtx );
5568 if ( VOS_STATUS_SUCCESS != status )
5569 {
5570 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5571 __func__, WLAN_INI_FILE);
5572 goto err_config;
5573 }
5574
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305575 /* INI has been read, initialise the configuredMcastBcastFilter with
5576 * INI value as this will serve as the default value
5577 */
5578 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5579 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5580 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305581
5582 if (false == hdd_is_5g_supported(pHddCtx))
5583 {
5584 //5Ghz is not supported.
5585 if (1 != pHddCtx->cfg_ini->nBandCapability)
5586 {
5587 hddLog(VOS_TRACE_LEVEL_INFO,
5588 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5589 pHddCtx->cfg_ini->nBandCapability = 1;
5590 }
5591 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05305592
5593 /* If SNR Monitoring is enabled, FW has to parse all beacons
5594 * for calcaluting and storing the average SNR, so set Nth beacon
5595 * filter to 1 to enable FW to parse all the beaocons
5596 */
5597 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
5598 {
5599 /* The log level is deliberately set to WARN as overriding
5600 * nthBeaconFilter to 1 will increase power cosumption and this
5601 * might just prove helpful to detect the power issue.
5602 */
5603 hddLog(VOS_TRACE_LEVEL_WARN,
5604 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
5605 pHddCtx->cfg_ini->nthBeaconFilter = 1;
5606 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005607 /*
5608 * cfg80211: Initialization and registration ...
5609 */
5610 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5611 {
5612 hddLog(VOS_TRACE_LEVEL_FATAL,
5613 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5614 goto err_wiphy_reg;
5615 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005616
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005617 // Update VOS trace levels based upon the cfg.ini
5618 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5619 pHddCtx->cfg_ini->vosTraceEnableBAP);
5620 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5621 pHddCtx->cfg_ini->vosTraceEnableTL);
5622 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5623 pHddCtx->cfg_ini->vosTraceEnableWDI);
5624 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5625 pHddCtx->cfg_ini->vosTraceEnableHDD);
5626 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5627 pHddCtx->cfg_ini->vosTraceEnableSME);
5628 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5629 pHddCtx->cfg_ini->vosTraceEnablePE);
5630 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5631 pHddCtx->cfg_ini->vosTraceEnableWDA);
5632 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5633 pHddCtx->cfg_ini->vosTraceEnableSYS);
5634 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5635 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005636 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5637 pHddCtx->cfg_ini->vosTraceEnableSAP);
5638 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5639 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005640
Jeff Johnson295189b2012-06-20 16:38:30 -07005641 // Update WDI trace levels based upon the cfg.ini
5642 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5643 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5644 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5645 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5646 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5647 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5648 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5649 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005650
Jeff Johnson88ba7742013-02-27 14:36:02 -08005651 if (VOS_FTM_MODE == hdd_get_conparam())
5652 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005653 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5654 {
5655 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5656 goto err_free_hdd_context;
5657 }
5658 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5659 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005660 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005661
Jeff Johnson88ba7742013-02-27 14:36:02 -08005662 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005663 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5664 {
5665 status = vos_watchdog_open(pVosContext,
5666 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5667
5668 if(!VOS_IS_STATUS_SUCCESS( status ))
5669 {
5670 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005671 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005672 }
5673 }
5674
5675 pHddCtx->isLogpInProgress = FALSE;
5676 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5677
Jeff Johnson295189b2012-06-20 16:38:30 -07005678 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5679 if(!VOS_IS_STATUS_SUCCESS(status))
5680 {
5681 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005682 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005683 }
5684
Jeff Johnson295189b2012-06-20 16:38:30 -07005685 status = vos_open( &pVosContext, 0);
5686 if ( !VOS_IS_STATUS_SUCCESS( status ))
5687 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005688 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5689 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005690 }
5691
Jeff Johnson295189b2012-06-20 16:38:30 -07005692 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5693
5694 if ( NULL == pHddCtx->hHal )
5695 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005696 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005697 goto err_vosclose;
5698 }
5699
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005700 status = vos_preStart( pHddCtx->pvosContext );
5701 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5702 {
5703 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5704 goto err_vosclose;
5705 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005706
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005707 /* Note that the vos_preStart() sequence triggers the cfg download.
5708 The cfg download must occur before we update the SME config
5709 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005710 status = hdd_set_sme_config( pHddCtx );
5711
5712 if ( VOS_STATUS_SUCCESS != status )
5713 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005714 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5715 goto err_vosclose;
5716 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005717
5718 //Initialize the WMM module
5719 status = hdd_wmm_init(pHddCtx);
5720 if (!VOS_IS_STATUS_SUCCESS(status))
5721 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005722 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005723 goto err_vosclose;
5724 }
5725
Jeff Johnson295189b2012-06-20 16:38:30 -07005726 /* In the integrated architecture we update the configuration from
5727 the INI file and from NV before vOSS has been started so that
5728 the final contents are available to send down to the cCPU */
5729
5730 // Apply the cfg.ini to cfg.dat
5731 if (FALSE == hdd_update_config_dat(pHddCtx))
5732 {
5733 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5734 goto err_vosclose;
5735 }
5736
5737 // Apply the NV to cfg.dat
5738 /* Prima Update MAC address only at here */
5739 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5740 {
5741#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5742 /* There was not a valid set of MAC Addresses in NV. See if the
5743 default addresses were modified by the cfg.ini settings. If so,
5744 we'll use them, but if not, we'll autogenerate a set of MAC
5745 addresses based upon the device serial number */
5746
5747 static const v_MACADDR_t default_address =
5748 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5749 unsigned int serialno;
5750 int i;
5751
5752 serialno = wcnss_get_serial_number();
5753 if ((0 != serialno) &&
5754 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5755 sizeof(default_address))))
5756 {
5757 /* cfg.ini has the default address, invoke autogen logic */
5758
5759 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5760 bytes of the serial number that can be used to generate
5761 the other 3 bytes of the MAC address. Mask off all but
5762 the lower 3 bytes (this will also make sure we don't
5763 overflow in the next step) */
5764 serialno &= 0x00FFFFFF;
5765
5766 /* we need a unique address for each session */
5767 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5768
5769 /* autogen all addresses */
5770 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5771 {
5772 /* start with the entire default address */
5773 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5774 /* then replace the lower 3 bytes */
5775 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5776 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5777 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5778
5779 serialno++;
5780 }
5781
5782 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5783 MAC_ADDRESS_STR,
5784 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5785 }
5786 else
5787#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5788 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005789 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005790 "%s: Invalid MAC address in NV, using MAC from ini file "
5791 MAC_ADDRESS_STR, __func__,
5792 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5793 }
5794 }
5795 {
5796 eHalStatus halStatus;
5797 // Set the MAC Address
5798 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5799 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5800 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5801 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5802
5803 if (!HAL_STATUS_SUCCESS( halStatus ))
5804 {
5805 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5806 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005807 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005808 }
5809 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005810
5811 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5812 Note: Firmware image will be read and downloaded inside vos_start API */
5813 status = vos_start( pHddCtx->pvosContext );
5814 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5815 {
5816 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5817 goto err_vosclose;
5818 }
5819
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005820 /* Exchange capability info between Host and FW and also get versioning info from FW */
5821 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005822
5823 status = hdd_post_voss_start_config( pHddCtx );
5824 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5825 {
5826 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5827 __func__);
5828 goto err_vosstop;
5829 }
5830
Jeff Johnson295189b2012-06-20 16:38:30 -07005831 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5832 {
5833 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5834 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5835 }
5836 else
5837 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005838 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5839 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5840 if (pAdapter != NULL)
5841 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305842 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005843 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305844 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5845 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5846 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005847
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305848 /* Generate the P2P Device Address. This consists of the device's
5849 * primary MAC address with the locally administered bit set.
5850 */
5851 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005852 }
5853 else
5854 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305855 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5856 if (p2p_dev_addr != NULL)
5857 {
5858 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5859 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5860 }
5861 else
5862 {
5863 hddLog(VOS_TRACE_LEVEL_FATAL,
5864 "%s: Failed to allocate mac_address for p2p_device",
5865 __func__);
5866 goto err_close_adapter;
5867 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005868 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005869
5870 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5871 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5872 if ( NULL == pP2pAdapter )
5873 {
5874 hddLog(VOS_TRACE_LEVEL_FATAL,
5875 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005876 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005877 goto err_close_adapter;
5878 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005879 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005880 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005881
5882 if( pAdapter == NULL )
5883 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005884 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5885 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005886 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005887
Jeff Johnson295189b2012-06-20 16:38:30 -07005888#ifdef WLAN_BTAMP_FEATURE
5889 vStatus = WLANBAP_Open(pVosContext);
5890 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5891 {
5892 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5893 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005894 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005895 }
5896
5897 vStatus = BSL_Init(pVosContext);
5898 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5899 {
5900 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5901 "%s: Failed to Init BSL",__func__);
5902 goto err_bap_close;
5903 }
5904 vStatus = WLANBAP_Start(pVosContext);
5905 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5906 {
5907 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5908 "%s: Failed to start TL",__func__);
5909 goto err_bap_close;
5910 }
5911
5912 pConfig = pHddCtx->cfg_ini;
5913 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5914 status = WLANBAP_SetConfig(&btAmpConfig);
5915
5916#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005917
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005918#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5919 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5920 {
5921 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5922 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5923 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5924 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5925 }
5926#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005927#ifdef FEATURE_WLAN_SCAN_PNO
5928 /*SME must send channel update configuration to RIVA*/
5929 sme_UpdateChannelConfig(pHddCtx->hHal);
5930#endif
5931
Jeff Johnson295189b2012-06-20 16:38:30 -07005932 /* Register with platform driver as client for Suspend/Resume */
5933 status = hddRegisterPmOps(pHddCtx);
5934 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5935 {
5936 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5937#ifdef WLAN_BTAMP_FEATURE
5938 goto err_bap_stop;
5939#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005940 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005941#endif //WLAN_BTAMP_FEATURE
5942 }
5943
Yue Ma0d4891e2013-08-06 17:01:45 -07005944 /* Open debugfs interface */
5945 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
5946 {
5947 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5948 "%s: hdd_debugfs_init failed!", __func__);
5949 goto err_close_debugfs;
5950 }
5951
Jeff Johnson295189b2012-06-20 16:38:30 -07005952 /* Register TM level change handler function to the platform */
5953 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5954 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5955 {
5956 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5957 goto err_unregister_pmops;
5958 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005959
5960 /* register for riva power on lock to platform driver */
5961 if (req_riva_power_on_lock("wlan"))
5962 {
5963 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5964 __func__);
5965 goto err_unregister_pmops;
5966 }
5967
Jeff Johnson295189b2012-06-20 16:38:30 -07005968 // register net device notifier for device change notification
5969 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5970
5971 if(ret < 0)
5972 {
5973 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5974 goto err_free_power_on_lock;
5975 }
5976
5977 //Initialize the nlink service
5978 if(nl_srv_init() != 0)
5979 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305980 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005981 goto err_reg_netdev;
5982 }
5983
5984 //Initialize the BTC service
5985 if(btc_activate_service(pHddCtx) != 0)
5986 {
5987 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5988 goto err_nl_srv;
5989 }
5990
5991#ifdef PTT_SOCK_SVC_ENABLE
5992 //Initialize the PTT service
5993 if(ptt_sock_activate_svc(pHddCtx) != 0)
5994 {
5995 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5996 goto err_nl_srv;
5997 }
5998#endif
5999
Jeff Johnson295189b2012-06-20 16:38:30 -07006000 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006001 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006002 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07006003 /* Action frame registered in one adapter which will
6004 * applicable to all interfaces
6005 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07006006 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006007 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006008
6009 mutex_init(&pHddCtx->sap_lock);
6010
6011 pHddCtx->isLoadUnloadInProgress = FALSE;
6012
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006013#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07006014#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
6015 /* Initialize the wake lcok */
6016 wake_lock_init(&pHddCtx->rx_wake_lock,
6017 WAKE_LOCK_SUSPEND,
6018 "qcom_rx_wakelock");
6019#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08006020 /* Initialize the wake lcok */
6021 wake_lock_init(&pHddCtx->sap_wake_lock,
6022 WAKE_LOCK_SUSPEND,
6023 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006024#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07006025
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006026 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
6027 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07006028
6029 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
6030 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05306031
Jeff Johnsone7245742012-09-05 17:12:55 -07006032 // Initialize the restart logic
6033 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05306034
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05306035 if (!VOS_IS_STATUS_SUCCESS( vos_timer_init( &pHddCtx->hdd_p2p_go_conn_is_in_progress,
6036 VOS_TIMER_TYPE_SW, wlan_hdd_p2p_go_connection_in_progresscb, pAdapter) ) )
6037 {
6038 hddLog(VOS_TRACE_LEVEL_ERROR,
6039 "%s: vos timer init failed for hdd_p2p_go_conn_is_in_progress", __func__);
6040 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006041 goto success;
6042
6043err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07006044#ifdef WLAN_KD_READY_NOTIFIER
6045 nl_srv_exit(pHddCtx->ptt_pid);
6046#else
Jeff Johnson295189b2012-06-20 16:38:30 -07006047 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07006048#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07006049err_reg_netdev:
6050 unregister_netdevice_notifier(&hdd_netdev_notifier);
6051
6052err_free_power_on_lock:
6053 free_riva_power_on_lock("wlan");
6054
6055err_unregister_pmops:
6056 hddDevTmUnregisterNotifyCallback(pHddCtx);
6057 hddDeregisterPmOps(pHddCtx);
6058
Yue Ma0d4891e2013-08-06 17:01:45 -07006059err_close_debugfs:
6060 hdd_debugfs_exit(pHddCtx);
6061
Jeff Johnson295189b2012-06-20 16:38:30 -07006062#ifdef WLAN_BTAMP_FEATURE
6063err_bap_stop:
6064 WLANBAP_Stop(pVosContext);
6065#endif
6066
6067#ifdef WLAN_BTAMP_FEATURE
6068err_bap_close:
6069 WLANBAP_Close(pVosContext);
6070#endif
6071
Jeff Johnson295189b2012-06-20 16:38:30 -07006072err_close_adapter:
6073 hdd_close_all_adapters( pHddCtx );
6074
6075err_vosstop:
6076 vos_stop(pVosContext);
6077
6078err_vosclose:
6079 status = vos_sched_close( pVosContext );
6080 if (!VOS_IS_STATUS_SUCCESS(status)) {
6081 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
6082 "%s: Failed to close VOSS Scheduler", __func__);
6083 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
6084 }
6085 vos_close(pVosContext );
6086
Jeff Johnson295189b2012-06-20 16:38:30 -07006087err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006088 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006089
6090err_wdclose:
6091 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6092 vos_watchdog_close(pVosContext);
6093
Jeff Johnson295189b2012-06-20 16:38:30 -07006094err_wiphy_reg:
6095 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006096
6097err_config:
6098 kfree(pHddCtx->cfg_ini);
6099 pHddCtx->cfg_ini= NULL;
6100
6101err_free_hdd_context:
6102 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07006103 wiphy_free(wiphy) ;
6104 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006105 VOS_BUG(1);
6106
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08006107 if (hdd_is_ssr_required())
6108 {
6109 /* WDI timeout had happened during load, so SSR is needed here */
6110 subsystem_restart("wcnss");
6111 msleep(5000);
6112 }
6113 hdd_set_ssr_required (VOS_FALSE);
6114
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006115 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006116
6117success:
6118 EXIT();
6119 return 0;
6120}
6121
6122/**---------------------------------------------------------------------------
6123
Jeff Johnson32d95a32012-09-10 13:15:23 -07006124 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07006125
Jeff Johnson32d95a32012-09-10 13:15:23 -07006126 This is the driver entry point - called in different timeline depending
6127 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07006128
6129 \param - None
6130
6131 \return - 0 for success, non zero for failure
6132
6133 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07006134static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006135{
6136 VOS_STATUS status;
6137 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006138 struct device *dev = NULL;
6139 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006140#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6141 int max_retries = 0;
6142#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006143
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306144#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6145 vos_wconn_trace_init();
6146#endif
6147
Jeff Johnson295189b2012-06-20 16:38:30 -07006148 ENTER();
6149
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006150#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006151 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07006152#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006153
6154 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
6155 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
6156
6157 //Power Up Libra WLAN card first if not already powered up
6158 status = vos_chipPowerUp(NULL,NULL,NULL);
6159 if (!VOS_IS_STATUS_SUCCESS(status))
6160 {
6161 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
6162 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306163#ifdef WLAN_OPEN_SOURCE
6164 wake_lock_destroy(&wlan_wake_lock);
6165#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006166 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006167 }
6168
Jeff Johnson295189b2012-06-20 16:38:30 -07006169#ifdef ANI_BUS_TYPE_PCI
6170
6171 dev = wcnss_wlan_get_device();
6172
6173#endif // ANI_BUS_TYPE_PCI
6174
6175#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006176
6177#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6178 /* wait until WCNSS driver downloads NV */
6179 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6180 msleep(1000);
6181 }
6182 if (max_retries >= 5) {
6183 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306184#ifdef WLAN_OPEN_SOURCE
6185 wake_lock_destroy(&wlan_wake_lock);
6186#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006187 return -ENODEV;
6188 }
6189#endif
6190
Jeff Johnson295189b2012-06-20 16:38:30 -07006191 dev = wcnss_wlan_get_device();
6192#endif // ANI_BUS_TYPE_PLATFORM
6193
6194
6195 do {
6196 if (NULL == dev) {
6197 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6198 ret_status = -1;
6199 break;
6200 }
6201
6202#ifdef MEMORY_DEBUG
6203 vos_mem_init();
6204#endif
6205
6206#ifdef TIMER_MANAGER
6207 vos_timer_manager_init();
6208#endif
6209
6210 /* Preopen VOSS so that it is ready to start at least SAL */
6211 status = vos_preOpen(&pVosContext);
6212
6213 if (!VOS_IS_STATUS_SUCCESS(status))
6214 {
6215 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6216 ret_status = -1;
6217 break;
6218 }
6219
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006220#ifndef MODULE
6221 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6222 */
6223 hdd_set_conparam((v_UINT_t)con_mode);
6224#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006225
6226 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006227 if (hdd_wlan_startup(dev))
6228 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006229 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006230 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006231 vos_preClose( &pVosContext );
6232 ret_status = -1;
6233 break;
6234 }
6235
6236 /* Cancel the vote for XO Core ON
6237 * This is done here for safety purposes in case we re-initialize without turning
6238 * it OFF in any error scenario.
6239 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006240 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006241 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006242 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006243 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6244 {
6245 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6246 " Power consumed will be high\n");
6247 }
6248 } while (0);
6249
6250 if (0 != ret_status)
6251 {
6252 //Assert Deep sleep signal now to put Libra HW in lowest power state
6253 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6254 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6255
6256 //Vote off any PMIC voltage supplies
6257 vos_chipPowerDown(NULL, NULL, NULL);
6258#ifdef TIMER_MANAGER
6259 vos_timer_exit();
6260#endif
6261#ifdef MEMORY_DEBUG
6262 vos_mem_exit();
6263#endif
6264
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006265#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006266 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006267#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006268 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6269 }
6270 else
6271 {
6272 //Send WLAN UP indication to Nlink Service
6273 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6274
6275 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07006276 }
6277
6278 EXIT();
6279
6280 return ret_status;
6281}
6282
Jeff Johnson32d95a32012-09-10 13:15:23 -07006283/**---------------------------------------------------------------------------
6284
6285 \brief hdd_module_init() - Init Function
6286
6287 This is the driver entry point (invoked when module is loaded using insmod)
6288
6289 \param - None
6290
6291 \return - 0 for success, non zero for failure
6292
6293 --------------------------------------------------------------------------*/
6294#ifdef MODULE
6295static int __init hdd_module_init ( void)
6296{
6297 return hdd_driver_init();
6298}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006299#else /* #ifdef MODULE */
6300static int __init hdd_module_init ( void)
6301{
6302 /* Driver initialization is delayed to fwpath_changed_handler */
6303 return 0;
6304}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006305#endif /* #ifdef MODULE */
6306
Jeff Johnson295189b2012-06-20 16:38:30 -07006307
6308/**---------------------------------------------------------------------------
6309
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006310 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006311
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006312 This is the driver exit point (invoked when module is unloaded using rmmod
6313 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006314
6315 \param - None
6316
6317 \return - None
6318
6319 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006320static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006321{
6322 hdd_context_t *pHddCtx = NULL;
6323 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006324 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006325
6326 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6327
6328 //Get the global vos context
6329 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6330
6331 if(!pVosContext)
6332 {
6333 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6334 goto done;
6335 }
6336
6337 //Get the HDD context.
6338 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6339
6340 if(!pHddCtx)
6341 {
6342 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6343 }
6344 else
6345 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006346 while(isWDresetInProgress()) {
6347 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6348 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006349 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006350
6351 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6352 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6353 "%s:SSR never completed, fatal error", __func__);
6354 VOS_BUG(0);
6355 }
6356 }
6357
Jeff Johnson295189b2012-06-20 16:38:30 -07006358
6359 pHddCtx->isLoadUnloadInProgress = TRUE;
6360 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6361
6362 //Do all the cleanup before deregistering the driver
6363 hdd_wlan_exit(pHddCtx);
6364 }
6365
Jeff Johnson295189b2012-06-20 16:38:30 -07006366 vos_preClose( &pVosContext );
6367
6368#ifdef TIMER_MANAGER
6369 vos_timer_exit();
6370#endif
6371#ifdef MEMORY_DEBUG
6372 vos_mem_exit();
6373#endif
6374
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306375#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6376 vos_wconn_trace_exit();
6377#endif
6378
Jeff Johnson295189b2012-06-20 16:38:30 -07006379done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006380#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006381 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006382#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006383 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6384}
6385
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006386/**---------------------------------------------------------------------------
6387
6388 \brief hdd_module_exit() - Exit function
6389
6390 This is the driver exit point (invoked when module is unloaded using rmmod)
6391
6392 \param - None
6393
6394 \return - None
6395
6396 --------------------------------------------------------------------------*/
6397static void __exit hdd_module_exit(void)
6398{
6399 hdd_driver_exit();
6400}
6401
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006402#ifdef MODULE
6403static int fwpath_changed_handler(const char *kmessage,
6404 struct kernel_param *kp)
6405{
Jeff Johnson76052702013-04-16 13:55:05 -07006406 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006407}
6408
6409static int con_mode_handler(const char *kmessage,
6410 struct kernel_param *kp)
6411{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006412 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006413}
6414#else /* #ifdef MODULE */
6415/**---------------------------------------------------------------------------
6416
Jeff Johnson76052702013-04-16 13:55:05 -07006417 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006418
Jeff Johnson76052702013-04-16 13:55:05 -07006419 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006420 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006421 - invoked when module parameter fwpath is modified from userspace to signal
6422 initializing the WLAN driver or when con_mode is modified from userspace
6423 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006424
6425 \return - 0 for success, non zero for failure
6426
6427 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006428static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006429{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006430 int ret_status;
6431
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006432 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006433 ret_status = hdd_driver_init();
6434 wlan_hdd_inited = ret_status ? 0 : 1;
6435 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006436 }
6437
6438 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006439
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006440 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006441
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006442 ret_status = hdd_driver_init();
6443 wlan_hdd_inited = ret_status ? 0 : 1;
6444 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006445}
6446
Jeff Johnson295189b2012-06-20 16:38:30 -07006447/**---------------------------------------------------------------------------
6448
Jeff Johnson76052702013-04-16 13:55:05 -07006449 \brief fwpath_changed_handler() - Handler Function
6450
6451 Handle changes to the fwpath parameter
6452
6453 \return - 0 for success, non zero for failure
6454
6455 --------------------------------------------------------------------------*/
6456static int fwpath_changed_handler(const char *kmessage,
6457 struct kernel_param *kp)
6458{
6459 int ret;
6460
6461 ret = param_set_copystring(kmessage, kp);
6462 if (0 == ret)
6463 ret = kickstart_driver();
6464 return ret;
6465}
6466
6467/**---------------------------------------------------------------------------
6468
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006469 \brief con_mode_handler() -
6470
6471 Handler function for module param con_mode when it is changed by userspace
6472 Dynamically linked - do nothing
6473 Statically linked - exit and init driver, as in rmmod and insmod
6474
Jeff Johnson76052702013-04-16 13:55:05 -07006475 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006476
Jeff Johnson76052702013-04-16 13:55:05 -07006477 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006478
6479 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006480static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006481{
Jeff Johnson76052702013-04-16 13:55:05 -07006482 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006483
Jeff Johnson76052702013-04-16 13:55:05 -07006484 ret = param_set_int(kmessage, kp);
6485 if (0 == ret)
6486 ret = kickstart_driver();
6487 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006488}
6489#endif /* #ifdef MODULE */
6490
6491/**---------------------------------------------------------------------------
6492
Jeff Johnson295189b2012-06-20 16:38:30 -07006493 \brief hdd_get_conparam() -
6494
6495 This is the driver exit point (invoked when module is unloaded using rmmod)
6496
6497 \param - None
6498
6499 \return - tVOS_CON_MODE
6500
6501 --------------------------------------------------------------------------*/
6502tVOS_CON_MODE hdd_get_conparam ( void )
6503{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006504#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006505 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006506#else
6507 return (tVOS_CON_MODE)curr_con_mode;
6508#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006509}
6510void hdd_set_conparam ( v_UINT_t newParam )
6511{
6512 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006513#ifndef MODULE
6514 curr_con_mode = con_mode;
6515#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006516}
6517/**---------------------------------------------------------------------------
6518
6519 \brief hdd_softap_sta_deauth() - function
6520
6521 This to take counter measure to handle deauth req from HDD
6522
6523 \param - pAdapter - Pointer to the HDD
6524
6525 \param - enable - boolean value
6526
6527 \return - None
6528
6529 --------------------------------------------------------------------------*/
6530
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006531VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006532{
Jeff Johnson295189b2012-06-20 16:38:30 -07006533 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006534 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006535
6536 ENTER();
6537
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07006538 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
6539 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006540
6541 //Ignore request to deauth bcmc station
6542 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006543 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006544
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006545 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006546
6547 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006548 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006549}
6550
6551/**---------------------------------------------------------------------------
6552
6553 \brief hdd_softap_sta_disassoc() - function
6554
6555 This to take counter measure to handle deauth req from HDD
6556
6557 \param - pAdapter - Pointer to the HDD
6558
6559 \param - enable - boolean value
6560
6561 \return - None
6562
6563 --------------------------------------------------------------------------*/
6564
6565void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6566{
6567 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6568
6569 ENTER();
6570
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306571 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006572
6573 //Ignore request to disassoc bcmc station
6574 if( pDestMacAddress[0] & 0x1 )
6575 return;
6576
6577 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6578}
6579
6580void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6581{
6582 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6583
6584 ENTER();
6585
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306586 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006587
6588 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6589}
6590
Jeff Johnson295189b2012-06-20 16:38:30 -07006591/**---------------------------------------------------------------------------
6592 *
6593 * \brief hdd_get__concurrency_mode() -
6594 *
6595 *
6596 * \param - None
6597 *
6598 * \return - CONCURRENCY MODE
6599 *
6600 * --------------------------------------------------------------------------*/
6601tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6602{
6603 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6604 hdd_context_t *pHddCtx;
6605
6606 if (NULL != pVosContext)
6607 {
6608 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6609 if (NULL != pHddCtx)
6610 {
6611 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6612 }
6613 }
6614
6615 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006616 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006617 return VOS_STA;
6618}
6619
6620/* Decide whether to allow/not the apps power collapse.
6621 * Allow apps power collapse if we are in connected state.
6622 * if not, allow only if we are in IMPS */
6623v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6624{
6625 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006626 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006627 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006628 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6629 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6630 hdd_adapter_t *pAdapter = NULL;
6631 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006632 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006633
Jeff Johnson295189b2012-06-20 16:38:30 -07006634 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6635 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006636
Yathish9f22e662012-12-10 14:21:35 -08006637 concurrent_state = hdd_get_concurrency_mode();
6638
6639#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6640 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6641 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6642 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6643 return TRUE;
6644#endif
6645
Jeff Johnson295189b2012-06-20 16:38:30 -07006646 /*loop through all adapters. TBD fix for Concurrency */
6647 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6648 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6649 {
6650 pAdapter = pAdapterNode->pAdapter;
6651 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6652 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6653 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006654 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006655 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006656 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006657 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6658 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006659 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006660 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006661 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6662 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006663 return FALSE;
6664 }
6665 }
6666 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6667 pAdapterNode = pNext;
6668 }
6669 return TRUE;
6670}
6671
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006672/* Decides whether to send suspend notification to Riva
6673 * if any adapter is in BMPS; then it is required */
6674v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6675{
6676 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6677 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6678
6679 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6680 {
6681 return TRUE;
6682 }
6683 return FALSE;
6684}
6685
Jeff Johnson295189b2012-06-20 16:38:30 -07006686void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6687{
6688 switch(mode)
6689 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006690 case VOS_STA_MODE:
6691 case VOS_P2P_CLIENT_MODE:
6692 case VOS_P2P_GO_MODE:
6693 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006694 pHddCtx->concurrency_mode |= (1 << mode);
6695 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006696 break;
6697 default:
6698 break;
6699
6700 }
6701 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6702 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6703}
6704
6705
6706void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6707{
6708 switch(mode)
6709 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006710 case VOS_STA_MODE:
6711 case VOS_P2P_CLIENT_MODE:
6712 case VOS_P2P_GO_MODE:
6713 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006714 pHddCtx->no_of_sessions[mode]--;
6715 if (!(pHddCtx->no_of_sessions[mode]))
6716 pHddCtx->concurrency_mode &= (~(1 << mode));
6717 break;
6718 default:
6719 break;
6720 }
6721 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6722 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6723}
6724
Jeff Johnsone7245742012-09-05 17:12:55 -07006725/**---------------------------------------------------------------------------
6726 *
6727 * \brief wlan_hdd_restart_init
6728 *
6729 * This function initalizes restart timer/flag. An internal function.
6730 *
6731 * \param - pHddCtx
6732 *
6733 * \return - None
6734 *
6735 * --------------------------------------------------------------------------*/
6736
6737static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6738{
6739 /* Initialize */
6740 pHddCtx->hdd_restart_retries = 0;
6741 atomic_set(&pHddCtx->isRestartInProgress, 0);
6742 vos_timer_init(&pHddCtx->hdd_restart_timer,
6743 VOS_TIMER_TYPE_SW,
6744 wlan_hdd_restart_timer_cb,
6745 pHddCtx);
6746}
6747/**---------------------------------------------------------------------------
6748 *
6749 * \brief wlan_hdd_restart_deinit
6750 *
6751 * This function cleans up the resources used. An internal function.
6752 *
6753 * \param - pHddCtx
6754 *
6755 * \return - None
6756 *
6757 * --------------------------------------------------------------------------*/
6758
6759static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6760{
6761
6762 VOS_STATUS vos_status;
6763 /* Block any further calls */
6764 atomic_set(&pHddCtx->isRestartInProgress, 1);
6765 /* Cleanup */
6766 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6767 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006768 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006769 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6770 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006771 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006772
6773}
6774
6775/**---------------------------------------------------------------------------
6776 *
6777 * \brief wlan_hdd_framework_restart
6778 *
6779 * This function uses a cfg80211 API to start a framework initiated WLAN
6780 * driver module unload/load.
6781 *
6782 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6783 *
6784 *
6785 * \param - pHddCtx
6786 *
6787 * \return - VOS_STATUS_SUCCESS: Success
6788 * VOS_STATUS_E_EMPTY: Adapter is Empty
6789 * VOS_STATUS_E_NOMEM: No memory
6790
6791 * --------------------------------------------------------------------------*/
6792
6793static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6794{
6795 VOS_STATUS status = VOS_STATUS_SUCCESS;
6796 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006797 int len = (sizeof (struct ieee80211_mgmt));
6798 struct ieee80211_mgmt *mgmt = NULL;
6799
6800 /* Prepare the DEAUTH managment frame with reason code */
6801 mgmt = kzalloc(len, GFP_KERNEL);
6802 if(mgmt == NULL)
6803 {
6804 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6805 "%s: memory allocation failed (%d bytes)", __func__, len);
6806 return VOS_STATUS_E_NOMEM;
6807 }
6808 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006809
6810 /* Iterate over all adapters/devices */
6811 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6812 do
6813 {
6814 if( (status == VOS_STATUS_SUCCESS) &&
6815 pAdapterNode &&
6816 pAdapterNode->pAdapter)
6817 {
6818 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6819 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6820 pAdapterNode->pAdapter->dev->name,
6821 pAdapterNode->pAdapter->device_mode,
6822 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006823 /*
6824 * CFG80211 event to restart the driver
6825 *
6826 * 'cfg80211_send_unprot_deauth' sends a
6827 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6828 * of SME(Linux Kernel) state machine.
6829 *
6830 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6831 * the driver.
6832 *
6833 */
6834
6835 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006836 }
6837 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6838 pAdapterNode = pNext;
6839 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6840
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006841
6842 /* Free the allocated management frame */
6843 kfree(mgmt);
6844
Jeff Johnsone7245742012-09-05 17:12:55 -07006845 /* Retry until we unload or reach max count */
6846 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6847 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6848
6849 return status;
6850
6851}
6852/**---------------------------------------------------------------------------
6853 *
6854 * \brief wlan_hdd_restart_timer_cb
6855 *
6856 * Restart timer callback. An internal function.
6857 *
6858 * \param - User data:
6859 *
6860 * \return - None
6861 *
6862 * --------------------------------------------------------------------------*/
6863
6864void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6865{
6866 hdd_context_t *pHddCtx = usrDataForCallback;
6867 wlan_hdd_framework_restart(pHddCtx);
6868 return;
6869
6870}
6871
6872
6873/**---------------------------------------------------------------------------
6874 *
6875 * \brief wlan_hdd_restart_driver
6876 *
6877 * This function sends an event to supplicant to restart the WLAN driver.
6878 *
6879 * This function is called from vos_wlanRestart.
6880 *
6881 * \param - pHddCtx
6882 *
6883 * \return - VOS_STATUS_SUCCESS: Success
6884 * VOS_STATUS_E_EMPTY: Adapter is Empty
6885 * VOS_STATUS_E_ALREADY: Request already in progress
6886
6887 * --------------------------------------------------------------------------*/
6888VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6889{
6890 VOS_STATUS status = VOS_STATUS_SUCCESS;
6891
6892 /* A tight check to make sure reentrancy */
6893 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6894 {
6895 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6896 "%s: WLAN restart is already in progress", __func__);
6897
6898 return VOS_STATUS_E_ALREADY;
6899 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006900 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006901#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006902 wcnss_reset_intr();
6903#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006904
Jeff Johnsone7245742012-09-05 17:12:55 -07006905 return status;
6906}
6907
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006908/*
6909 * API to find if there is any STA or P2P-Client is connected
6910 */
6911VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6912{
6913 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6914}
Jeff Johnsone7245742012-09-05 17:12:55 -07006915
Jeff Johnson295189b2012-06-20 16:38:30 -07006916//Register the module init/exit functions
6917module_init(hdd_module_init);
6918module_exit(hdd_module_exit);
6919
6920MODULE_LICENSE("Dual BSD/GPL");
6921MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6922MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6923
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006924module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6925 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006926
Jeff Johnson76052702013-04-16 13:55:05 -07006927module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006928 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);