blob: a850e406eb1bfb3b86a5b294c30867f6bb3f330c [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
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127#ifdef MODULE
128#define WLAN_MODULE_NAME module_name(THIS_MODULE)
129#else
130#define WLAN_MODULE_NAME "wlan"
131#endif
132
133#ifdef TIMER_MANAGER
134#define TIMER_MANAGER_STR " +TIMER_MANAGER"
135#else
136#define TIMER_MANAGER_STR ""
137#endif
138
139#ifdef MEMORY_DEBUG
140#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
141#else
142#define MEMORY_DEBUG_STR ""
143#endif
144
145/* the Android framework expects this param even though we don't use it */
146#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700147static char fwpath_buffer[BUF_LEN];
148static struct kparam_string fwpath = {
149 .string = fwpath_buffer,
150 .maxlen = BUF_LEN,
151};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700152#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700153static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700154#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700155
Jeff Johnsone7245742012-09-05 17:12:55 -0700156/*
157 * The rate at which the driver sends RESTART event to supplicant
158 * once the function 'vos_wlanRestart()' is called
159 *
160 */
161#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
162#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700163
164/*
165 * Size of Driver command strings from upper layer
166 */
167#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
168#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
169
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800170#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700171static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700172#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700173/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700174static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700175
176//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700177static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
178static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
179static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
180void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800181void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700182
Jeff Johnson295189b2012-06-20 16:38:30 -0700183v_U16_t hdd_select_queue(struct net_device *dev,
184 struct sk_buff *skb);
185
186#ifdef WLAN_FEATURE_PACKET_FILTERING
187static void hdd_set_multicast_list(struct net_device *dev);
188#endif
189
190void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700191int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700192
193extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800194#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
195void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
196static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
197static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700198static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
199 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
200 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700201static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
202 tANI_U8 *pTargetApBssid,
203 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800204#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700205static int hdd_netdev_notifier_call(struct notifier_block * nb,
206 unsigned long state,
207 void *ndev)
208{
209 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700210 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700211 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700212#ifdef WLAN_BTAMP_FEATURE
213 VOS_STATUS status;
214 hdd_context_t *pHddCtx;
215#endif
216
217 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700218 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700219 (strncmp(dev->name, "p2p", 3)))
220 return NOTIFY_DONE;
221
222 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700223 return NOTIFY_DONE;
224
Jeff Johnson295189b2012-06-20 16:38:30 -0700225 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700226 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700227
Jeff Johnson27cee452013-03-27 11:10:24 -0700228 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700229 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800230 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700231 VOS_ASSERT(0);
232 return NOTIFY_DONE;
233 }
234
Jeff Johnson27cee452013-03-27 11:10:24 -0700235 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
236 if (NULL == pHddCtx)
237 {
238 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
239 VOS_ASSERT(0);
240 return NOTIFY_DONE;
241 }
242
243 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
244 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700245
246 switch (state) {
247 case NETDEV_REGISTER:
248 break;
249
250 case NETDEV_UNREGISTER:
251 break;
252
253 case NETDEV_UP:
254 break;
255
256 case NETDEV_DOWN:
257 break;
258
259 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700260 if(TRUE == pAdapter->isLinkUpSvcNeeded)
261 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700262 break;
263
264 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700265 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700266 {
267 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800268 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700269 hdd_abort_mac_scan(pAdapter->pHddCtx);
270 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800271 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700272 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
273 if(!result)
274 {
275 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800276 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700277 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700278 }
279 }
280 else
281 {
282 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700283 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700284 }
285#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700286 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700287 status = WLANBAP_StopAmp();
288 if(VOS_STATUS_SUCCESS != status )
289 {
290 pHddCtx->isAmpAllowed = VOS_TRUE;
291 hddLog(VOS_TRACE_LEVEL_FATAL,
292 "%s: Failed to stop AMP", __func__);
293 }
294 else
295 {
296 //a state m/c implementation in PAL is TBD to avoid this delay
297 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700298 if ( pHddCtx->isAmpAllowed )
299 {
300 WLANBAP_DeregisterFromHCI();
301 pHddCtx->isAmpAllowed = VOS_FALSE;
302 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700303 }
304#endif //WLAN_BTAMP_FEATURE
305 break;
306
307 default:
308 break;
309 }
310
311 return NOTIFY_DONE;
312}
313
314struct notifier_block hdd_netdev_notifier = {
315 .notifier_call = hdd_netdev_notifier_call,
316};
317
318/*---------------------------------------------------------------------------
319 * Function definitions
320 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700321void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
322void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700323//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700324static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700325#ifndef MODULE
326/* current con_mode - used only for statically linked driver
327 * con_mode is changed by userspace to indicate a mode change which will
328 * result in calling the module exit and init functions. The module
329 * exit function will clean up based on the value of con_mode prior to it
330 * being changed by userspace. So curr_con_mode records the current con_mode
331 * for exit when con_mode becomes the next mode for init
332 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700333static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700334#endif
335
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800336/**---------------------------------------------------------------------------
337
338 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
339
340 Called immediately after the cfg.ini is read in order to configure
341 the desired trace levels.
342
343 \param - moduleId - module whose trace level is being configured
344 \param - bitmask - bitmask of log levels to be enabled
345
346 \return - void
347
348 --------------------------------------------------------------------------*/
349static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
350{
351 wpt_tracelevel level;
352
353 /* if the bitmask is the default value, then a bitmask was not
354 specified in cfg.ini, so leave the logging level alone (it
355 will remain at the "compiled in" default value) */
356 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
357 {
358 return;
359 }
360
361 /* a mask was specified. start by disabling all logging */
362 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
363
364 /* now cycle through the bitmask until all "set" bits are serviced */
365 level = VOS_TRACE_LEVEL_FATAL;
366 while (0 != bitmask)
367 {
368 if (bitmask & 1)
369 {
370 vos_trace_setValue(moduleId, level, 1);
371 }
372 level++;
373 bitmask >>= 1;
374 }
375}
376
377
Jeff Johnson295189b2012-06-20 16:38:30 -0700378/**---------------------------------------------------------------------------
379
380 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
381
382 Called immediately after the cfg.ini is read in order to configure
383 the desired trace levels in the WDI.
384
385 \param - moduleId - module whose trace level is being configured
386 \param - bitmask - bitmask of log levels to be enabled
387
388 \return - void
389
390 --------------------------------------------------------------------------*/
391static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
392{
393 wpt_tracelevel level;
394
395 /* if the bitmask is the default value, then a bitmask was not
396 specified in cfg.ini, so leave the logging level alone (it
397 will remain at the "compiled in" default value) */
398 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
399 {
400 return;
401 }
402
403 /* a mask was specified. start by disabling all logging */
404 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
405
406 /* now cycle through the bitmask until all "set" bits are serviced */
407 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
408 while (0 != bitmask)
409 {
410 if (bitmask & 1)
411 {
412 wpalTraceSetLevel(moduleId, level, 1);
413 }
414 level++;
415 bitmask >>= 1;
416 }
417}
Jeff Johnson295189b2012-06-20 16:38:30 -0700418
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530419/*
420 * FUNCTION: wlan_hdd_validate_context
421 * This function is used to check the HDD context
422 */
423int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
424{
425 ENTER();
426
427 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
428 {
429 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
430 "%s: HDD context is Null", __func__);
431 return -ENODEV;
432 }
433
434 if (pHddCtx->isLogpInProgress)
435 {
436 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
437 "%s: LOGP in Progress. Ignore!!!", __func__);
438 return -EAGAIN;
439 }
440
441 if (pHddCtx->isLoadUnloadInProgress)
442 {
443 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
444 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
445 return -EAGAIN;
446 }
447 return 0;
448}
449
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530450void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
451{
452 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
453 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
454 hdd_config_t *cfg_param;
455 eCsrPhyMode phyMode;
456
457 if (NULL == pHddCtx)
458 {
459 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
460 "HDD Context is null !!");
461 return ;
462 }
463
464 cfg_param = pHddCtx->cfg_ini;
465
466 if (NULL == cfg_param)
467 {
468 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
469 "cfg_params not available !!");
470 return ;
471 }
472
473 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
474
475 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
476 {
477 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
478 (eCSR_DOT11_MODE_11ac == phyMode) ||
479 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
480 {
481 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
482 "Setting phymode to 11n!!");
483 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
484 }
485 }
486 else
487 {
488 /*New country Supports 11ac as well resetting value back from .ini*/
489 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
490 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
491 return ;
492 }
493
494 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
495 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
496 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
497 {
498 VOS_STATUS vosStatus;
499
500 // need to issue a disconnect to CSR.
501 INIT_COMPLETION(pAdapter->disconnect_comp_var);
502 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
503 pAdapter->sessionId,
504 eCSR_DISCONNECT_REASON_UNSPECIFIED );
505
506 if (VOS_STATUS_SUCCESS == vosStatus)
507 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
508 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
509
510 }
511}
512
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700513void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
514{
515 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
516 hdd_config_t *cfg_param;
517
518 if (NULL == pHddCtx)
519 {
520 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
521 "HDD Context is null !!");
522 return ;
523 }
524
525 cfg_param = pHddCtx->cfg_ini;
526
527 if (NULL == cfg_param)
528 {
529 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
530 "cfg_params not available !!");
531 return ;
532 }
533
534 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
535 {
536 /*New country doesn't support DFS */
537 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
538 }
539 else
540 {
541 /*New country Supports DFS as well resetting value back from .ini*/
542 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
543 }
544
545}
546
Jeff Johnson295189b2012-06-20 16:38:30 -0700547int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
548{
549 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
550 hdd_priv_data_t priv_data;
551 tANI_U8 *command = NULL;
552 int ret = 0;
553
554 if (NULL == pAdapter)
555 {
556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700557 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700558 ret = -ENODEV;
559 goto exit;
560 }
561
Jeff Johnsone7245742012-09-05 17:12:55 -0700562 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700563 {
564 ret = -EINVAL;
565 goto exit;
566 }
567
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -0700568 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
569 {
570 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
571 "%s:LOGP in Progress. Ignore!!!", __func__);
572 ret = -EBUSY;
573 goto exit;
574 }
575
Jeff Johnson295189b2012-06-20 16:38:30 -0700576 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
577 {
578 ret = -EFAULT;
579 goto exit;
580 }
581
582 command = kmalloc(priv_data.total_len, GFP_KERNEL);
583 if (!command)
584 {
585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700586 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700587 ret = -ENOMEM;
588 goto exit;
589 }
590
591 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
592 {
593 ret = -EFAULT;
594 goto exit;
595 }
596
597 if ((SIOCDEVPRIVATE + 1) == cmd)
598 {
599 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
600
601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700602 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700603
604 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
605 {
606 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
607 sizeof(tSirMacAddr)))
608 {
609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700610 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700611 ret = -EFAULT;
612 }
613 }
Amar Singhal0974e402013-02-12 14:27:46 -0800614 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700615 {
Amar Singhal0974e402013-02-12 14:27:46 -0800616 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700617 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800618
Jeff Johnson295189b2012-06-20 16:38:30 -0700619 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800620
621 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700623 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800624 "%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 -0700625 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800626 ret = hdd_setBand_helper(dev, ptr);
627 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700628 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
629 {
630 char *country_code;
631
632 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700633
634 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530635 hdd_checkandupdate_phymode(pAdapter, country_code);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700636 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
Gopichand Nakkalaacd94112013-05-29 21:37:47 +0530637 pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700638 if( 0 != ret )
639 {
640 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
641 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
642
643 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700644 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800645#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
646 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
647 {
648 tANI_U8 *value = command;
649 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
650 tANI_U8 revision = 0;
651 eHalStatus status = eHAL_STATUS_SUCCESS;
652 v_REGDOMAIN_t regId;
653
654 status = hdd_parse_countryrev(value, countryCode, &revision);
655 if (eHAL_STATUS_SUCCESS != status)
656 {
657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
658 "%s: Failed to parse country revision information", __func__);
659 ret = -EINVAL;
660 goto exit;
661 }
662
663 /* Validate country code */
664 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
665 if (eHAL_STATUS_SUCCESS != status)
666 {
667 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
668 "%s: Invalid country code %s", __func__, countryCode);
669 ret = -EINVAL;
670 goto exit;
671 }
672
673 /* Validate revision */
674 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
675 {
676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
677 "%s: Invalid revision %d", __func__, revision);
678 ret = -EINVAL;
679 goto exit;
680 }
681
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700682 hdd_checkandupdate_dfssetting(pAdapter, countryCode);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530683 hdd_checkandupdate_phymode(pAdapter, countryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800684 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
Gopichand Nakkalaacd94112013-05-29 21:37:47 +0530685 pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800686 if (0 != ret)
687 {
688 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
689 "%s: SME Change Country code fail ret=%d", __func__, ret);
690 ret = -EINVAL;
691 goto exit;
692 }
693
694 if (0 == strncmp(countryCode, "KR", 2))
695 {
696 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
697 revision);
698 if (eHAL_STATUS_SUCCESS != status)
699 {
700 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
701 "%s: Failed to build valid channel list", __func__);
702 ret = -EINVAL;
703 goto exit;
704 }
705 }
706 }
707#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700708 /*
709 command should be a string having format
710 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
711 */
Amar Singhal0974e402013-02-12 14:27:46 -0800712 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700713 {
Amar Singhal0974e402013-02-12 14:27:46 -0800714 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700715
716 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700717 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700718
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800719 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700720 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800721 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
722 {
723 int suspend = 0;
724 tANI_U8 *ptr = (tANI_U8*)command + 15;
725
726 suspend = *ptr - '0';
727 hdd_set_wlan_suspend_mode(suspend);
728 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800729#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
730 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
731 {
732 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700733 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800734 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
735 eHalStatus status = eHAL_STATUS_SUCCESS;
736
737 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
738 value = value + 15;
739
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700740 /* Convert the value from ascii to integer */
741 ret = kstrtos8(value, 10, &rssi);
742 if (ret < 0)
743 {
744 /* If the input value is greater than max value of datatype, then also
745 kstrtou8 fails */
746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
747 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
748 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
749 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
750 ret = -EINVAL;
751 goto exit;
752 }
753
Srinivas Girigowdade697412013-02-14 16:31:48 -0800754 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700755
Srinivas Girigowdade697412013-02-14 16:31:48 -0800756 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
757 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
758 {
759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
760 "Neighbor lookup threshold value %d is out of range"
761 " (Min: %d Max: %d)", lookUpThreshold,
762 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
763 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
764 ret = -EINVAL;
765 goto exit;
766 }
767
768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
769 "%s: Received Command to Set Roam trigger"
770 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
771
772 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
773 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
774 if (eHAL_STATUS_SUCCESS != status)
775 {
776 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
777 "%s: Failed to set roam trigger, try again", __func__);
778 ret = -EPERM;
779 goto exit;
780 }
781
782 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
783 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
784 }
785 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
786 {
787 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
788 int rssi = (-1) * lookUpThreshold;
789 char extra[32];
790 tANI_U8 len = 0;
791
792 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
793 if (copy_to_user(priv_data.buf, &extra, len + 1))
794 {
795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
796 "%s: failed to copy data to user buffer", __func__);
797 ret = -EFAULT;
798 goto exit;
799 }
800 }
801 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
802 {
803 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700804 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700805 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700806
Srinivas Girigowdade697412013-02-14 16:31:48 -0800807 /* input refresh period is in terms of seconds */
808 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
809 value = value + 18;
810 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700811 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800812 if (ret < 0)
813 {
814 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700815 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800816 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700817 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -0800818 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700819 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
820 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800821 ret = -EINVAL;
822 goto exit;
823 }
824
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700825 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
826 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800827 {
828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700829 "Roam scan period value %d is out of range"
830 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700831 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
832 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800833 ret = -EINVAL;
834 goto exit;
835 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700836 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800837
838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
839 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700840 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800841
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700842 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
843 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800844 }
845 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
846 {
847 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
848 char extra[32];
849 tANI_U8 len = 0;
850
851 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
852 /* Returned value is in units of seconds */
853 if (copy_to_user(priv_data.buf, &extra, len + 1))
854 {
855 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
856 "%s: failed to copy data to user buffer", __func__);
857 ret = -EFAULT;
858 goto exit;
859 }
860 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700861 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
862 {
863 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700864 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700865 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700866
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700867 /* input refresh period is in terms of seconds */
868 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
869 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700870
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700871 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700872 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700873 if (ret < 0)
874 {
875 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700876 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700877 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700878 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700879 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700880 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
881 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
882 ret = -EINVAL;
883 goto exit;
884 }
885
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700886 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
887 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
888 {
889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
890 "Neighbor scan results refresh period value %d is out of range"
891 " (Min: %d Max: %d)", roamScanRefreshPeriod,
892 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
893 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
894 ret = -EINVAL;
895 goto exit;
896 }
897 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
898
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
900 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700901 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700902
903 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
904 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
905 }
906 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
907 {
908 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
909 char extra[32];
910 tANI_U8 len = 0;
911
912 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
913 /* Returned value is in units of seconds */
914 if (copy_to_user(priv_data.buf, &extra, len + 1))
915 {
916 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
917 "%s: failed to copy data to user buffer", __func__);
918 ret = -EFAULT;
919 goto exit;
920 }
921 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700922#ifdef FEATURE_WLAN_LFR
923 /* SETROAMMODE */
924 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
925 {
926 tANI_U8 *value = command;
927 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
928
929 /* Move pointer to ahead of SETROAMMODE<delimiter> */
930 value = value + SIZE_OF_SETROAMMODE + 1;
931
932 /* Convert the value from ascii to integer */
933 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
934 if (ret < 0)
935 {
936 /* If the input value is greater than max value of datatype, then also
937 kstrtou8 fails */
938 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
939 "%s: kstrtou8 failed range [%d - %d]", __func__,
940 CFG_LFR_FEATURE_ENABLED_MIN,
941 CFG_LFR_FEATURE_ENABLED_MAX);
942 ret = -EINVAL;
943 goto exit;
944 }
945 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
946 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
947 {
948 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
949 "Roam Mode value %d is out of range"
950 " (Min: %d Max: %d)", roamMode,
951 CFG_LFR_FEATURE_ENABLED_MIN,
952 CFG_LFR_FEATURE_ENABLED_MAX);
953 ret = -EINVAL;
954 goto exit;
955 }
956
957 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
958 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
959 /*
960 * Note that
961 * SETROAMMODE 0 is to enable LFR while
962 * SETROAMMODE 1 is to disable LFR, but
963 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
964 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
965 */
966 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
967 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
968 else
969 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
970
971 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
972 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
973 }
974 /* GETROAMMODE */
975 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
976 {
977 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
978 char extra[32];
979 tANI_U8 len = 0;
980
981 /*
982 * roamMode value shall be inverted because the sementics is different.
983 */
984 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
985 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
986 else
987 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
988
989 len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode);
990 if (copy_to_user(priv_data.buf, &extra, len + 1))
991 {
992 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
993 "%s: failed to copy data to user buffer", __func__);
994 ret = -EFAULT;
995 goto exit;
996 }
997 }
998#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -0800999#endif
1000#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1001 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
1002 {
1003 tANI_U8 *value = command;
1004 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
1005
1006 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
1007 value = value + 13;
1008 /* Convert the value from ascii to integer */
1009 ret = kstrtou8(value, 10, &roamRssiDiff);
1010 if (ret < 0)
1011 {
1012 /* If the input value is greater than max value of datatype, then also
1013 kstrtou8 fails */
1014 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1015 "%s: kstrtou8 failed range [%d - %d]", __func__,
1016 CFG_ROAM_RSSI_DIFF_MIN,
1017 CFG_ROAM_RSSI_DIFF_MAX);
1018 ret = -EINVAL;
1019 goto exit;
1020 }
1021
1022 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1023 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1024 {
1025 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1026 "Roam rssi diff value %d is out of range"
1027 " (Min: %d Max: %d)", roamRssiDiff,
1028 CFG_ROAM_RSSI_DIFF_MIN,
1029 CFG_ROAM_RSSI_DIFF_MAX);
1030 ret = -EINVAL;
1031 goto exit;
1032 }
1033
1034 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1035 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1036
1037 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1038 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1039 }
1040 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1041 {
1042 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1043 char extra[32];
1044 tANI_U8 len = 0;
1045
1046 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
1047 if (copy_to_user(priv_data.buf, &extra, len + 1))
1048 {
1049 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1050 "%s: failed to copy data to user buffer", __func__);
1051 ret = -EFAULT;
1052 goto exit;
1053 }
1054 }
1055#endif
1056#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1057 else if (strncmp(command, "GETBAND", 7) == 0)
1058 {
1059 int band = -1;
1060 char extra[32];
1061 tANI_U8 len = 0;
1062 hdd_getBand_helper(pHddCtx, &band);
1063
1064 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
1065 if (copy_to_user(priv_data.buf, &extra, len + 1))
1066 {
1067 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1068 "%s: failed to copy data to user buffer", __func__);
1069 ret = -EFAULT;
1070 goto exit;
1071 }
1072 }
1073 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
1074 {
1075 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
1076 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
1077 tANI_U8 revision = 0;
1078 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
1079 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
1080 char extra[32] = {0};
1081 tANI_U8 len = 0;
1082
1083 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
1084 {
1085 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1086 "%s: failed to get country code", __func__);
1087 ret = -EFAULT;
1088 goto exit;
1089 }
1090 pBuf[uBufLen] = '\0';
1091 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
1092
1093 if (0 == strncmp(pBuf, "KR", 2))
1094 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
1095 else
1096 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
1097
1098 if (copy_to_user(priv_data.buf, &extra, len + 1))
1099 {
1100 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1101 "%s: failed to copy data to user buffer", __func__);
1102 ret = -EFAULT;
1103 goto exit;
1104 }
1105 }
1106 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1107 {
1108 tANI_U8 *value = command;
1109 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1110 tANI_U8 numChannels = 0;
1111 eHalStatus status = eHAL_STATUS_SUCCESS;
1112
1113 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1114 if (eHAL_STATUS_SUCCESS != status)
1115 {
1116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1117 "%s: Failed to parse channel list information", __func__);
1118 ret = -EINVAL;
1119 goto exit;
1120 }
1121
1122 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1123 {
1124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1125 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1126 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1127 ret = -EINVAL;
1128 goto exit;
1129 }
1130 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1131 numChannels);
1132 if (eHAL_STATUS_SUCCESS != status)
1133 {
1134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1135 "%s: Failed to update channel list information", __func__);
1136 ret = -EINVAL;
1137 goto exit;
1138 }
1139 }
1140 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1141 {
1142 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1143 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001144 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001145 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001146 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001147
1148 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1149 ChannelList, &numChannels ))
1150 {
1151 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1152 "%s: failed to get roam scan channel list", __func__);
1153 ret = -EFAULT;
1154 goto exit;
1155 }
1156 /* output channel list is of the format
1157 [Number of roam scan channels][Channel1][Channel2]... */
1158 /* copy the number of channels in the 0th index */
1159 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1160 for (j = 0; (j < numChannels); j++)
1161 {
1162 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1163 }
1164
1165 if (copy_to_user(priv_data.buf, &extra, len + 1))
1166 {
1167 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1168 "%s: failed to copy data to user buffer", __func__);
1169 ret = -EFAULT;
1170 goto exit;
1171 }
1172 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001173 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1174 {
1175 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1176 char extra[32];
1177 tANI_U8 len = 0;
1178
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001179 /* Check if the features OKC/CCX/11R are supported simultaneously,
1180 then this operation is not permitted (return FAILURE) */
1181 if (ccxMode &&
1182 hdd_is_okc_mode_enabled(pHddCtx) &&
1183 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1184 {
1185 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1186 "%s: OKC/CCX/11R are supported simultaneously"
1187 " hence this operation is not permitted!", __func__);
1188 ret = -EPERM;
1189 goto exit;
1190 }
1191
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001192 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1193 if (copy_to_user(priv_data.buf, &extra, len + 1))
1194 {
1195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1196 "%s: failed to copy data to user buffer", __func__);
1197 ret = -EFAULT;
1198 goto exit;
1199 }
1200 }
1201 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1202 {
1203 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1204 char extra[32];
1205 tANI_U8 len = 0;
1206
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001207 /* Check if the features OKC/CCX/11R are supported simultaneously,
1208 then this operation is not permitted (return FAILURE) */
1209 if (okcMode &&
1210 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1211 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1212 {
1213 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1214 "%s: OKC/CCX/11R are supported simultaneously"
1215 " hence this operation is not permitted!", __func__);
1216 ret = -EPERM;
1217 goto exit;
1218 }
1219
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001220 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1221 if (copy_to_user(priv_data.buf, &extra, len + 1))
1222 {
1223 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1224 "%s: failed to copy data to user buffer", __func__);
1225 ret = -EFAULT;
1226 goto exit;
1227 }
1228 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001229 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001230 {
1231 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1232 char extra[32];
1233 tANI_U8 len = 0;
1234
1235 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1236 if (copy_to_user(priv_data.buf, &extra, len + 1))
1237 {
1238 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1239 "%s: failed to copy data to user buffer", __func__);
1240 ret = -EFAULT;
1241 goto exit;
1242 }
1243 }
1244 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1245 {
1246 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1247 char extra[32];
1248 tANI_U8 len = 0;
1249
1250 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1251 if (copy_to_user(priv_data.buf, &extra, len + 1))
1252 {
1253 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1254 "%s: failed to copy data to user buffer", __func__);
1255 ret = -EFAULT;
1256 goto exit;
1257 }
1258 }
1259 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1260 {
1261 tANI_U8 *value = command;
1262 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1263
1264 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1265 value = value + 26;
1266 /* Convert the value from ascii to integer */
1267 ret = kstrtou8(value, 10, &minTime);
1268 if (ret < 0)
1269 {
1270 /* If the input value is greater than max value of datatype, then also
1271 kstrtou8 fails */
1272 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1273 "%s: kstrtou8 failed range [%d - %d]", __func__,
1274 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1275 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1276 ret = -EINVAL;
1277 goto exit;
1278 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001279 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1280 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1281 {
1282 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1283 "scan min channel time value %d is out of range"
1284 " (Min: %d Max: %d)", minTime,
1285 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1286 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1287 ret = -EINVAL;
1288 goto exit;
1289 }
1290
1291 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1292 "%s: Received Command to change channel min time = %d", __func__, minTime);
1293
1294 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1295 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1296 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001297 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1298 {
1299 tANI_U8 *value = command;
1300 tANI_U8 channel = 0;
1301 tANI_U8 dwellTime = 0;
1302 tANI_U8 bufLen = 0;
1303 tANI_U8 *buf = NULL;
1304 tSirMacAddr targetApBssid;
1305 eHalStatus status = eHAL_STATUS_SUCCESS;
1306 struct ieee80211_channel chan;
1307 tANI_U8 finalLen = 0;
1308 tANI_U8 *finalBuf = NULL;
1309 tANI_U8 temp = 0;
1310 u64 cookie;
1311 hdd_station_ctx_t *pHddStaCtx = NULL;
1312 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1313
1314 /* if not associated, no need to send action frame */
1315 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1316 {
1317 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1318 ret = -EINVAL;
1319 goto exit;
1320 }
1321
1322 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1323 &dwellTime, &buf, &bufLen);
1324 if (eHAL_STATUS_SUCCESS != status)
1325 {
1326 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1327 "%s: Failed to parse send action frame data", __func__);
1328 ret = -EINVAL;
1329 goto exit;
1330 }
1331
1332 /* if the target bssid is different from currently associated AP,
1333 then no need to send action frame */
1334 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1335 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1336 {
1337 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1338 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001339 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001340 goto exit;
1341 }
1342
1343 /* if the channel number is different from operating channel then
1344 no need to send action frame */
1345 if (channel != pHddStaCtx->conn_info.operationChannel)
1346 {
1347 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1348 "%s: channel(%d) is different from operating channel(%d)",
1349 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1350 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001351 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001352 goto exit;
1353 }
1354 chan.center_freq = sme_ChnToFreq(channel);
1355
1356 finalLen = bufLen + 24;
1357 finalBuf = vos_mem_malloc(finalLen);
1358 if (NULL == finalBuf)
1359 {
1360 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1361 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001362 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001363 goto exit;
1364 }
1365 vos_mem_zero(finalBuf, finalLen);
1366
1367 /* Fill subtype */
1368 temp = SIR_MAC_MGMT_ACTION << 4;
1369 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1370
1371 /* Fill type */
1372 temp = SIR_MAC_MGMT_FRAME;
1373 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1374
1375 /* Fill destination address (bssid of the AP) */
1376 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1377
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001378 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001379 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1380
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001381 /* Fill BSSID (AP mac address) */
1382 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001383
1384 /* Fill received buffer from 24th address */
1385 vos_mem_copy(finalBuf + 24, buf, bufLen);
1386
Jeff Johnson11c33152013-04-16 17:52:40 -07001387 /* done with the parsed buffer */
1388 vos_mem_free(buf);
1389
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001390 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1391 1, dwellTime, finalBuf, finalLen, 1,
1392 1, &cookie );
1393 vos_mem_free(finalBuf);
1394 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001395 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1396 {
1397 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1398 char extra[32];
1399 tANI_U8 len = 0;
1400
1401 /* value is interms of msec */
1402 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1403 if (copy_to_user(priv_data.buf, &extra, len + 1))
1404 {
1405 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1406 "%s: failed to copy data to user buffer", __func__);
1407 ret = -EFAULT;
1408 goto exit;
1409 }
1410 }
1411 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1412 {
1413 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001414 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001415 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001416
1417 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1418 value = value + 19;
1419 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001420 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001421 if (ret < 0)
1422 {
1423 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001424 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001425 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001426 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001427 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1428 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1429 ret = -EINVAL;
1430 goto exit;
1431 }
1432
1433 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1434 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1435 {
1436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1437 "lfr mode value %d is out of range"
1438 " (Min: %d Max: %d)", maxTime,
1439 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1440 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1441 ret = -EINVAL;
1442 goto exit;
1443 }
1444
1445 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1446 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1447
1448 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001449
1450 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1451 * where RFS is the RF Switching time. It is twice RFS to consider the
1452 * time to go off channel and return to the home channel. */
1453 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1454 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1455 {
1456 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1457 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1458 " Hence enforcing home away time to disable (0)",
1459 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1460 homeAwayTime = 0;
1461 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1462 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
1463 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001464 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1465 }
1466 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1467 {
1468 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1469 char extra[32];
1470 tANI_U8 len = 0;
1471
1472 /* value is interms of msec */
1473 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1474 if (copy_to_user(priv_data.buf, &extra, len + 1))
1475 {
1476 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1477 "%s: failed to copy data to user buffer", __func__);
1478 ret = -EFAULT;
1479 goto exit;
1480 }
1481 }
1482 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1483 {
1484 tANI_U8 *value = command;
1485 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1486
1487 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1488 value = value + 16;
1489 /* Convert the value from ascii to integer */
1490 ret = kstrtou16(value, 10, &val);
1491 if (ret < 0)
1492 {
1493 /* If the input value is greater than max value of datatype, then also
1494 kstrtou16 fails */
1495 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1496 "%s: kstrtou16 failed range [%d - %d]", __func__,
1497 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1498 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1499 ret = -EINVAL;
1500 goto exit;
1501 }
1502
1503 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1504 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1505 {
1506 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1507 "scan home time value %d is out of range"
1508 " (Min: %d Max: %d)", val,
1509 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1510 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1511 ret = -EINVAL;
1512 goto exit;
1513 }
1514
1515 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1516 "%s: Received Command to change scan home time = %d", __func__, val);
1517
1518 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1519 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1520 }
1521 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1522 {
1523 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1524 char extra[32];
1525 tANI_U8 len = 0;
1526
1527 /* value is interms of msec */
1528 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1529 if (copy_to_user(priv_data.buf, &extra, len + 1))
1530 {
1531 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1532 "%s: failed to copy data to user buffer", __func__);
1533 ret = -EFAULT;
1534 goto exit;
1535 }
1536 }
1537 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1538 {
1539 tANI_U8 *value = command;
1540 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1541
1542 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1543 value = value + 17;
1544 /* Convert the value from ascii to integer */
1545 ret = kstrtou8(value, 10, &val);
1546 if (ret < 0)
1547 {
1548 /* If the input value is greater than max value of datatype, then also
1549 kstrtou8 fails */
1550 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1551 "%s: kstrtou8 failed range [%d - %d]", __func__,
1552 CFG_ROAM_INTRA_BAND_MIN,
1553 CFG_ROAM_INTRA_BAND_MAX);
1554 ret = -EINVAL;
1555 goto exit;
1556 }
1557
1558 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1559 (val > CFG_ROAM_INTRA_BAND_MAX))
1560 {
1561 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1562 "intra band mode value %d is out of range"
1563 " (Min: %d Max: %d)", val,
1564 CFG_ROAM_INTRA_BAND_MIN,
1565 CFG_ROAM_INTRA_BAND_MAX);
1566 ret = -EINVAL;
1567 goto exit;
1568 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1570 "%s: Received Command to change intra band = %d", __func__, val);
1571
1572 pHddCtx->cfg_ini->nRoamIntraBand = val;
1573 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1574 }
1575 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1576 {
1577 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1578 char extra[32];
1579 tANI_U8 len = 0;
1580
1581 /* value is interms of msec */
1582 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1583 if (copy_to_user(priv_data.buf, &extra, len + 1))
1584 {
1585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1586 "%s: failed to copy data to user buffer", __func__);
1587 ret = -EFAULT;
1588 goto exit;
1589 }
1590 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001591 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1592 {
1593 tANI_U8 *value = command;
1594 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1595
1596 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1597 value = value + 15;
1598 /* Convert the value from ascii to integer */
1599 ret = kstrtou8(value, 10, &nProbes);
1600 if (ret < 0)
1601 {
1602 /* If the input value is greater than max value of datatype, then also
1603 kstrtou8 fails */
1604 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1605 "%s: kstrtou8 failed range [%d - %d]", __func__,
1606 CFG_ROAM_SCAN_N_PROBES_MIN,
1607 CFG_ROAM_SCAN_N_PROBES_MAX);
1608 ret = -EINVAL;
1609 goto exit;
1610 }
1611
1612 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1613 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1614 {
1615 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1616 "NProbes value %d is out of range"
1617 " (Min: %d Max: %d)", nProbes,
1618 CFG_ROAM_SCAN_N_PROBES_MIN,
1619 CFG_ROAM_SCAN_N_PROBES_MAX);
1620 ret = -EINVAL;
1621 goto exit;
1622 }
1623
1624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1625 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1626
1627 pHddCtx->cfg_ini->nProbes = nProbes;
1628 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1629 }
1630 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1631 {
1632 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1633 char extra[32];
1634 tANI_U8 len = 0;
1635
1636 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1637 if (copy_to_user(priv_data.buf, &extra, len + 1))
1638 {
1639 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1640 "%s: failed to copy data to user buffer", __func__);
1641 ret = -EFAULT;
1642 goto exit;
1643 }
1644 }
1645 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1646 {
1647 tANI_U8 *value = command;
1648 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001649 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001650
1651 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1652 /* input value is in units of msec */
1653 value = value + 20;
1654 /* Convert the value from ascii to integer */
1655 ret = kstrtou16(value, 10, &homeAwayTime);
1656 if (ret < 0)
1657 {
1658 /* If the input value is greater than max value of datatype, then also
1659 kstrtou8 fails */
1660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1661 "%s: kstrtou8 failed range [%d - %d]", __func__,
1662 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1663 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1664 ret = -EINVAL;
1665 goto exit;
1666 }
1667
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001668 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1669 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1670 {
1671 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1672 "homeAwayTime value %d is out of range"
1673 " (Min: %d Max: %d)", homeAwayTime,
1674 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1675 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1676 ret = -EINVAL;
1677 goto exit;
1678 }
1679
1680 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1681 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1682
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001683 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1684 * where RFS is the RF Switching time. It is twice RFS to consider the
1685 * time to go off channel and return to the home channel. */
1686 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1687 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1688 {
1689 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1690 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1691 " Hence enforcing home away time to disable (0)",
1692 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1693 homeAwayTime = 0;
1694 }
1695
1696 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
1697 {
1698 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1699 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
1700 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001701 }
1702 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1703 {
1704 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1705 char extra[32];
1706 tANI_U8 len = 0;
1707
1708 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1709 if (copy_to_user(priv_data.buf, &extra, len + 1))
1710 {
1711 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1712 "%s: failed to copy data to user buffer", __func__);
1713 ret = -EFAULT;
1714 goto exit;
1715 }
1716 }
1717 else if (strncmp(command, "REASSOC", 7) == 0)
1718 {
1719 tANI_U8 *value = command;
1720 tANI_U8 channel = 0;
1721 tSirMacAddr targetApBssid;
1722 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001723#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1724 tCsrHandoffRequest handoffInfo;
1725#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001726 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001727 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1728
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001729 /* if not associated, no need to proceed with reassoc */
1730 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1731 {
1732 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1733 ret = -EINVAL;
1734 goto exit;
1735 }
1736
1737 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1738 if (eHAL_STATUS_SUCCESS != status)
1739 {
1740 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1741 "%s: Failed to parse reassoc command data", __func__);
1742 ret = -EINVAL;
1743 goto exit;
1744 }
1745
1746 /* if the target bssid is same as currently associated AP,
1747 then no need to proceed with reassoc */
1748 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1749 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1750 {
1751 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1752 ret = -EINVAL;
1753 goto exit;
1754 }
1755
1756 /* Check channel number is a valid channel number */
1757 if(VOS_STATUS_SUCCESS !=
1758 wlan_hdd_validate_operation_channel(pAdapter, channel))
1759 {
1760 hddLog(VOS_TRACE_LEVEL_ERROR,
1761 "%s: Invalid Channel [%d] \n", __func__, channel);
1762 return -EINVAL;
1763 }
1764
1765 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001766#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1767 handoffInfo.channel = channel;
1768 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1769 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1770#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001771 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001772#endif
1773#ifdef FEATURE_WLAN_LFR
1774 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1775 {
1776 tANI_U8 *value = command;
1777 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1778
1779 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1780 value = value + 12;
1781 /* Convert the value from ascii to integer */
1782 ret = kstrtou8(value, 10, &lfrMode);
1783 if (ret < 0)
1784 {
1785 /* If the input value is greater than max value of datatype, then also
1786 kstrtou8 fails */
1787 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1788 "%s: kstrtou8 failed range [%d - %d]", __func__,
1789 CFG_LFR_FEATURE_ENABLED_MIN,
1790 CFG_LFR_FEATURE_ENABLED_MAX);
1791 ret = -EINVAL;
1792 goto exit;
1793 }
1794
1795 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1796 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1797 {
1798 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1799 "lfr mode value %d is out of range"
1800 " (Min: %d Max: %d)", lfrMode,
1801 CFG_LFR_FEATURE_ENABLED_MIN,
1802 CFG_LFR_FEATURE_ENABLED_MAX);
1803 ret = -EINVAL;
1804 goto exit;
1805 }
1806
1807 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1808 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1809
1810 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1811 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1812 }
1813#endif
1814#ifdef WLAN_FEATURE_VOWIFI_11R
1815 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1816 {
1817 tANI_U8 *value = command;
1818 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1819
1820 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1821 value = value + 18;
1822 /* Convert the value from ascii to integer */
1823 ret = kstrtou8(value, 10, &ft);
1824 if (ret < 0)
1825 {
1826 /* If the input value is greater than max value of datatype, then also
1827 kstrtou8 fails */
1828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1829 "%s: kstrtou8 failed range [%d - %d]", __func__,
1830 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1831 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1832 ret = -EINVAL;
1833 goto exit;
1834 }
1835
1836 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1837 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1838 {
1839 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1840 "ft mode value %d is out of range"
1841 " (Min: %d Max: %d)", ft,
1842 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1843 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1844 ret = -EINVAL;
1845 goto exit;
1846 }
1847
1848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1849 "%s: Received Command to change ft mode = %d", __func__, ft);
1850
1851 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1852 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1853 }
1854#endif
1855#ifdef FEATURE_WLAN_CCX
1856 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1857 {
1858 tANI_U8 *value = command;
1859 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1860
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001861 /* Check if the features OKC/CCX/11R are supported simultaneously,
1862 then this operation is not permitted (return FAILURE) */
1863 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1864 hdd_is_okc_mode_enabled(pHddCtx) &&
1865 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1866 {
1867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1868 "%s: OKC/CCX/11R are supported simultaneously"
1869 " hence this operation is not permitted!", __func__);
1870 ret = -EPERM;
1871 goto exit;
1872 }
1873
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001874 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1875 value = value + 11;
1876 /* Convert the value from ascii to integer */
1877 ret = kstrtou8(value, 10, &ccxMode);
1878 if (ret < 0)
1879 {
1880 /* If the input value is greater than max value of datatype, then also
1881 kstrtou8 fails */
1882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1883 "%s: kstrtou8 failed range [%d - %d]", __func__,
1884 CFG_CCX_FEATURE_ENABLED_MIN,
1885 CFG_CCX_FEATURE_ENABLED_MAX);
1886 ret = -EINVAL;
1887 goto exit;
1888 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001889 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1890 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1891 {
1892 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1893 "Ccx mode value %d is out of range"
1894 " (Min: %d Max: %d)", ccxMode,
1895 CFG_CCX_FEATURE_ENABLED_MIN,
1896 CFG_CCX_FEATURE_ENABLED_MAX);
1897 ret = -EINVAL;
1898 goto exit;
1899 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1901 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1902
1903 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1904 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1905 }
1906#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001907 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1908 {
1909 tANI_U8 *value = command;
1910 tANI_BOOLEAN roamScanControl = 0;
1911
1912 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1913 value = value + 19;
1914 /* Convert the value from ascii to integer */
1915 ret = kstrtou8(value, 10, &roamScanControl);
1916 if (ret < 0)
1917 {
1918 /* If the input value is greater than max value of datatype, then also
1919 kstrtou8 fails */
1920 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1921 "%s: kstrtou8 failed ", __func__);
1922 ret = -EINVAL;
1923 goto exit;
1924 }
1925
1926 if (0 != roamScanControl)
1927 {
1928 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1929 "roam scan control invalid value = %d",
1930 roamScanControl);
1931 ret = -EINVAL;
1932 goto exit;
1933 }
1934 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1935 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1936
1937 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1938 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001939#ifdef FEATURE_WLAN_OKC
1940 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1941 {
1942 tANI_U8 *value = command;
1943 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1944
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07001945 /* Check if the features OKC/CCX/11R are supported simultaneously,
1946 then this operation is not permitted (return FAILURE) */
1947 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
1948 hdd_is_okc_mode_enabled(pHddCtx) &&
1949 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
1950 {
1951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1952 "%s: OKC/CCX/11R are supported simultaneously"
1953 " hence this operation is not permitted!", __func__);
1954 ret = -EPERM;
1955 goto exit;
1956 }
1957
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001958 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1959 value = value + 11;
1960 /* Convert the value from ascii to integer */
1961 ret = kstrtou8(value, 10, &okcMode);
1962 if (ret < 0)
1963 {
1964 /* If the input value is greater than max value of datatype, then also
1965 kstrtou8 fails */
1966 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1967 "%s: kstrtou8 failed range [%d - %d]", __func__,
1968 CFG_OKC_FEATURE_ENABLED_MIN,
1969 CFG_OKC_FEATURE_ENABLED_MAX);
1970 ret = -EINVAL;
1971 goto exit;
1972 }
1973
1974 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1975 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1976 {
1977 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1978 "Okc mode value %d is out of range"
1979 " (Min: %d Max: %d)", okcMode,
1980 CFG_OKC_FEATURE_ENABLED_MIN,
1981 CFG_OKC_FEATURE_ENABLED_MAX);
1982 ret = -EINVAL;
1983 goto exit;
1984 }
1985
1986 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1987 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1988
1989 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1990 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001991 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1992 {
1993 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1994 char extra[32];
1995 tANI_U8 len = 0;
1996
1997 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1998 if (copy_to_user(priv_data.buf, &extra, len + 1))
1999 {
2000 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2001 "%s: failed to copy data to user buffer", __func__);
2002 ret = -EFAULT;
2003 goto exit;
2004 }
2005 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002006#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05302007#ifdef WLAN_FEATURE_PACKET_FILTERING
2008 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
2009 {
2010 tANI_U8 filterType = 0;
2011 tANI_U8 *value = command;
2012
2013 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
2014 value = value + 22;
2015
2016 /* Convert the value from ascii to integer */
2017 ret = kstrtou8(value, 10, &filterType);
2018 if (ret < 0)
2019 {
2020 /* If the input value is greater than max value of datatype,
2021 * then also kstrtou8 fails
2022 */
2023 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2024 "%s: kstrtou8 failed range ", __func__);
2025 ret = -EINVAL;
2026 goto exit;
2027 }
2028
2029 if (filterType != 0 && filterType != 1)
2030 {
2031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2032 "%s: Accepted Values are 0 and 1 ", __func__);
2033 ret = -EINVAL;
2034 goto exit;
2035 }
2036 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
2037 pAdapter->sessionId);
2038 }
2039#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05302040 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
2041 {
2042 char *dhcpPhase;
2043 dhcpPhase = command + 12;
2044 if ('1' == *dhcpPhase)
2045 {
2046 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
2047 pAdapter->macAddressCurrent.bytes);
2048 }
2049 else if ('2' == *dhcpPhase)
2050 {
2051 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
2052 pAdapter->macAddressCurrent.bytes);
2053 }
2054 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07002055 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
2056 {
2057 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
2058 }
2059 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
2060 {
2061 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
2062 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002063 else {
2064 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2065 __func__, command);
2066 }
2067
Jeff Johnson295189b2012-06-20 16:38:30 -07002068 }
2069exit:
2070 if (command)
2071 {
2072 kfree(command);
2073 }
2074 return ret;
2075}
2076
Srinivas Girigowdade697412013-02-14 16:31:48 -08002077#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2078void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2079{
2080 eCsrBand band = -1;
2081 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2082 switch (band)
2083 {
2084 case eCSR_BAND_ALL:
2085 *pBand = WLAN_HDD_UI_BAND_AUTO;
2086 break;
2087
2088 case eCSR_BAND_24:
2089 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2090 break;
2091
2092 case eCSR_BAND_5G:
2093 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2094 break;
2095
2096 default:
2097 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2098 *pBand = -1;
2099 break;
2100 }
2101}
2102
2103/**---------------------------------------------------------------------------
2104
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002105 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2106
2107 This function parses the send action frame data passed in the format
2108 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2109
2110 \param - pValue Pointer to input country code revision
2111 \param - pTargetApBssid Pointer to target Ap bssid
2112 \param - pChannel Pointer to the Target AP channel
2113 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2114 \param - pBuf Pointer to data
2115 \param - pBufLen Pointer to data length
2116
2117 \return - 0 for success non-zero for failure
2118
2119 --------------------------------------------------------------------------*/
2120VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2121 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2122{
2123 tANI_U8 *inPtr = pValue;
2124 tANI_U8 *dataEnd;
2125 int tempInt;
2126 int j = 0;
2127 int i = 0;
2128 int v = 0;
2129 tANI_U8 tempBuf[32];
2130 tANI_U8 tempByte = 0;
2131
2132 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2133 /*no argument after the command*/
2134 if (NULL == inPtr)
2135 {
2136 return -EINVAL;
2137 }
2138
2139 /*no space after the command*/
2140 else if (SPACE_ASCII_VALUE != *inPtr)
2141 {
2142 return -EINVAL;
2143 }
2144
2145 /*removing empty spaces*/
2146 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2147
2148 /*no argument followed by spaces*/
2149 if ('\0' == *inPtr)
2150 {
2151 return -EINVAL;
2152 }
2153
2154 /*getting the first argument ie the target AP bssid */
2155 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2156 {
2157 return -EINVAL;
2158 }
2159 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2160 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2161 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2162
2163 /* point to the next argument */
2164 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2165 /*no argument after the command*/
2166 if (NULL == inPtr) return -EINVAL;
2167
2168 /*removing empty spaces*/
2169 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2170
2171 /*no argument followed by spaces*/
2172 if ('\0' == *inPtr)
2173 {
2174 return -EINVAL;
2175 }
2176
2177 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002178 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002179 v = kstrtos32(tempBuf, 10, &tempInt);
2180 if ( v < 0) return -EINVAL;
2181
2182 *pChannel = tempInt;
2183
2184 /* point to the next argument */
2185 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2186 /*no argument after the command*/
2187 if (NULL == inPtr) return -EINVAL;
2188 /*removing empty spaces*/
2189 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2190
2191 /*no argument followed by spaces*/
2192 if ('\0' == *inPtr)
2193 {
2194 return -EINVAL;
2195 }
2196
2197 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002198 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002199 v = kstrtos32(tempBuf, 10, &tempInt);
2200 if ( v < 0) return -EINVAL;
2201
2202 *pDwellTime = tempInt;
2203
2204 /* point to the next argument */
2205 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2206 /*no argument after the command*/
2207 if (NULL == inPtr) return -EINVAL;
2208 /*removing empty spaces*/
2209 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2210
2211 /*no argument followed by spaces*/
2212 if ('\0' == *inPtr)
2213 {
2214 return -EINVAL;
2215 }
2216
2217 /* find the length of data */
2218 dataEnd = inPtr;
2219 while(('\0' != *dataEnd) )
2220 {
2221 dataEnd++;
2222 ++(*pBufLen);
2223 }
2224 if ( *pBufLen <= 0) return -EINVAL;
2225
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002226 /* Allocate the number of bytes based on the number of input characters
2227 whether it is even or odd.
2228 if the number of input characters are even, then we need N/2 byte.
2229 if the number of input characters are odd, then we need do (N+1)/2 to
2230 compensate rounding off.
2231 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2232 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2233 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002234 if (NULL == *pBuf)
2235 {
2236 hddLog(VOS_TRACE_LEVEL_FATAL,
2237 "%s: vos_mem_alloc failed ", __func__);
2238 return -EINVAL;
2239 }
2240
2241 /* the buffer received from the upper layer is character buffer,
2242 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2243 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2244 and f0 in 3rd location */
2245 for (i = 0, j = 0; j < *pBufLen; j += 2)
2246 {
2247 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2248 (*pBuf)[i++] = tempByte;
2249 }
2250 *pBufLen = i;
2251 return VOS_STATUS_SUCCESS;
2252}
2253
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002254/**---------------------------------------------------------------------------
2255
Srinivas Girigowdade697412013-02-14 16:31:48 -08002256 \brief hdd_parse_countryrev() - HDD Parse country code revision
2257
2258 This function parses the country code revision passed in the format
2259 SETCOUNTRYREV<space><Country code><space>revision
2260
2261 \param - pValue Pointer to input country code revision
2262 \param - pCountryCode Pointer to local output array to record country code
2263 \param - pRevision Pointer to store revision integer number
2264
2265 \return - 0 for success non-zero for failure
2266
2267 --------------------------------------------------------------------------*/
2268VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
2269{
2270 tANI_U8 *inPtr = pValue;
2271 int tempInt;
2272
2273 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2274 /*no argument after the command*/
2275 if (NULL == inPtr)
2276 {
2277 return -EINVAL;
2278 }
2279
2280 /*no space after the command*/
2281 else if (SPACE_ASCII_VALUE != *inPtr)
2282 {
2283 return -EINVAL;
2284 }
2285
2286 /*removing empty spaces*/
2287 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
2288
2289 /*no argument followed by spaces*/
2290 if ('\0' == *inPtr)
2291 {
2292 return -EINVAL;
2293 }
2294
2295 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07002296 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002297
2298 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2299 "Country code is : %s", pCountryCode);
2300
2301 /*inPtr pointing to the beginning of first space after country code */
2302 inPtr = strpbrk( inPtr, " " );
2303 /*no revision number after the country code argument */
2304 if (NULL == inPtr)
2305 {
2306 return -EINVAL;
2307 }
2308
2309 inPtr++;
2310
2311 /*removing empty space*/
2312 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2313
2314 /*no channel list after the number of channels argument and spaces*/
2315 if (0 == strncmp(pCountryCode, "KR", 2))
2316 {
2317 if ('\0' == *inPtr)
2318 {
2319 return -EINVAL;
2320 }
2321
2322 sscanf(inPtr, "%d", &tempInt);
2323 *pRevision = tempInt;
2324 }
2325 else
2326 {
2327 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2328 "Revision input is required only for Country KR");
2329 return -EINVAL;
2330 }
2331 return VOS_STATUS_SUCCESS;
2332}
2333
2334/**---------------------------------------------------------------------------
2335
2336 \brief hdd_parse_channellist() - HDD Parse channel list
2337
2338 This function parses the channel list passed in the format
2339 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002340 if the Number of channels (N) does not match with the actual number of channels passed
2341 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2342 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2343 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2344 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002345
2346 \param - pValue Pointer to input channel list
2347 \param - ChannelList Pointer to local output array to record channel list
2348 \param - pNumChannels Pointer to number of roam scan channels
2349
2350 \return - 0 for success non-zero for failure
2351
2352 --------------------------------------------------------------------------*/
2353VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2354{
2355 tANI_U8 *inPtr = pValue;
2356 int tempInt;
2357 int j = 0;
2358 int v = 0;
2359 char buf[32];
2360
2361 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2362 /*no argument after the command*/
2363 if (NULL == inPtr)
2364 {
2365 return -EINVAL;
2366 }
2367
2368 /*no space after the command*/
2369 else if (SPACE_ASCII_VALUE != *inPtr)
2370 {
2371 return -EINVAL;
2372 }
2373
2374 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002375 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002376
2377 /*no argument followed by spaces*/
2378 if ('\0' == *inPtr)
2379 {
2380 return -EINVAL;
2381 }
2382
2383 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002384 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002385 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002386 if ((v < 0) ||
2387 (tempInt <= 0) ||
2388 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2389 {
2390 return -EINVAL;
2391 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002392
2393 *pNumChannels = tempInt;
2394
2395 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2396 "Number of channels are: %d", *pNumChannels);
2397
2398 for (j = 0; j < (*pNumChannels); j++)
2399 {
2400 /*inPtr pointing to the beginning of first space after number of channels*/
2401 inPtr = strpbrk( inPtr, " " );
2402 /*no channel list after the number of channels argument*/
2403 if (NULL == inPtr)
2404 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002405 if (0 != j)
2406 {
2407 *pNumChannels = j;
2408 return VOS_STATUS_SUCCESS;
2409 }
2410 else
2411 {
2412 return -EINVAL;
2413 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002414 }
2415
2416 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002417 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002418
2419 /*no channel list after the number of channels argument and spaces*/
2420 if ( '\0' == *inPtr )
2421 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002422 if (0 != j)
2423 {
2424 *pNumChannels = j;
2425 return VOS_STATUS_SUCCESS;
2426 }
2427 else
2428 {
2429 return -EINVAL;
2430 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002431 }
2432
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002433 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002434 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002435 if ((v < 0) ||
2436 (tempInt <= 0) ||
2437 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2438 {
2439 return -EINVAL;
2440 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002441 pChannelList[j] = tempInt;
2442
2443 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2444 "Channel %d added to preferred channel list",
2445 pChannelList[j] );
2446 }
2447
Srinivas Girigowdade697412013-02-14 16:31:48 -08002448 return VOS_STATUS_SUCCESS;
2449}
2450
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002451
2452/**---------------------------------------------------------------------------
2453
2454 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2455
2456 This function parses the reasoc command data passed in the format
2457 REASSOC<space><bssid><space><channel>
2458
2459 \param - pValue Pointer to input country code revision
2460 \param - pTargetApBssid Pointer to target Ap bssid
2461 \param - pChannel Pointer to the Target AP channel
2462
2463 \return - 0 for success non-zero for failure
2464
2465 --------------------------------------------------------------------------*/
2466VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2467{
2468 tANI_U8 *inPtr = pValue;
2469 int tempInt;
2470 int v = 0;
2471 tANI_U8 tempBuf[32];
2472
2473 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2474 /*no argument after the command*/
2475 if (NULL == inPtr)
2476 {
2477 return -EINVAL;
2478 }
2479
2480 /*no space after the command*/
2481 else if (SPACE_ASCII_VALUE != *inPtr)
2482 {
2483 return -EINVAL;
2484 }
2485
2486 /*removing empty spaces*/
2487 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2488
2489 /*no argument followed by spaces*/
2490 if ('\0' == *inPtr)
2491 {
2492 return -EINVAL;
2493 }
2494
2495 /*getting the first argument ie the target AP bssid */
2496 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2497 {
2498 return -EINVAL;
2499 }
2500 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2501 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2502 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2503
2504 /* point to the next argument */
2505 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2506 /*no argument after the command*/
2507 if (NULL == inPtr) return -EINVAL;
2508
2509 /*removing empty spaces*/
2510 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2511
2512 /*no argument followed by spaces*/
2513 if ('\0' == *inPtr)
2514 {
2515 return -EINVAL;
2516 }
2517
2518 /*getting the next argument ie the channel number */
2519 sscanf(inPtr, "%s ", tempBuf);
2520 v = kstrtos32(tempBuf, 10, &tempInt);
2521 if ( v < 0) return -EINVAL;
2522
2523 *pChannel = tempInt;
2524 return VOS_STATUS_SUCCESS;
2525}
2526
2527#endif
2528
Jeff Johnson295189b2012-06-20 16:38:30 -07002529/**---------------------------------------------------------------------------
2530
2531 \brief hdd_open() - HDD Open function
2532
2533 This is called in response to ifconfig up
2534
2535 \param - dev Pointer to net_device structure
2536
2537 \return - 0 for success non-zero for failure
2538
2539 --------------------------------------------------------------------------*/
2540int hdd_open (struct net_device *dev)
2541{
2542 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2543 hdd_context_t *pHddCtx;
2544 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2545 VOS_STATUS status;
2546 v_BOOL_t in_standby = TRUE;
2547
2548 if (NULL == pAdapter)
2549 {
2550 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002551 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002552 return -ENODEV;
2553 }
2554
2555 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2556 if (NULL == pHddCtx)
2557 {
2558 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002559 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002560 return -ENODEV;
2561 }
2562
2563 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2564 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2565 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002566 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2567 {
2568 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302569 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002570 in_standby = FALSE;
2571 break;
2572 }
2573 else
2574 {
2575 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2576 pAdapterNode = pNext;
2577 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002578 }
2579
2580 if (TRUE == in_standby)
2581 {
2582 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2583 {
2584 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2585 "wlan out of power save", __func__);
2586 return -EINVAL;
2587 }
2588 }
2589
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002590 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002591 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2592 {
2593 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002594 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002595 /* Enable TX queues only when we are connected */
2596 netif_tx_start_all_queues(dev);
2597 }
2598
2599 return 0;
2600}
2601
2602int hdd_mon_open (struct net_device *dev)
2603{
2604 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2605
2606 if(pAdapter == NULL) {
2607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002608 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002609 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002610 }
2611
2612 netif_start_queue(dev);
2613
2614 return 0;
2615}
2616/**---------------------------------------------------------------------------
2617
2618 \brief hdd_stop() - HDD stop function
2619
2620 This is called in response to ifconfig down
2621
2622 \param - dev Pointer to net_device structure
2623
2624 \return - 0 for success non-zero for failure
2625
2626 --------------------------------------------------------------------------*/
2627
2628int hdd_stop (struct net_device *dev)
2629{
2630 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2631 hdd_context_t *pHddCtx;
2632 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2633 VOS_STATUS status;
2634 v_BOOL_t enter_standby = TRUE;
2635
2636 ENTER();
2637
2638 if (NULL == pAdapter)
2639 {
2640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002641 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002642 return -ENODEV;
2643 }
2644
2645 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2646 if (NULL == pHddCtx)
2647 {
2648 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002649 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002650 return -ENODEV;
2651 }
2652
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002653 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002654 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2655 netif_tx_disable(pAdapter->dev);
2656 netif_carrier_off(pAdapter->dev);
2657
2658
2659 /* SoftAP ifaces should never go in power save mode
2660 making sure same here. */
2661 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2662 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002663 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002664 )
2665 {
2666 /* SoftAP mode, so return from here */
2667 EXIT();
2668 return 0;
2669 }
2670
2671 /* Find if any iface is up then
2672 if any iface is up then can't put device to sleep/ power save mode. */
2673 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2674 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2675 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002676 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2677 {
2678 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302679 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002680 enter_standby = FALSE;
2681 break;
2682 }
2683 else
2684 {
2685 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2686 pAdapterNode = pNext;
2687 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002688 }
2689
2690 if (TRUE == enter_standby)
2691 {
2692 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2693 "entering standby", __func__);
2694 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2695 {
2696 /*log and return success*/
2697 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2698 "wlan in power save", __func__);
2699 }
2700 }
2701
2702 EXIT();
2703 return 0;
2704}
2705
2706/**---------------------------------------------------------------------------
2707
2708 \brief hdd_uninit() - HDD uninit function
2709
2710 This is called during the netdev unregister to uninitialize all data
2711associated with the device
2712
2713 \param - dev Pointer to net_device structure
2714
2715 \return - void
2716
2717 --------------------------------------------------------------------------*/
2718static void hdd_uninit (struct net_device *dev)
2719{
2720 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2721
2722 ENTER();
2723
2724 do
2725 {
2726 if (NULL == pAdapter)
2727 {
2728 hddLog(VOS_TRACE_LEVEL_FATAL,
2729 "%s: NULL pAdapter", __func__);
2730 break;
2731 }
2732
2733 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2734 {
2735 hddLog(VOS_TRACE_LEVEL_FATAL,
2736 "%s: Invalid magic", __func__);
2737 break;
2738 }
2739
2740 if (NULL == pAdapter->pHddCtx)
2741 {
2742 hddLog(VOS_TRACE_LEVEL_FATAL,
2743 "%s: NULL pHddCtx", __func__);
2744 break;
2745 }
2746
2747 if (dev != pAdapter->dev)
2748 {
2749 hddLog(VOS_TRACE_LEVEL_FATAL,
2750 "%s: Invalid device reference", __func__);
2751 /* we haven't validated all cases so let this go for now */
2752 }
2753
2754 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2755
2756 /* after uninit our adapter structure will no longer be valid */
2757 pAdapter->dev = NULL;
2758 pAdapter->magic = 0;
2759 } while (0);
2760
2761 EXIT();
2762}
2763
2764/**---------------------------------------------------------------------------
2765
2766 \brief hdd_release_firmware() -
2767
2768 This function calls the release firmware API to free the firmware buffer.
2769
2770 \param - pFileName Pointer to the File Name.
2771 pCtx - Pointer to the adapter .
2772
2773
2774 \return - 0 for success, non zero for failure
2775
2776 --------------------------------------------------------------------------*/
2777
2778VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2779{
2780 VOS_STATUS status = VOS_STATUS_SUCCESS;
2781 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2782 ENTER();
2783
2784
2785 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2786
2787 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2788
2789 if(pHddCtx->fw) {
2790 release_firmware(pHddCtx->fw);
2791 pHddCtx->fw = NULL;
2792 }
2793 else
2794 status = VOS_STATUS_E_FAILURE;
2795 }
2796 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2797 if(pHddCtx->nv) {
2798 release_firmware(pHddCtx->nv);
2799 pHddCtx->nv = NULL;
2800 }
2801 else
2802 status = VOS_STATUS_E_FAILURE;
2803
2804 }
2805
2806 EXIT();
2807 return status;
2808}
2809
2810/**---------------------------------------------------------------------------
2811
2812 \brief hdd_request_firmware() -
2813
2814 This function reads the firmware file using the request firmware
2815 API and returns the the firmware data and the firmware file size.
2816
2817 \param - pfileName - Pointer to the file name.
2818 - pCtx - Pointer to the adapter .
2819 - ppfw_data - Pointer to the pointer of the firmware data.
2820 - pSize - Pointer to the file size.
2821
2822 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2823
2824 --------------------------------------------------------------------------*/
2825
2826
2827VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2828{
2829 int status;
2830 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2831 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2832 ENTER();
2833
2834 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2835
2836 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2837
2838 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2839 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2840 __func__, pfileName);
2841 retval = VOS_STATUS_E_FAILURE;
2842 }
2843
2844 else {
2845 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2846 *pSize = pHddCtx->fw->size;
2847 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2848 __func__, *pSize);
2849 }
2850 }
2851 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2852
2853 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2854
2855 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2856 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2857 __func__, pfileName);
2858 retval = VOS_STATUS_E_FAILURE;
2859 }
2860
2861 else {
2862 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2863 *pSize = pHddCtx->nv->size;
2864 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2865 __func__, *pSize);
2866 }
2867 }
2868
2869 EXIT();
2870 return retval;
2871}
2872/**---------------------------------------------------------------------------
2873 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2874
2875 This is the function invoked by SME to inform the result of a full power
2876 request issued by HDD
2877
2878 \param - callbackcontext - Pointer to cookie
2879 status - result of request
2880
2881 \return - None
2882
2883--------------------------------------------------------------------------*/
2884void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2885{
2886 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2887
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002888 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002889 if(&pHddCtx->full_pwr_comp_var)
2890 {
2891 complete(&pHddCtx->full_pwr_comp_var);
2892 }
2893}
2894
2895/**---------------------------------------------------------------------------
2896
2897 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2898
2899 This is the function invoked by SME to inform the result of BMPS
2900 request issued by HDD
2901
2902 \param - callbackcontext - Pointer to cookie
2903 status - result of request
2904
2905 \return - None
2906
2907--------------------------------------------------------------------------*/
2908void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2909{
2910
2911 struct completion *completion_var = (struct completion*) callbackContext;
2912
2913 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2914 if(completion_var != NULL)
2915 {
2916 complete(completion_var);
2917 }
2918}
2919
2920/**---------------------------------------------------------------------------
2921
2922 \brief hdd_get_cfg_file_size() -
2923
2924 This function reads the configuration file using the request firmware
2925 API and returns the configuration file size.
2926
2927 \param - pCtx - Pointer to the adapter .
2928 - pFileName - Pointer to the file name.
2929 - pBufSize - Pointer to the buffer size.
2930
2931 \return - 0 for success, non zero for failure
2932
2933 --------------------------------------------------------------------------*/
2934
2935VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2936{
2937 int status;
2938 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2939
2940 ENTER();
2941
2942 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2943
2944 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2945 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2946 status = VOS_STATUS_E_FAILURE;
2947 }
2948 else {
2949 *pBufSize = pHddCtx->fw->size;
2950 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2951 release_firmware(pHddCtx->fw);
2952 pHddCtx->fw = NULL;
2953 }
2954
2955 EXIT();
2956 return VOS_STATUS_SUCCESS;
2957}
2958
2959/**---------------------------------------------------------------------------
2960
2961 \brief hdd_read_cfg_file() -
2962
2963 This function reads the configuration file using the request firmware
2964 API and returns the cfg data and the buffer size of the configuration file.
2965
2966 \param - pCtx - Pointer to the adapter .
2967 - pFileName - Pointer to the file name.
2968 - pBuffer - Pointer to the data buffer.
2969 - pBufSize - Pointer to the buffer size.
2970
2971 \return - 0 for success, non zero for failure
2972
2973 --------------------------------------------------------------------------*/
2974
2975VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2976 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2977{
2978 int status;
2979 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2980
2981 ENTER();
2982
2983 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2984
2985 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2986 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2987 return VOS_STATUS_E_FAILURE;
2988 }
2989 else {
2990 if(*pBufSize != pHddCtx->fw->size) {
2991 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2992 "file size", __func__);
2993 release_firmware(pHddCtx->fw);
2994 pHddCtx->fw = NULL;
2995 return VOS_STATUS_E_FAILURE;
2996 }
2997 else {
2998 if(pBuffer) {
2999 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
3000 }
3001 release_firmware(pHddCtx->fw);
3002 pHddCtx->fw = NULL;
3003 }
3004 }
3005
3006 EXIT();
3007
3008 return VOS_STATUS_SUCCESS;
3009}
3010
3011/**---------------------------------------------------------------------------
3012
Jeff Johnson295189b2012-06-20 16:38:30 -07003013 \brief hdd_set_mac_address() -
3014
3015 This function sets the user specified mac address using
3016 the command ifconfig wlanX hw ether <mac adress>.
3017
3018 \param - dev - Pointer to the net device.
3019 - addr - Pointer to the sockaddr.
3020 \return - 0 for success, non zero for failure
3021
3022 --------------------------------------------------------------------------*/
3023
3024static int hdd_set_mac_address(struct net_device *dev, void *addr)
3025{
3026 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3027 struct sockaddr *psta_mac_addr = addr;
3028 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3029
3030 ENTER();
3031
3032 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
3033
3034#ifdef HDD_SESSIONIZE
3035 // set the MAC address though the STA ID CFG.
3036 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
3037 (v_U8_t *)&pAdapter->macAddressCurrent,
3038 sizeof( pAdapter->macAddressCurrent ),
3039 hdd_set_mac_addr_cb, VOS_FALSE );
3040#endif
3041
3042 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
3043
3044 EXIT();
3045 return halStatus;
3046}
3047
3048tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
3049{
3050 int i;
3051 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3052 {
3053 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
3054 break;
3055 }
3056
3057 if( VOS_MAX_CONCURRENCY_PERSONA == i)
3058 return NULL;
3059
3060 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
3061 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
3062}
3063
3064void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
3065{
3066 int i;
3067 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3068 {
3069 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
3070 {
3071 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
3072 break;
3073 }
3074 }
3075 return;
3076}
3077
3078#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3079 static struct net_device_ops wlan_drv_ops = {
3080 .ndo_open = hdd_open,
3081 .ndo_stop = hdd_stop,
3082 .ndo_uninit = hdd_uninit,
3083 .ndo_start_xmit = hdd_hard_start_xmit,
3084 .ndo_tx_timeout = hdd_tx_timeout,
3085 .ndo_get_stats = hdd_stats,
3086 .ndo_do_ioctl = hdd_ioctl,
3087 .ndo_set_mac_address = hdd_set_mac_address,
3088 .ndo_select_queue = hdd_select_queue,
3089#ifdef WLAN_FEATURE_PACKET_FILTERING
3090#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3091 .ndo_set_rx_mode = hdd_set_multicast_list,
3092#else
3093 .ndo_set_multicast_list = hdd_set_multicast_list,
3094#endif //LINUX_VERSION_CODE
3095#endif
3096 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003097 static struct net_device_ops wlan_mon_drv_ops = {
3098 .ndo_open = hdd_mon_open,
3099 .ndo_stop = hdd_stop,
3100 .ndo_uninit = hdd_uninit,
3101 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3102 .ndo_tx_timeout = hdd_tx_timeout,
3103 .ndo_get_stats = hdd_stats,
3104 .ndo_do_ioctl = hdd_ioctl,
3105 .ndo_set_mac_address = hdd_set_mac_address,
3106 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003107
3108#endif
3109
3110void hdd_set_station_ops( struct net_device *pWlanDev )
3111{
3112#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3113 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3114 pWlanDev->netdev_ops = &wlan_drv_ops;
3115#else
3116 pWlanDev->open = hdd_open;
3117 pWlanDev->stop = hdd_stop;
3118 pWlanDev->uninit = hdd_uninit;
3119 pWlanDev->hard_start_xmit = NULL;
3120 pWlanDev->tx_timeout = hdd_tx_timeout;
3121 pWlanDev->get_stats = hdd_stats;
3122 pWlanDev->do_ioctl = hdd_ioctl;
3123 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3124 pWlanDev->set_mac_address = hdd_set_mac_address;
3125#endif
3126}
3127
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003128static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003129{
3130 struct net_device *pWlanDev = NULL;
3131 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003132 /*
3133 * cfg80211 initialization and registration....
3134 */
3135 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3136
Jeff Johnson295189b2012-06-20 16:38:30 -07003137 if(pWlanDev != NULL)
3138 {
3139
3140 //Save the pointer to the net_device in the HDD adapter
3141 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3142
Jeff Johnson295189b2012-06-20 16:38:30 -07003143 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3144
3145 pAdapter->dev = pWlanDev;
3146 pAdapter->pHddCtx = pHddCtx;
3147 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3148
3149 init_completion(&pAdapter->session_open_comp_var);
3150 init_completion(&pAdapter->session_close_comp_var);
3151 init_completion(&pAdapter->disconnect_comp_var);
3152 init_completion(&pAdapter->linkup_event_var);
3153 init_completion(&pAdapter->cancel_rem_on_chan_var);
3154 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003155#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3156 init_completion(&pAdapter->offchannel_tx_event);
3157#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003158 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003159#ifdef FEATURE_WLAN_TDLS
3160 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003161 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003162 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303163 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003164#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003165 init_completion(&pHddCtx->mc_sus_event_var);
3166 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303167 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003168 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003169
Jeff Johnson295189b2012-06-20 16:38:30 -07003170 pAdapter->isLinkUpSvcNeeded = FALSE;
3171 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3172 //Init the net_device structure
3173 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3174
3175 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3176 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3177 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3178 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3179
3180 hdd_set_station_ops( pAdapter->dev );
3181
3182 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003183 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3184 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3185 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003186 /* set pWlanDev's parent to underlying device */
3187 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3188 }
3189
3190 return pAdapter;
3191}
3192
3193VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3194{
3195 struct net_device *pWlanDev = pAdapter->dev;
3196 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3197 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3198 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3199
3200 if( rtnl_lock_held )
3201 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003202 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003203 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3204 {
3205 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3206 return VOS_STATUS_E_FAILURE;
3207 }
3208 }
3209 if (register_netdevice(pWlanDev))
3210 {
3211 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3212 return VOS_STATUS_E_FAILURE;
3213 }
3214 }
3215 else
3216 {
3217 if(register_netdev(pWlanDev))
3218 {
3219 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3220 return VOS_STATUS_E_FAILURE;
3221 }
3222 }
3223 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3224
3225 return VOS_STATUS_SUCCESS;
3226}
3227
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003228static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003229{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003230 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003231
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003232 if (NULL == pAdapter)
3233 {
3234 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3235 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003236 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003237
3238 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3239 {
3240 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3241 return eHAL_STATUS_NOT_INITIALIZED;
3242 }
3243
3244 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3245
3246 /* need to make sure all of our scheduled work has completed.
3247 * This callback is called from MC thread context, so it is safe to
3248 * to call below flush workqueue API from here.
3249 */
3250 flush_scheduled_work();
3251
3252 /* We can be blocked while waiting for scheduled work to be
3253 * flushed, and the adapter structure can potentially be freed, in
3254 * which case the magic will have been reset. So make sure the
3255 * magic is still good, and hence the adapter structure is still
3256 * valid, before signaling completion */
3257 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3258 {
3259 complete(&pAdapter->session_close_comp_var);
3260 }
3261
Jeff Johnson295189b2012-06-20 16:38:30 -07003262 return eHAL_STATUS_SUCCESS;
3263}
3264
3265VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3266{
3267 struct net_device *pWlanDev = pAdapter->dev;
3268 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3269 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3270 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3271 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3272 int rc = 0;
3273
3274 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003275 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003276 //Open a SME session for future operation
3277 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003278 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003279 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3280 {
3281 hddLog(VOS_TRACE_LEVEL_FATAL,
3282 "sme_OpenSession() failed with status code %08d [x%08lx]",
3283 halStatus, halStatus );
3284 status = VOS_STATUS_E_FAILURE;
3285 goto error_sme_open;
3286 }
3287
3288 //Block on a completion variable. Can't wait forever though.
3289 rc = wait_for_completion_interruptible_timeout(
3290 &pAdapter->session_open_comp_var,
3291 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3292 if (!rc)
3293 {
3294 hddLog(VOS_TRACE_LEVEL_FATAL,
3295 "Session is not opened within timeout period code %08d", rc );
3296 status = VOS_STATUS_E_FAILURE;
3297 goto error_sme_open;
3298 }
3299
3300 // Register wireless extensions
3301 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3302 {
3303 hddLog(VOS_TRACE_LEVEL_FATAL,
3304 "hdd_register_wext() failed with status code %08d [x%08lx]",
3305 halStatus, halStatus );
3306 status = VOS_STATUS_E_FAILURE;
3307 goto error_register_wext;
3308 }
3309 //Safe to register the hard_start_xmit function again
3310#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3311 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3312#else
3313 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3314#endif
3315
3316 //Set the Connection State to Not Connected
3317 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3318
3319 //Set the default operation channel
3320 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3321
3322 /* Make the default Auth Type as OPEN*/
3323 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3324
3325 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3326 {
3327 hddLog(VOS_TRACE_LEVEL_FATAL,
3328 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3329 status, status );
3330 goto error_init_txrx;
3331 }
3332
3333 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3334
3335 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3336 {
3337 hddLog(VOS_TRACE_LEVEL_FATAL,
3338 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3339 status, status );
3340 goto error_wmm_init;
3341 }
3342
3343 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3344
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003345#ifdef FEATURE_WLAN_TDLS
3346 if(0 != wlan_hdd_tdls_init(pAdapter))
3347 {
3348 status = VOS_STATUS_E_FAILURE;
3349 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3350 goto error_tdls_init;
3351 }
3352 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3353#endif
3354
Jeff Johnson295189b2012-06-20 16:38:30 -07003355 return VOS_STATUS_SUCCESS;
3356
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003357#ifdef FEATURE_WLAN_TDLS
3358error_tdls_init:
3359 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3360 hdd_wmm_adapter_close(pAdapter);
3361#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003362error_wmm_init:
3363 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3364 hdd_deinit_tx_rx(pAdapter);
3365error_init_txrx:
3366 hdd_UnregisterWext(pWlanDev);
3367error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003368 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003369 {
3370 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003371 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003372 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003373 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003374 {
3375 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003376 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003377 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003378 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003379 }
3380}
3381error_sme_open:
3382 return status;
3383}
3384
Jeff Johnson295189b2012-06-20 16:38:30 -07003385void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3386{
3387 hdd_cfg80211_state_t *cfgState;
3388
3389 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3390
3391 if( NULL != cfgState->buf )
3392 {
3393 int rc;
3394 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3395 rc = wait_for_completion_interruptible_timeout(
3396 &pAdapter->tx_action_cnf_event,
3397 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3398 if(!rc)
3399 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003400 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003401 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3402 }
3403 }
3404 return;
3405}
Jeff Johnson295189b2012-06-20 16:38:30 -07003406
3407void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3408{
3409 ENTER();
3410 switch ( pAdapter->device_mode )
3411 {
3412 case WLAN_HDD_INFRA_STATION:
3413 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003414 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003415 {
3416 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3417 {
3418 hdd_deinit_tx_rx( pAdapter );
3419 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3420 }
3421
3422 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3423 {
3424 hdd_wmm_adapter_close( pAdapter );
3425 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3426 }
3427
Jeff Johnson295189b2012-06-20 16:38:30 -07003428 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003429#ifdef FEATURE_WLAN_TDLS
3430 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3431 {
3432 wlan_hdd_tdls_exit(pAdapter);
3433 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3434 }
3435#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003436
3437 break;
3438 }
3439
3440 case WLAN_HDD_SOFTAP:
3441 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003442 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003443 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003444
3445 hdd_unregister_hostapd(pAdapter);
3446 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003447 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003448 break;
3449 }
3450
3451 case WLAN_HDD_MONITOR:
3452 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003453 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003454 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3455 {
3456 hdd_deinit_tx_rx( pAdapter );
3457 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3458 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003459 if(NULL != pAdapterforTx)
3460 {
3461 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3462 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003463 break;
3464 }
3465
3466
3467 default:
3468 break;
3469 }
3470
3471 EXIT();
3472}
3473
3474void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3475{
3476 struct net_device *pWlanDev = pAdapter->dev;
3477
3478 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3479 if( rtnl_held )
3480 {
3481 unregister_netdevice(pWlanDev);
3482 }
3483 else
3484 {
3485 unregister_netdev(pWlanDev);
3486 }
3487 // note that the pAdapter is no longer valid at this point
3488 // since the memory has been reclaimed
3489 }
3490
3491}
3492
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003493void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3494{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303495 VOS_STATUS status;
3496 hdd_adapter_t *pAdapter = NULL;
3497 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003498
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303499 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003500
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303501 /*loop through all adapters.*/
3502 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003503 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303504 pAdapter = pAdapterNode->pAdapter;
3505 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3506 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003507
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303508 { // we skip this registration for modes other than STA and P2P client modes.
3509 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3510 pAdapterNode = pNext;
3511 continue;
3512 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003513
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303514 //Apply Dynamic DTIM For P2P
3515 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3516 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3517 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3518 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3519 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3520 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3521 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3522 (eConnectionState_Associated ==
3523 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3524 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3525 {
3526 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003527
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303528 powerRequest.uIgnoreDTIM = 1;
3529 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3530
3531 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3532 {
3533 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3534 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3535 }
3536 else
3537 {
3538 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3539 }
3540
3541 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3542 * specified during Enter/Exit BMPS when LCD off*/
3543 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3544 NULL, eANI_BOOLEAN_FALSE);
3545 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3546 NULL, eANI_BOOLEAN_FALSE);
3547
3548 /* switch to the DTIM specified in cfg.ini */
3549 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3550 "Switch to DTIM %d", powerRequest.uListenInterval);
3551 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3552 break;
3553
3554 }
3555
3556 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3557 pAdapterNode = pNext;
3558 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003559}
3560
3561void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3562{
3563 /*Switch back to DTIM 1*/
3564 tSirSetPowerParamsReq powerRequest = { 0 };
3565
3566 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3567 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003568 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003569
3570 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3571 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3572 NULL, eANI_BOOLEAN_FALSE);
3573 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3574 NULL, eANI_BOOLEAN_FALSE);
3575
3576 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3577 "Switch to DTIM%d",powerRequest.uListenInterval);
3578 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3579
3580}
3581
Jeff Johnson295189b2012-06-20 16:38:30 -07003582VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3583{
3584 VOS_STATUS status = VOS_STATUS_SUCCESS;
3585
3586 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3587 {
3588 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3589 }
3590
3591 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3592 {
3593 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3594 }
3595
3596 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3597 {
3598 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3599 }
3600
3601 return status;
3602}
3603
3604VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3605{
3606 hdd_adapter_t *pAdapter = NULL;
3607 eHalStatus halStatus;
3608 VOS_STATUS status = VOS_STATUS_E_INVAL;
3609 v_BOOL_t disableBmps = FALSE;
3610 v_BOOL_t disableImps = FALSE;
3611
3612 switch(session_type)
3613 {
3614 case WLAN_HDD_INFRA_STATION:
3615 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003616 case WLAN_HDD_P2P_CLIENT:
3617 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003618 //Exit BMPS -> Is Sta/P2P Client is already connected
3619 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3620 if((NULL != pAdapter)&&
3621 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3622 {
3623 disableBmps = TRUE;
3624 }
3625
3626 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3627 if((NULL != pAdapter)&&
3628 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3629 {
3630 disableBmps = TRUE;
3631 }
3632
3633 //Exit both Bmps and Imps incase of Go/SAP Mode
3634 if((WLAN_HDD_SOFTAP == session_type) ||
3635 (WLAN_HDD_P2P_GO == session_type))
3636 {
3637 disableBmps = TRUE;
3638 disableImps = TRUE;
3639 }
3640
3641 if(TRUE == disableImps)
3642 {
3643 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3644 {
3645 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3646 }
3647 }
3648
3649 if(TRUE == disableBmps)
3650 {
3651 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3652 {
3653 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3654
3655 if(eHAL_STATUS_SUCCESS != halStatus)
3656 {
3657 status = VOS_STATUS_E_FAILURE;
3658 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3659 VOS_ASSERT(0);
3660 return status;
3661 }
3662 }
3663
3664 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3665 {
3666 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3667
3668 if(eHAL_STATUS_SUCCESS != halStatus)
3669 {
3670 status = VOS_STATUS_E_FAILURE;
3671 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3672 VOS_ASSERT(0);
3673 return status;
3674 }
3675 }
3676 }
3677
3678 if((TRUE == disableBmps) ||
3679 (TRUE == disableImps))
3680 {
3681 /* Now, get the chip into Full Power now */
3682 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3683 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3684 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3685
3686 if(halStatus != eHAL_STATUS_SUCCESS)
3687 {
3688 if(halStatus == eHAL_STATUS_PMC_PENDING)
3689 {
3690 //Block on a completion variable. Can't wait forever though
3691 wait_for_completion_interruptible_timeout(
3692 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3693 }
3694 else
3695 {
3696 status = VOS_STATUS_E_FAILURE;
3697 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3698 VOS_ASSERT(0);
3699 return status;
3700 }
3701 }
3702
3703 status = VOS_STATUS_SUCCESS;
3704 }
3705
3706 break;
3707 }
3708 return status;
3709}
3710
3711hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003712 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003713 tANI_U8 rtnl_held )
3714{
3715 hdd_adapter_t *pAdapter = NULL;
3716 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3717 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3718 VOS_STATUS exitbmpsStatus;
3719
3720 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3721
3722 //Disable BMPS incase of Concurrency
3723 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3724
3725 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3726 {
3727 //Fail to Exit BMPS
3728 VOS_ASSERT(0);
3729 return NULL;
3730 }
3731
3732 switch(session_type)
3733 {
3734 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003735 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003736 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003737 {
3738 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3739
3740 if( NULL == pAdapter )
3741 return NULL;
3742
Jeff Johnsone7245742012-09-05 17:12:55 -07003743 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3744 NL80211_IFTYPE_P2P_CLIENT:
3745 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003746
Jeff Johnson295189b2012-06-20 16:38:30 -07003747 pAdapter->device_mode = session_type;
3748
3749 status = hdd_init_station_mode( pAdapter );
3750 if( VOS_STATUS_SUCCESS != status )
3751 goto err_free_netdev;
3752
3753 status = hdd_register_interface( pAdapter, rtnl_held );
3754 if( VOS_STATUS_SUCCESS != status )
3755 {
3756 hdd_deinit_adapter(pHddCtx, pAdapter);
3757 goto err_free_netdev;
3758 }
3759 //Stop the Interface TX queue.
3760 netif_tx_disable(pAdapter->dev);
3761 //netif_tx_disable(pWlanDev);
3762 netif_carrier_off(pAdapter->dev);
3763
3764 break;
3765 }
3766
Jeff Johnson295189b2012-06-20 16:38:30 -07003767 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003768 case WLAN_HDD_SOFTAP:
3769 {
3770 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3771 if( NULL == pAdapter )
3772 return NULL;
3773
Jeff Johnson295189b2012-06-20 16:38:30 -07003774 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3775 NL80211_IFTYPE_AP:
3776 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003777 pAdapter->device_mode = session_type;
3778
3779 status = hdd_init_ap_mode(pAdapter);
3780 if( VOS_STATUS_SUCCESS != status )
3781 goto err_free_netdev;
3782
3783 status = hdd_register_hostapd( pAdapter, rtnl_held );
3784 if( VOS_STATUS_SUCCESS != status )
3785 {
3786 hdd_deinit_adapter(pHddCtx, pAdapter);
3787 goto err_free_netdev;
3788 }
3789
3790 netif_tx_disable(pAdapter->dev);
3791 netif_carrier_off(pAdapter->dev);
3792
3793 hdd_set_conparam( 1 );
3794 break;
3795 }
3796 case WLAN_HDD_MONITOR:
3797 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003798 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3799 if( NULL == pAdapter )
3800 return NULL;
3801
3802 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3803 pAdapter->device_mode = session_type;
3804 status = hdd_register_interface( pAdapter, rtnl_held );
3805#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3806 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3807#else
3808 pAdapter->dev->open = hdd_mon_open;
3809 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3810#endif
3811 hdd_init_tx_rx( pAdapter );
3812 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3813 //Set adapter to be used for data tx. It will use either GO or softap.
3814 pAdapter->sessionCtx.monitor.pAdapterForTx =
3815 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003816 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3817 {
3818 pAdapter->sessionCtx.monitor.pAdapterForTx =
3819 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3820 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003821 /* This workqueue will be used to transmit management packet over
3822 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003823 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3824 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3825 return NULL;
3826 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003827
Jeff Johnson295189b2012-06-20 16:38:30 -07003828 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3829 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003830 }
3831 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003832 case WLAN_HDD_FTM:
3833 {
3834 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3835
3836 if( NULL == pAdapter )
3837 return NULL;
3838 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3839 * message while loading driver in FTM mode. */
3840 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3841 pAdapter->device_mode = session_type;
3842 status = hdd_register_interface( pAdapter, rtnl_held );
3843 }
3844 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003845 default:
3846 {
3847 VOS_ASSERT(0);
3848 return NULL;
3849 }
3850 }
3851
3852
3853 if( VOS_STATUS_SUCCESS == status )
3854 {
3855 //Add it to the hdd's session list.
3856 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3857 if( NULL == pHddAdapterNode )
3858 {
3859 status = VOS_STATUS_E_NOMEM;
3860 }
3861 else
3862 {
3863 pHddAdapterNode->pAdapter = pAdapter;
3864 status = hdd_add_adapter_back ( pHddCtx,
3865 pHddAdapterNode );
3866 }
3867 }
3868
3869 if( VOS_STATUS_SUCCESS != status )
3870 {
3871 if( NULL != pAdapter )
3872 {
3873 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3874 pAdapter = NULL;
3875 }
3876 if( NULL != pHddAdapterNode )
3877 {
3878 vos_mem_free( pHddAdapterNode );
3879 }
3880
3881 goto resume_bmps;
3882 }
3883
3884 if(VOS_STATUS_SUCCESS == status)
3885 {
3886 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3887
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003888 //Initialize the WoWL service
3889 if(!hdd_init_wowl(pAdapter))
3890 {
3891 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3892 goto err_free_netdev;
3893 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003894 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003895 return pAdapter;
3896
3897err_free_netdev:
3898 free_netdev(pAdapter->dev);
3899 wlan_hdd_release_intf_addr( pHddCtx,
3900 pAdapter->macAddressCurrent.bytes );
3901
3902resume_bmps:
3903 //If bmps disabled enable it
3904 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3905 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303906 if (pHddCtx->hdd_wlan_suspended)
3907 {
3908 hdd_set_pwrparams(pHddCtx);
3909 }
3910 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003911 }
3912 return NULL;
3913}
3914
3915VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3916 tANI_U8 rtnl_held )
3917{
3918 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3919 VOS_STATUS status;
3920
3921 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3922 if( VOS_STATUS_SUCCESS != status )
3923 return status;
3924
3925 while ( pCurrent->pAdapter != pAdapter )
3926 {
3927 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3928 if( VOS_STATUS_SUCCESS != status )
3929 break;
3930
3931 pCurrent = pNext;
3932 }
3933 pAdapterNode = pCurrent;
3934 if( VOS_STATUS_SUCCESS == status )
3935 {
3936 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3937 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3938 hdd_remove_adapter( pHddCtx, pAdapterNode );
3939 vos_mem_free( pAdapterNode );
3940
Jeff Johnson295189b2012-06-20 16:38:30 -07003941
3942 /* If there is a single session of STA/P2P client, re-enable BMPS */
3943 if ((!vos_concurrent_sessions_running()) &&
3944 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3945 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3946 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303947 if (pHddCtx->hdd_wlan_suspended)
3948 {
3949 hdd_set_pwrparams(pHddCtx);
3950 }
3951 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003952 }
3953
3954 return VOS_STATUS_SUCCESS;
3955 }
3956
3957 return VOS_STATUS_E_FAILURE;
3958}
3959
3960VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3961{
3962 hdd_adapter_list_node_t *pHddAdapterNode;
3963 VOS_STATUS status;
3964
3965 ENTER();
3966
3967 do
3968 {
3969 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3970 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3971 {
3972 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3973 vos_mem_free( pHddAdapterNode );
3974 }
3975 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3976
3977 EXIT();
3978
3979 return VOS_STATUS_SUCCESS;
3980}
3981
3982void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3983{
3984 v_U8_t addIE[1] = {0};
3985
3986 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3987 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3988 eANI_BOOLEAN_FALSE) )
3989 {
3990 hddLog(LOGE,
3991 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3992 }
3993
3994 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3995 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3996 eANI_BOOLEAN_FALSE) )
3997 {
3998 hddLog(LOGE,
3999 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
4000 }
4001
4002 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4003 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
4004 eANI_BOOLEAN_FALSE) )
4005 {
4006 hddLog(LOGE,
4007 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
4008 }
4009}
4010
4011VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4012{
4013 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4014 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4015 union iwreq_data wrqu;
4016
4017 ENTER();
4018
4019 switch(pAdapter->device_mode)
4020 {
4021 case WLAN_HDD_INFRA_STATION:
4022 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004023 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004024 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4025 {
4026 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
4027 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4028 pAdapter->sessionId,
4029 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
4030 else
4031 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4032 pAdapter->sessionId,
4033 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4034 //success implies disconnect command got queued up successfully
4035 if(halStatus == eHAL_STATUS_SUCCESS)
4036 {
4037 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
4038 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4039 }
4040 memset(&wrqu, '\0', sizeof(wrqu));
4041 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4042 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4043 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
4044 }
4045 else
4046 {
4047 hdd_abort_mac_scan(pHddCtx);
4048 }
4049
4050 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
4051 {
4052 INIT_COMPLETION(pAdapter->session_close_comp_var);
4053 if (eHAL_STATUS_SUCCESS ==
4054 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
4055 hdd_smeCloseSessionCallback, pAdapter))
4056 {
4057 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004058 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004059 &pAdapter->session_close_comp_var,
4060 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4061 }
4062 }
4063
4064 break;
4065
4066 case WLAN_HDD_SOFTAP:
4067 case WLAN_HDD_P2P_GO:
4068 //Any softap specific cleanup here...
4069 mutex_lock(&pHddCtx->sap_lock);
4070 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4071 {
4072 VOS_STATUS status;
4073 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4074
4075 //Stop Bss.
4076 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4077 if (VOS_IS_STATUS_SUCCESS(status))
4078 {
4079 hdd_hostapd_state_t *pHostapdState =
4080 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4081
4082 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4083
4084 if (!VOS_IS_STATUS_SUCCESS(status))
4085 {
4086 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004087 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004088 }
4089 }
4090 else
4091 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004092 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004093 }
4094 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4095
4096 if (eHAL_STATUS_FAILURE ==
4097 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4098 0, NULL, eANI_BOOLEAN_FALSE))
4099 {
4100 hddLog(LOGE,
4101 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004102 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004103 }
4104
4105 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4106 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4107 eANI_BOOLEAN_FALSE) )
4108 {
4109 hddLog(LOGE,
4110 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4111 }
4112
4113 // Reset WNI_CFG_PROBE_RSP Flags
4114 wlan_hdd_reset_prob_rspies(pAdapter);
4115 kfree(pAdapter->sessionCtx.ap.beacon);
4116 pAdapter->sessionCtx.ap.beacon = NULL;
4117 }
4118 mutex_unlock(&pHddCtx->sap_lock);
4119 break;
4120 case WLAN_HDD_MONITOR:
4121 break;
4122 default:
4123 break;
4124 }
4125
4126 EXIT();
4127 return VOS_STATUS_SUCCESS;
4128}
4129
4130VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4131{
4132 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4133 VOS_STATUS status;
4134 hdd_adapter_t *pAdapter;
4135
4136 ENTER();
4137
4138 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4139
4140 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4141 {
4142 pAdapter = pAdapterNode->pAdapter;
4143 netif_tx_disable(pAdapter->dev);
4144 netif_carrier_off(pAdapter->dev);
4145
4146 hdd_stop_adapter( pHddCtx, pAdapter );
4147
4148 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4149 pAdapterNode = pNext;
4150 }
4151
4152 EXIT();
4153
4154 return VOS_STATUS_SUCCESS;
4155}
4156
4157VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4158{
4159 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4160 VOS_STATUS status;
4161 hdd_adapter_t *pAdapter;
4162
4163 ENTER();
4164
4165 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4166
4167 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4168 {
4169 pAdapter = pAdapterNode->pAdapter;
4170 netif_tx_disable(pAdapter->dev);
4171 netif_carrier_off(pAdapter->dev);
4172
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004173 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
4174
Jeff Johnson295189b2012-06-20 16:38:30 -07004175 hdd_deinit_tx_rx(pAdapter);
4176 hdd_wmm_adapter_close(pAdapter);
4177
4178 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4179 pAdapterNode = pNext;
4180 }
4181
4182 EXIT();
4183
4184 return VOS_STATUS_SUCCESS;
4185}
4186
4187VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4188{
4189 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4190 VOS_STATUS status;
4191 hdd_adapter_t *pAdapter;
4192 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304193 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004194
4195 ENTER();
4196
4197 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4198
4199 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4200 {
4201 pAdapter = pAdapterNode->pAdapter;
4202
4203 switch(pAdapter->device_mode)
4204 {
4205 case WLAN_HDD_INFRA_STATION:
4206 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004207 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304208
4209 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4210
Jeff Johnson295189b2012-06-20 16:38:30 -07004211 hdd_init_station_mode(pAdapter);
4212 /* Open the gates for HDD to receive Wext commands */
4213 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004214 pHddCtx->scan_info.mScanPending = FALSE;
4215 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004216
4217 //Trigger the initial scan
4218 hdd_wlan_initial_scan(pAdapter);
4219
4220 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304221 if (eConnectionState_Associated == connState ||
4222 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004223 {
4224 union iwreq_data wrqu;
4225 memset(&wrqu, '\0', sizeof(wrqu));
4226 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4227 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4228 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004229 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004230
Jeff Johnson295189b2012-06-20 16:38:30 -07004231 /* indicate disconnected event to nl80211 */
4232 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4233 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004234 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304235 else if (eConnectionState_Connecting == connState)
4236 {
4237 /*
4238 * Indicate connect failure to supplicant if we were in the
4239 * process of connecting
4240 */
4241 cfg80211_connect_result(pAdapter->dev, NULL,
4242 NULL, 0, NULL, 0,
4243 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4244 GFP_KERNEL);
4245 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004246 break;
4247
4248 case WLAN_HDD_SOFTAP:
4249 /* softAP can handle SSR */
4250 break;
4251
4252 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004253 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4254 __func__);
4255 /* event supplicant to restart */
4256 cfg80211_del_sta(pAdapter->dev,
4257 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004258 break;
4259
4260 case WLAN_HDD_MONITOR:
4261 /* monitor interface start */
4262 break;
4263 default:
4264 break;
4265 }
4266
4267 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4268 pAdapterNode = pNext;
4269 }
4270
4271 EXIT();
4272
4273 return VOS_STATUS_SUCCESS;
4274}
4275
4276VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4277{
4278 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4279 hdd_adapter_t *pAdapter;
4280 VOS_STATUS status;
4281 v_U32_t roamId;
4282
4283 ENTER();
4284
4285 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4286
4287 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4288 {
4289 pAdapter = pAdapterNode->pAdapter;
4290
4291 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4292 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4293 {
4294 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4295 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4296
4297 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4298 init_completion(&pAdapter->disconnect_comp_var);
4299 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4300 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4301
4302 wait_for_completion_interruptible_timeout(
4303 &pAdapter->disconnect_comp_var,
4304 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4305
4306 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4307 pHddCtx->isAmpAllowed = VOS_FALSE;
4308 sme_RoamConnect(pHddCtx->hHal,
4309 pAdapter->sessionId, &(pWextState->roamProfile),
4310 &roamId);
4311 }
4312
4313 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4314 pAdapterNode = pNext;
4315 }
4316
4317 EXIT();
4318
4319 return VOS_STATUS_SUCCESS;
4320}
4321
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004322void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4323{
4324 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4325 VOS_STATUS status;
4326 hdd_adapter_t *pAdapter;
4327 hdd_station_ctx_t *pHddStaCtx;
4328 hdd_ap_ctx_t *pHddApCtx;
4329 hdd_hostapd_state_t * pHostapdState;
4330 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4331 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4332 const char *p2pMode = "DEV";
4333 const char *ccMode = "Standalone";
4334 int n;
4335
4336 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4337 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4338 {
4339 pAdapter = pAdapterNode->pAdapter;
4340 switch (pAdapter->device_mode) {
4341 case WLAN_HDD_INFRA_STATION:
4342 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4343 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4344 staChannel = pHddStaCtx->conn_info.operationChannel;
4345 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4346 }
4347 break;
4348 case WLAN_HDD_P2P_CLIENT:
4349 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4350 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4351 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4352 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4353 p2pMode = "CLI";
4354 }
4355 break;
4356 case WLAN_HDD_P2P_GO:
4357 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4358 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4359 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4360 p2pChannel = pHddApCtx->operatingChannel;
4361 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4362 }
4363 p2pMode = "GO";
4364 break;
4365 case WLAN_HDD_SOFTAP:
4366 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4367 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4368 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4369 apChannel = pHddApCtx->operatingChannel;
4370 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4371 }
4372 break;
4373 default:
4374 break;
4375 }
4376 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4377 pAdapterNode = pNext;
4378 }
4379 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4380 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4381 }
4382 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4383 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4384 if (p2pChannel > 0) {
4385 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4386 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4387 }
4388 if (apChannel > 0) {
4389 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4390 apChannel, MAC_ADDR_ARRAY(apBssid));
4391 }
4392
4393 if (p2pChannel > 0 && apChannel > 0) {
4394 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4395 }
4396}
4397
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004398bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004399{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004400 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004401}
4402
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004403/* Once SSR is disabled then it cannot be set. */
4404void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004405{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004406 if (HDD_SSR_DISABLED == isSsrRequired)
4407 return;
4408
Jeff Johnson295189b2012-06-20 16:38:30 -07004409 isSsrRequired = value;
4410}
4411
4412VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4413 hdd_adapter_list_node_t** ppAdapterNode)
4414{
4415 VOS_STATUS status;
4416 spin_lock(&pHddCtx->hddAdapters.lock);
4417 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4418 (hdd_list_node_t**) ppAdapterNode );
4419 spin_unlock(&pHddCtx->hddAdapters.lock);
4420 return status;
4421}
4422
4423VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4424 hdd_adapter_list_node_t* pAdapterNode,
4425 hdd_adapter_list_node_t** pNextAdapterNode)
4426{
4427 VOS_STATUS status;
4428 spin_lock(&pHddCtx->hddAdapters.lock);
4429 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4430 (hdd_list_node_t*) pAdapterNode,
4431 (hdd_list_node_t**)pNextAdapterNode );
4432
4433 spin_unlock(&pHddCtx->hddAdapters.lock);
4434 return status;
4435}
4436
4437VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4438 hdd_adapter_list_node_t* pAdapterNode)
4439{
4440 VOS_STATUS status;
4441 spin_lock(&pHddCtx->hddAdapters.lock);
4442 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4443 &pAdapterNode->node );
4444 spin_unlock(&pHddCtx->hddAdapters.lock);
4445 return status;
4446}
4447
4448VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4449 hdd_adapter_list_node_t** ppAdapterNode)
4450{
4451 VOS_STATUS status;
4452 spin_lock(&pHddCtx->hddAdapters.lock);
4453 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4454 (hdd_list_node_t**) ppAdapterNode );
4455 spin_unlock(&pHddCtx->hddAdapters.lock);
4456 return status;
4457}
4458
4459VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4460 hdd_adapter_list_node_t* pAdapterNode)
4461{
4462 VOS_STATUS status;
4463 spin_lock(&pHddCtx->hddAdapters.lock);
4464 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4465 (hdd_list_node_t*) pAdapterNode );
4466 spin_unlock(&pHddCtx->hddAdapters.lock);
4467 return status;
4468}
4469
4470VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4471 hdd_adapter_list_node_t* pAdapterNode)
4472{
4473 VOS_STATUS status;
4474 spin_lock(&pHddCtx->hddAdapters.lock);
4475 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4476 (hdd_list_node_t*) pAdapterNode );
4477 spin_unlock(&pHddCtx->hddAdapters.lock);
4478 return status;
4479}
4480
4481hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4482 tSirMacAddr macAddr )
4483{
4484 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4485 hdd_adapter_t *pAdapter;
4486 VOS_STATUS status;
4487
4488 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4489
4490 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4491 {
4492 pAdapter = pAdapterNode->pAdapter;
4493
4494 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4495 macAddr, sizeof(tSirMacAddr) ) )
4496 {
4497 return pAdapter;
4498 }
4499 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4500 pAdapterNode = pNext;
4501 }
4502
4503 return NULL;
4504
4505}
4506
4507hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4508{
4509 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4510 hdd_adapter_t *pAdapter;
4511 VOS_STATUS status;
4512
4513 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4514
4515 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4516 {
4517 pAdapter = pAdapterNode->pAdapter;
4518
4519 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4520 IFNAMSIZ ) )
4521 {
4522 return pAdapter;
4523 }
4524 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4525 pAdapterNode = pNext;
4526 }
4527
4528 return NULL;
4529
4530}
4531
4532hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4533{
4534 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4535 hdd_adapter_t *pAdapter;
4536 VOS_STATUS status;
4537
4538 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4539
4540 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4541 {
4542 pAdapter = pAdapterNode->pAdapter;
4543
4544 if( pAdapter && (mode == pAdapter->device_mode) )
4545 {
4546 return pAdapter;
4547 }
4548 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4549 pAdapterNode = pNext;
4550 }
4551
4552 return NULL;
4553
4554}
4555
4556//Remove this function later
4557hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4558{
4559 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4560 hdd_adapter_t *pAdapter;
4561 VOS_STATUS status;
4562
4563 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4564
4565 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4566 {
4567 pAdapter = pAdapterNode->pAdapter;
4568
4569 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4570 {
4571 return pAdapter;
4572 }
4573
4574 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4575 pAdapterNode = pNext;
4576 }
4577
4578 return NULL;
4579
4580}
4581
Jeff Johnson295189b2012-06-20 16:38:30 -07004582/**---------------------------------------------------------------------------
4583
4584 \brief hdd_set_monitor_tx_adapter() -
4585
4586 This API initializes the adapter to be used while transmitting on monitor
4587 adapter.
4588
4589 \param - pHddCtx - Pointer to the HDD context.
4590 pAdapter - Adapter that will used for TX. This can be NULL.
4591 \return - None.
4592 --------------------------------------------------------------------------*/
4593void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4594{
4595 hdd_adapter_t *pMonAdapter;
4596
4597 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4598
4599 if( NULL != pMonAdapter )
4600 {
4601 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4602 }
4603}
Jeff Johnson295189b2012-06-20 16:38:30 -07004604/**---------------------------------------------------------------------------
4605
4606 \brief hdd_select_queue() -
4607
4608 This API returns the operating channel of the requested device mode
4609
4610 \param - pHddCtx - Pointer to the HDD context.
4611 - mode - Device mode for which operating channel is required
4612 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4613 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4614 \return - channel number. "0" id the requested device is not found OR it is not connected.
4615 --------------------------------------------------------------------------*/
4616v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4617{
4618 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4619 VOS_STATUS status;
4620 hdd_adapter_t *pAdapter;
4621 v_U8_t operatingChannel = 0;
4622
4623 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4624
4625 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4626 {
4627 pAdapter = pAdapterNode->pAdapter;
4628
4629 if( mode == pAdapter->device_mode )
4630 {
4631 switch(pAdapter->device_mode)
4632 {
4633 case WLAN_HDD_INFRA_STATION:
4634 case WLAN_HDD_P2P_CLIENT:
4635 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4636 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4637 break;
4638 case WLAN_HDD_SOFTAP:
4639 case WLAN_HDD_P2P_GO:
4640 /*softap connection info */
4641 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4642 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4643 break;
4644 default:
4645 break;
4646 }
4647
4648 break; //Found the device of interest. break the loop
4649 }
4650
4651 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4652 pAdapterNode = pNext;
4653 }
4654 return operatingChannel;
4655}
4656
4657#ifdef WLAN_FEATURE_PACKET_FILTERING
4658/**---------------------------------------------------------------------------
4659
4660 \brief hdd_set_multicast_list() -
4661
4662 This used to set the multicast address list.
4663
4664 \param - dev - Pointer to the WLAN device.
4665 - skb - Pointer to OS packet (sk_buff).
4666 \return - success/fail
4667
4668 --------------------------------------------------------------------------*/
4669static void hdd_set_multicast_list(struct net_device *dev)
4670{
4671 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004672 int mc_count;
4673 int i = 0;
4674 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304675
4676 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004677 {
4678 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304679 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004680 return;
4681 }
4682
4683 if (dev->flags & IFF_ALLMULTI)
4684 {
4685 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004686 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304687 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004688 }
4689 else
4690 {
4691 mc_count = netdev_mc_count(dev);
4692 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004693 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004694 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4695 {
4696 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004697 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304698 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004699 return;
4700 }
4701
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304702 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004703
4704 netdev_for_each_mc_addr(ha, dev) {
4705 if (i == mc_count)
4706 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304707 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4708 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4709 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004710 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304711 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004712 i++;
4713 }
4714 }
4715 return;
4716}
4717#endif
4718
4719/**---------------------------------------------------------------------------
4720
4721 \brief hdd_select_queue() -
4722
4723 This function is registered with the Linux OS for network
4724 core to decide which queue to use first.
4725
4726 \param - dev - Pointer to the WLAN device.
4727 - skb - Pointer to OS packet (sk_buff).
4728 \return - ac, Queue Index/access category corresponding to UP in IP header
4729
4730 --------------------------------------------------------------------------*/
4731v_U16_t hdd_select_queue(struct net_device *dev,
4732 struct sk_buff *skb)
4733{
4734 return hdd_wmm_select_queue(dev, skb);
4735}
4736
4737
4738/**---------------------------------------------------------------------------
4739
4740 \brief hdd_wlan_initial_scan() -
4741
4742 This function triggers the initial scan
4743
4744 \param - pAdapter - Pointer to the HDD adapter.
4745
4746 --------------------------------------------------------------------------*/
4747void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4748{
4749 tCsrScanRequest scanReq;
4750 tCsrChannelInfo channelInfo;
4751 eHalStatus halStatus;
4752 unsigned long scanId;
4753 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4754
4755 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4756 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4757 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4758
4759 if(sme_Is11dSupported(pHddCtx->hHal))
4760 {
4761 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4762 if ( HAL_STATUS_SUCCESS( halStatus ) )
4763 {
4764 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4765 if( !scanReq.ChannelInfo.ChannelList )
4766 {
4767 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4768 vos_mem_free(channelInfo.ChannelList);
4769 return;
4770 }
4771 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4772 channelInfo.numOfChannels);
4773 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4774 vos_mem_free(channelInfo.ChannelList);
4775 }
4776
4777 scanReq.scanType = eSIR_PASSIVE_SCAN;
4778 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4779 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4780 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4781 }
4782 else
4783 {
4784 scanReq.scanType = eSIR_ACTIVE_SCAN;
4785 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4786 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4787 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4788 }
4789
4790 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4791 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4792 {
4793 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4794 __func__, halStatus );
4795 }
4796
4797 if(sme_Is11dSupported(pHddCtx->hHal))
4798 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4799}
4800
4801struct fullPowerContext
4802{
4803 struct completion completion;
4804 unsigned int magic;
4805};
4806#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4807
4808/**---------------------------------------------------------------------------
4809
4810 \brief hdd_full_power_callback() - HDD full power callback function
4811
4812 This is the function invoked by SME to inform the result of a full power
4813 request issued by HDD
4814
4815 \param - callbackcontext - Pointer to cookie
4816 \param - status - result of request
4817
4818 \return - None
4819
4820 --------------------------------------------------------------------------*/
4821static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4822{
4823 struct fullPowerContext *pContext = callbackContext;
4824
4825 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304826 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004827
4828 if (NULL == callbackContext)
4829 {
4830 hddLog(VOS_TRACE_LEVEL_ERROR,
4831 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004832 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004833 return;
4834 }
4835
4836 /* there is a race condition that exists between this callback function
4837 and the caller since the caller could time out either before or
4838 while this code is executing. we'll assume the timeout hasn't
4839 occurred, but we'll verify that right before we save our work */
4840
4841 if (POWER_CONTEXT_MAGIC != pContext->magic)
4842 {
4843 /* the caller presumably timed out so there is nothing we can do */
4844 hddLog(VOS_TRACE_LEVEL_WARN,
4845 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004846 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004847 return;
4848 }
4849
4850 /* the race is on. caller could have timed out immediately after
4851 we verified the magic, but if so, caller will wait a short time
4852 for us to notify the caller, so the context will stay valid */
4853 complete(&pContext->completion);
4854}
4855
4856/**---------------------------------------------------------------------------
4857
4858 \brief hdd_wlan_exit() - HDD WLAN exit function
4859
4860 This is the driver exit point (invoked during rmmod)
4861
4862 \param - pHddCtx - Pointer to the HDD Context
4863
4864 \return - None
4865
4866 --------------------------------------------------------------------------*/
4867void hdd_wlan_exit(hdd_context_t *pHddCtx)
4868{
4869 eHalStatus halStatus;
4870 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4871 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304872 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004873 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004874 struct fullPowerContext powerContext;
4875 long lrc;
4876
4877 ENTER();
4878
Jeff Johnson88ba7742013-02-27 14:36:02 -08004879 if (VOS_FTM_MODE != hdd_get_conparam())
4880 {
4881 // Unloading, restart logic is no more required.
4882 wlan_hdd_restart_deinit(pHddCtx);
4883 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004884
Jeff Johnson295189b2012-06-20 16:38:30 -07004885 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004886 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004887 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004888 {
4889 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4890 WLAN_HDD_INFRA_STATION);
4891 if (pAdapter == NULL)
4892 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4893
4894 if (pAdapter != NULL)
4895 {
4896 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4897 hdd_UnregisterWext(pAdapter->dev);
4898 }
4899 }
4900 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004901
Jeff Johnson295189b2012-06-20 16:38:30 -07004902 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004903 {
4904 wlan_hdd_ftm_close(pHddCtx);
4905 goto free_hdd_ctx;
4906 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004907 //Stop the Interface TX queue.
4908 //netif_tx_disable(pWlanDev);
4909 //netif_carrier_off(pWlanDev);
4910
Jeff Johnson295189b2012-06-20 16:38:30 -07004911 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4912 {
4913 pAdapter = hdd_get_adapter(pHddCtx,
4914 WLAN_HDD_SOFTAP);
4915 }
4916 else
4917 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004918 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004919 {
4920 pAdapter = hdd_get_adapter(pHddCtx,
4921 WLAN_HDD_INFRA_STATION);
4922 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004923 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004924 /* DeRegister with platform driver as client for Suspend/Resume */
4925 vosStatus = hddDeregisterPmOps(pHddCtx);
4926 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4927 {
4928 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4929 VOS_ASSERT(0);
4930 }
4931
4932 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4933 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4934 {
4935 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4936 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004937
4938 // Cancel any outstanding scan requests. We are about to close all
4939 // of our adapters, but an adapter structure is what SME passes back
4940 // to our callback function. Hence if there are any outstanding scan
4941 // requests then there is a race condition between when the adapter
4942 // is closed and when the callback is invoked. We try to resolve that
4943 // race condition here by canceling any outstanding scans before we
4944 // close the adapters.
4945 // Note that the scans may be cancelled in an asynchronous manner, so
4946 // ideally there needs to be some kind of synchronization. Rather than
4947 // introduce a new synchronization here, we will utilize the fact that
4948 // we are about to Request Full Power, and since that is synchronized,
4949 // the expectation is that by the time Request Full Power has completed,
4950 // all scans will be cancelled.
4951 hdd_abort_mac_scan( pHddCtx );
4952
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05304953 //Stop the timer if already running
4954 if (VOS_TIMER_STATE_RUNNING ==
4955 vos_timer_getCurrentState(&pHddCtx->hdd_p2p_go_conn_is_in_progress))
4956 {
4957 vos_timer_stop(&pHddCtx->hdd_p2p_go_conn_is_in_progress);
4958 }
4959
4960 // Destroy hdd_p2p_go_conn_is_in_progress timer
4961 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
4962 &pHddCtx->hdd_p2p_go_conn_is_in_progress)))
4963 {
4964 hddLog(VOS_TRACE_LEVEL_ERROR,
4965 "%s: Cannot deallocate p2p connection timer", __func__);
4966 }
4967
Jeff Johnson295189b2012-06-20 16:38:30 -07004968 //Disable IMPS/BMPS as we do not want the device to enter any power
4969 //save mode during shutdown
4970 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4971 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4972 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4973
4974 //Ensure that device is in full power as we will touch H/W during vos_Stop
4975 init_completion(&powerContext.completion);
4976 powerContext.magic = POWER_CONTEXT_MAGIC;
4977
4978 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4979 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4980
4981 if (eHAL_STATUS_SUCCESS != halStatus)
4982 {
4983 if (eHAL_STATUS_PMC_PENDING == halStatus)
4984 {
4985 /* request was sent -- wait for the response */
4986 lrc = wait_for_completion_interruptible_timeout(
4987 &powerContext.completion,
4988 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4989 /* either we have a response or we timed out
4990 either way, first invalidate our magic */
4991 powerContext.magic = 0;
4992 if (lrc <= 0)
4993 {
4994 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004995 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004996 /* there is a race condition such that the callback
4997 function could be executing at the same time we are. of
4998 primary concern is if the callback function had already
4999 verified the "magic" but hasn't yet set the completion
5000 variable. Since the completion variable is on our
5001 stack, we'll delay just a bit to make sure the data is
5002 still valid if that is the case */
5003 msleep(50);
5004 }
5005 }
5006 else
5007 {
5008 hddLog(VOS_TRACE_LEVEL_ERROR,
5009 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005010 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07005011 VOS_ASSERT(0);
5012 /* continue -- need to clean up as much as possible */
5013 }
5014 }
5015
5016 // Unregister the Net Device Notifier
5017 unregister_netdevice_notifier(&hdd_netdev_notifier);
5018
Jeff Johnson295189b2012-06-20 16:38:30 -07005019 hdd_stop_all_adapters( pHddCtx );
5020
Jeff Johnson295189b2012-06-20 16:38:30 -07005021#ifdef WLAN_BTAMP_FEATURE
5022 vosStatus = WLANBAP_Stop(pVosContext);
5023 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5024 {
5025 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5026 "%s: Failed to stop BAP",__func__);
5027 }
5028#endif //WLAN_BTAMP_FEATURE
5029
5030 //Stop all the modules
5031 vosStatus = vos_stop( pVosContext );
5032 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5033 {
5034 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5035 "%s: Failed to stop VOSS",__func__);
5036 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5037 }
5038
Jeff Johnson295189b2012-06-20 16:38:30 -07005039 //Assert Deep sleep signal now to put Libra HW in lowest power state
5040 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5041 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5042
5043 //Vote off any PMIC voltage supplies
5044 vos_chipPowerDown(NULL, NULL, NULL);
5045
5046 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
5047
Leo Chang59cdc7e2013-07-10 10:08:21 -07005048
Jeff Johnson295189b2012-06-20 16:38:30 -07005049 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07005050 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005051
5052 //Close the scheduler before calling vos_close to make sure no thread is
5053 // scheduled after the each module close is called i.e after all the data
5054 // structures are freed.
5055 vosStatus = vos_sched_close( pVosContext );
5056 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
5057 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5058 "%s: Failed to close VOSS Scheduler",__func__);
5059 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5060 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005061#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005062#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5063 /* Destroy the wake lock */
5064 wake_lock_destroy(&pHddCtx->rx_wake_lock);
5065#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005066 /* Destroy the wake lock */
5067 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005068#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005069
5070 //Close VOSS
5071 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
5072 vos_close(pVosContext);
5073
Jeff Johnson295189b2012-06-20 16:38:30 -07005074 //Close Watchdog
5075 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5076 vos_watchdog_close(pVosContext);
5077
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305078 //Clean up HDD Nlink Service
5079 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07005080#ifdef WLAN_KD_READY_NOTIFIER
5081 nl_srv_exit(pHddCtx->ptt_pid);
5082#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305083 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005084#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305085
Jeff Johnson295189b2012-06-20 16:38:30 -07005086 /* Cancel the vote for XO Core ON.
5087 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5088 * exited at this point
5089 */
5090 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5091 " when WLAN is turned OFF\n");
5092 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5093 {
5094 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5095 " Not returning failure."
5096 " Power consumed will be high\n");
5097 }
5098
5099 hdd_close_all_adapters( pHddCtx );
5100
5101
5102 //Free up dynamically allocated members inside HDD Adapter
5103 kfree(pHddCtx->cfg_ini);
5104 pHddCtx->cfg_ini= NULL;
5105
5106 /* free the power on lock from platform driver */
5107 if (free_riva_power_on_lock("wlan"))
5108 {
5109 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5110 __func__);
5111 }
5112
Jeff Johnson88ba7742013-02-27 14:36:02 -08005113free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08005114 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005115 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005116 if (hdd_is_ssr_required())
5117 {
5118 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005119 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005120 msleep(5000);
5121 }
5122 hdd_set_ssr_required (VOS_FALSE);
5123}
5124
5125
5126/**---------------------------------------------------------------------------
5127
5128 \brief hdd_update_config_from_nv() - Function to update the contents of
5129 the running configuration with parameters taken from NV storage
5130
5131 \param - pHddCtx - Pointer to the HDD global context
5132
5133 \return - VOS_STATUS_SUCCESS if successful
5134
5135 --------------------------------------------------------------------------*/
5136static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5137{
Jeff Johnson295189b2012-06-20 16:38:30 -07005138 v_BOOL_t itemIsValid = VOS_FALSE;
5139 VOS_STATUS status;
5140 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5141 v_U8_t macLoop;
5142
5143 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5144 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5145 if(status != VOS_STATUS_SUCCESS)
5146 {
5147 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5148 return VOS_STATUS_E_FAILURE;
5149 }
5150
5151 if (itemIsValid == VOS_TRUE)
5152 {
5153 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5154 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5155 VOS_MAX_CONCURRENCY_PERSONA);
5156 if(status != VOS_STATUS_SUCCESS)
5157 {
5158 /* Get MAC from NV fail, not update CFG info
5159 * INI MAC value will be used for MAC setting */
5160 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5161 return VOS_STATUS_E_FAILURE;
5162 }
5163
5164 /* If first MAC is not valid, treat all others are not valid
5165 * Then all MACs will be got from ini file */
5166 if(vos_is_macaddr_zero(&macFromNV[0]))
5167 {
5168 /* MAC address in NV file is not configured yet */
5169 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5170 return VOS_STATUS_E_INVAL;
5171 }
5172
5173 /* Get MAC address from NV, update CFG info */
5174 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5175 {
5176 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5177 {
5178 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5179 /* This MAC is not valid, skip it
5180 * This MAC will be got from ini file */
5181 }
5182 else
5183 {
5184 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5185 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5186 VOS_MAC_ADDR_SIZE);
5187 }
5188 }
5189 }
5190 else
5191 {
5192 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5193 return VOS_STATUS_E_FAILURE;
5194 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005195
Jeff Johnson295189b2012-06-20 16:38:30 -07005196
5197 return VOS_STATUS_SUCCESS;
5198}
5199
5200/**---------------------------------------------------------------------------
5201
5202 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5203
5204 \param - pAdapter - Pointer to the HDD
5205
5206 \return - None
5207
5208 --------------------------------------------------------------------------*/
5209VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5210{
5211 eHalStatus halStatus;
5212 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305213 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005214
Jeff Johnson295189b2012-06-20 16:38:30 -07005215
5216 // Send ready indication to the HDD. This will kick off the MAC
5217 // into a 'running' state and should kick off an initial scan.
5218 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5219 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5220 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305221 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005222 "code %08d [x%08x]",__func__, halStatus, halStatus );
5223 return VOS_STATUS_E_FAILURE;
5224 }
5225
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305226 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005227 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5228 // And RIVA will crash
5229 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5230 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305231 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5232 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5233
5234
Jeff Johnson295189b2012-06-20 16:38:30 -07005235 return VOS_STATUS_SUCCESS;
5236}
5237
Jeff Johnson295189b2012-06-20 16:38:30 -07005238/* wake lock APIs for HDD */
5239void hdd_prevent_suspend(void)
5240{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005241#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005242 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005243#else
5244 wcnss_prevent_suspend();
5245#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005246}
5247
5248void hdd_allow_suspend(void)
5249{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005250#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005251 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005252#else
5253 wcnss_allow_suspend();
5254#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005255}
5256
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005257void hdd_allow_suspend_timeout(v_U32_t timeout)
5258{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005259#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005260 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005261#else
5262 /* Do nothing as there is no API in wcnss for timeout*/
5263#endif
5264}
5265
Jeff Johnson295189b2012-06-20 16:38:30 -07005266/**---------------------------------------------------------------------------
5267
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005268 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5269 information between Host and Riva
5270
5271 This function gets reported version of FW
5272 It also finds the version of Riva headers used to compile the host
5273 It compares the above two and prints a warning if they are different
5274 It gets the SW and HW version string
5275 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5276 indicating the features they support through a bitmap
5277
5278 \param - pHddCtx - Pointer to HDD context
5279
5280 \return - void
5281
5282 --------------------------------------------------------------------------*/
5283
5284void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5285{
5286
5287 tSirVersionType versionCompiled;
5288 tSirVersionType versionReported;
5289 tSirVersionString versionString;
5290 tANI_U8 fwFeatCapsMsgSupported = 0;
5291 VOS_STATUS vstatus;
5292
5293 /* retrieve and display WCNSS version information */
5294 do {
5295
5296 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5297 &versionCompiled);
5298 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5299 {
5300 hddLog(VOS_TRACE_LEVEL_FATAL,
5301 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005302 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005303 break;
5304 }
5305
5306 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5307 &versionReported);
5308 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5309 {
5310 hddLog(VOS_TRACE_LEVEL_FATAL,
5311 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005312 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005313 break;
5314 }
5315
5316 if ((versionCompiled.major != versionReported.major) ||
5317 (versionCompiled.minor != versionReported.minor) ||
5318 (versionCompiled.version != versionReported.version) ||
5319 (versionCompiled.revision != versionReported.revision))
5320 {
5321 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5322 "Host expected %u.%u.%u.%u\n",
5323 WLAN_MODULE_NAME,
5324 (int)versionReported.major,
5325 (int)versionReported.minor,
5326 (int)versionReported.version,
5327 (int)versionReported.revision,
5328 (int)versionCompiled.major,
5329 (int)versionCompiled.minor,
5330 (int)versionCompiled.version,
5331 (int)versionCompiled.revision);
5332 }
5333 else
5334 {
5335 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5336 WLAN_MODULE_NAME,
5337 (int)versionReported.major,
5338 (int)versionReported.minor,
5339 (int)versionReported.version,
5340 (int)versionReported.revision);
5341 }
5342
5343 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5344 versionString,
5345 sizeof(versionString));
5346 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5347 {
5348 hddLog(VOS_TRACE_LEVEL_FATAL,
5349 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005350 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005351 break;
5352 }
5353
5354 pr_info("%s: WCNSS software version %s\n",
5355 WLAN_MODULE_NAME, versionString);
5356
5357 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5358 versionString,
5359 sizeof(versionString));
5360 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5361 {
5362 hddLog(VOS_TRACE_LEVEL_FATAL,
5363 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005364 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005365 break;
5366 }
5367
5368 pr_info("%s: WCNSS hardware version %s\n",
5369 WLAN_MODULE_NAME, versionString);
5370
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005371 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5372 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005373 send the message only if it the riva is 1.1
5374 minor numbers for different riva branches:
5375 0 -> (1.0)Mainline Build
5376 1 -> (1.1)Mainline Build
5377 2->(1.04) Stability Build
5378 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005379 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005380 ((versionReported.minor>=1) && (versionReported.version>=1)))
5381 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5382 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005383
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005384 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005385 {
5386#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5387 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5388 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5389#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07005390 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
5391 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
5392 {
5393 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
5394 }
5395
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005396 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005397 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005398
5399 } while (0);
5400
5401}
5402
5403/**---------------------------------------------------------------------------
5404
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305405 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5406
5407 \param - pHddCtx - Pointer to the hdd context
5408
5409 \return - true if hardware supports 5GHz
5410
5411 --------------------------------------------------------------------------*/
5412static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5413{
5414 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5415 * then hardware support 5Ghz.
5416 */
5417 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5418 {
5419 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5420 return true;
5421 }
5422 else
5423 {
5424 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5425 __func__);
5426 return false;
5427 }
5428}
5429
5430
5431/**---------------------------------------------------------------------------
5432
Jeff Johnson295189b2012-06-20 16:38:30 -07005433 \brief hdd_wlan_startup() - HDD init function
5434
5435 This is the driver startup code executed once a WLAN device has been detected
5436
5437 \param - dev - Pointer to the underlying device
5438
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005439 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005440
5441 --------------------------------------------------------------------------*/
5442
5443int hdd_wlan_startup(struct device *dev )
5444{
5445 VOS_STATUS status;
5446 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005447 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005448 hdd_context_t *pHddCtx = NULL;
5449 v_CONTEXT_t pVosContext= NULL;
5450#ifdef WLAN_BTAMP_FEATURE
5451 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5452 WLANBAP_ConfigType btAmpConfig;
5453 hdd_config_t *pConfig;
5454#endif
5455 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005456 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005457
5458 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005459 /*
5460 * cfg80211: wiphy allocation
5461 */
5462 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5463
5464 if(wiphy == NULL)
5465 {
5466 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005467 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005468 }
5469
5470 pHddCtx = wiphy_priv(wiphy);
5471
Jeff Johnson295189b2012-06-20 16:38:30 -07005472 //Initialize the adapter context to zeros.
5473 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5474
Jeff Johnson295189b2012-06-20 16:38:30 -07005475 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005476 hdd_prevent_suspend();
5477 pHddCtx->isLoadUnloadInProgress = TRUE;
5478
5479 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5480
5481 /*Get vos context here bcoz vos_open requires it*/
5482 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5483
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005484 if(pVosContext == NULL)
5485 {
5486 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5487 goto err_free_hdd_context;
5488 }
5489
Jeff Johnson295189b2012-06-20 16:38:30 -07005490 //Save the Global VOSS context in adapter context for future.
5491 pHddCtx->pvosContext = pVosContext;
5492
5493 //Save the adapter context in global context for future.
5494 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5495
Jeff Johnson295189b2012-06-20 16:38:30 -07005496 pHddCtx->parent_dev = dev;
5497
5498 init_completion(&pHddCtx->full_pwr_comp_var);
5499 init_completion(&pHddCtx->standby_comp_var);
5500 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005501 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005502 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005503
5504 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5505
5506 // Load all config first as TL config is needed during vos_open
5507 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5508 if(pHddCtx->cfg_ini == NULL)
5509 {
5510 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5511 goto err_free_hdd_context;
5512 }
5513
5514 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5515
5516 // Read and parse the qcom_cfg.ini file
5517 status = hdd_parse_config_ini( pHddCtx );
5518 if ( VOS_STATUS_SUCCESS != status )
5519 {
5520 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5521 __func__, WLAN_INI_FILE);
5522 goto err_config;
5523 }
5524
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305525 /* INI has been read, initialise the configuredMcastBcastFilter with
5526 * INI value as this will serve as the default value
5527 */
5528 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5529 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5530 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305531
5532 if (false == hdd_is_5g_supported(pHddCtx))
5533 {
5534 //5Ghz is not supported.
5535 if (1 != pHddCtx->cfg_ini->nBandCapability)
5536 {
5537 hddLog(VOS_TRACE_LEVEL_INFO,
5538 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5539 pHddCtx->cfg_ini->nBandCapability = 1;
5540 }
5541 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005542 /*
5543 * cfg80211: Initialization and registration ...
5544 */
5545 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5546 {
5547 hddLog(VOS_TRACE_LEVEL_FATAL,
5548 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5549 goto err_wiphy_reg;
5550 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005551
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005552 // Update VOS trace levels based upon the cfg.ini
5553 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5554 pHddCtx->cfg_ini->vosTraceEnableBAP);
5555 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5556 pHddCtx->cfg_ini->vosTraceEnableTL);
5557 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5558 pHddCtx->cfg_ini->vosTraceEnableWDI);
5559 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5560 pHddCtx->cfg_ini->vosTraceEnableHDD);
5561 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5562 pHddCtx->cfg_ini->vosTraceEnableSME);
5563 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5564 pHddCtx->cfg_ini->vosTraceEnablePE);
5565 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5566 pHddCtx->cfg_ini->vosTraceEnableWDA);
5567 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5568 pHddCtx->cfg_ini->vosTraceEnableSYS);
5569 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5570 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005571 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5572 pHddCtx->cfg_ini->vosTraceEnableSAP);
5573 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5574 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005575
Jeff Johnson295189b2012-06-20 16:38:30 -07005576 // Update WDI trace levels based upon the cfg.ini
5577 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5578 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5579 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5580 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5581 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5582 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5583 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5584 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005585
Jeff Johnson88ba7742013-02-27 14:36:02 -08005586 if (VOS_FTM_MODE == hdd_get_conparam())
5587 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005588 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5589 {
5590 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5591 goto err_free_hdd_context;
5592 }
5593 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5594 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005595 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005596
Jeff Johnson88ba7742013-02-27 14:36:02 -08005597 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005598 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5599 {
5600 status = vos_watchdog_open(pVosContext,
5601 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5602
5603 if(!VOS_IS_STATUS_SUCCESS( status ))
5604 {
5605 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005606 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005607 }
5608 }
5609
5610 pHddCtx->isLogpInProgress = FALSE;
5611 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5612
Jeff Johnson295189b2012-06-20 16:38:30 -07005613 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5614 if(!VOS_IS_STATUS_SUCCESS(status))
5615 {
5616 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005617 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005618 }
5619
Jeff Johnson295189b2012-06-20 16:38:30 -07005620 status = vos_open( &pVosContext, 0);
5621 if ( !VOS_IS_STATUS_SUCCESS( status ))
5622 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005623 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5624 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005625 }
5626
Jeff Johnson295189b2012-06-20 16:38:30 -07005627 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5628
5629 if ( NULL == pHddCtx->hHal )
5630 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005631 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005632 goto err_vosclose;
5633 }
5634
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005635 status = vos_preStart( pHddCtx->pvosContext );
5636 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5637 {
5638 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5639 goto err_vosclose;
5640 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005641
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005642 /* Note that the vos_preStart() sequence triggers the cfg download.
5643 The cfg download must occur before we update the SME config
5644 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005645 status = hdd_set_sme_config( pHddCtx );
5646
5647 if ( VOS_STATUS_SUCCESS != status )
5648 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005649 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5650 goto err_vosclose;
5651 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005652
5653 //Initialize the WMM module
5654 status = hdd_wmm_init(pHddCtx);
5655 if (!VOS_IS_STATUS_SUCCESS(status))
5656 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005657 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005658 goto err_vosclose;
5659 }
5660
Jeff Johnson295189b2012-06-20 16:38:30 -07005661 /* In the integrated architecture we update the configuration from
5662 the INI file and from NV before vOSS has been started so that
5663 the final contents are available to send down to the cCPU */
5664
5665 // Apply the cfg.ini to cfg.dat
5666 if (FALSE == hdd_update_config_dat(pHddCtx))
5667 {
5668 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5669 goto err_vosclose;
5670 }
5671
5672 // Apply the NV to cfg.dat
5673 /* Prima Update MAC address only at here */
5674 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5675 {
5676#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5677 /* There was not a valid set of MAC Addresses in NV. See if the
5678 default addresses were modified by the cfg.ini settings. If so,
5679 we'll use them, but if not, we'll autogenerate a set of MAC
5680 addresses based upon the device serial number */
5681
5682 static const v_MACADDR_t default_address =
5683 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5684 unsigned int serialno;
5685 int i;
5686
5687 serialno = wcnss_get_serial_number();
5688 if ((0 != serialno) &&
5689 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5690 sizeof(default_address))))
5691 {
5692 /* cfg.ini has the default address, invoke autogen logic */
5693
5694 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5695 bytes of the serial number that can be used to generate
5696 the other 3 bytes of the MAC address. Mask off all but
5697 the lower 3 bytes (this will also make sure we don't
5698 overflow in the next step) */
5699 serialno &= 0x00FFFFFF;
5700
5701 /* we need a unique address for each session */
5702 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5703
5704 /* autogen all addresses */
5705 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5706 {
5707 /* start with the entire default address */
5708 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5709 /* then replace the lower 3 bytes */
5710 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5711 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5712 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5713
5714 serialno++;
5715 }
5716
5717 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5718 MAC_ADDRESS_STR,
5719 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5720 }
5721 else
5722#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5723 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005724 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005725 "%s: Invalid MAC address in NV, using MAC from ini file "
5726 MAC_ADDRESS_STR, __func__,
5727 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5728 }
5729 }
5730 {
5731 eHalStatus halStatus;
5732 // Set the MAC Address
5733 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5734 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5735 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5736 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5737
5738 if (!HAL_STATUS_SUCCESS( halStatus ))
5739 {
5740 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5741 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005742 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005743 }
5744 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005745
5746 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5747 Note: Firmware image will be read and downloaded inside vos_start API */
5748 status = vos_start( pHddCtx->pvosContext );
5749 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5750 {
5751 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5752 goto err_vosclose;
5753 }
5754
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005755 /* Exchange capability info between Host and FW and also get versioning info from FW */
5756 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005757
5758 status = hdd_post_voss_start_config( pHddCtx );
5759 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5760 {
5761 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5762 __func__);
5763 goto err_vosstop;
5764 }
5765
Jeff Johnson295189b2012-06-20 16:38:30 -07005766 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5767 {
5768 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5769 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5770 }
5771 else
5772 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005773 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5774 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5775 if (pAdapter != NULL)
5776 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305777 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005778 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305779 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5780 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5781 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005782
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305783 /* Generate the P2P Device Address. This consists of the device's
5784 * primary MAC address with the locally administered bit set.
5785 */
5786 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005787 }
5788 else
5789 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305790 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5791 if (p2p_dev_addr != NULL)
5792 {
5793 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5794 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5795 }
5796 else
5797 {
5798 hddLog(VOS_TRACE_LEVEL_FATAL,
5799 "%s: Failed to allocate mac_address for p2p_device",
5800 __func__);
5801 goto err_close_adapter;
5802 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005803 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005804
5805 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5806 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5807 if ( NULL == pP2pAdapter )
5808 {
5809 hddLog(VOS_TRACE_LEVEL_FATAL,
5810 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005811 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005812 goto err_close_adapter;
5813 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005814 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005815 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005816
5817 if( pAdapter == NULL )
5818 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005819 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5820 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005821 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005822
Jeff Johnson295189b2012-06-20 16:38:30 -07005823#ifdef WLAN_BTAMP_FEATURE
5824 vStatus = WLANBAP_Open(pVosContext);
5825 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5826 {
5827 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5828 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005829 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005830 }
5831
5832 vStatus = BSL_Init(pVosContext);
5833 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5834 {
5835 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5836 "%s: Failed to Init BSL",__func__);
5837 goto err_bap_close;
5838 }
5839 vStatus = WLANBAP_Start(pVosContext);
5840 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5841 {
5842 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5843 "%s: Failed to start TL",__func__);
5844 goto err_bap_close;
5845 }
5846
5847 pConfig = pHddCtx->cfg_ini;
5848 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5849 status = WLANBAP_SetConfig(&btAmpConfig);
5850
5851#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005852
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005853#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5854 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5855 {
5856 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5857 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5858 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5859 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5860 }
5861#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005862#ifdef FEATURE_WLAN_SCAN_PNO
5863 /*SME must send channel update configuration to RIVA*/
5864 sme_UpdateChannelConfig(pHddCtx->hHal);
5865#endif
5866
Jeff Johnson295189b2012-06-20 16:38:30 -07005867 /* Register with platform driver as client for Suspend/Resume */
5868 status = hddRegisterPmOps(pHddCtx);
5869 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5870 {
5871 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5872#ifdef WLAN_BTAMP_FEATURE
5873 goto err_bap_stop;
5874#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005875 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005876#endif //WLAN_BTAMP_FEATURE
5877 }
5878
5879 /* Register TM level change handler function to the platform */
5880 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5881 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5882 {
5883 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5884 goto err_unregister_pmops;
5885 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005886
5887 /* register for riva power on lock to platform driver */
5888 if (req_riva_power_on_lock("wlan"))
5889 {
5890 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5891 __func__);
5892 goto err_unregister_pmops;
5893 }
5894
Jeff Johnson295189b2012-06-20 16:38:30 -07005895 // register net device notifier for device change notification
5896 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5897
5898 if(ret < 0)
5899 {
5900 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5901 goto err_free_power_on_lock;
5902 }
5903
5904 //Initialize the nlink service
5905 if(nl_srv_init() != 0)
5906 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305907 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005908 goto err_reg_netdev;
5909 }
5910
5911 //Initialize the BTC service
5912 if(btc_activate_service(pHddCtx) != 0)
5913 {
5914 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5915 goto err_nl_srv;
5916 }
5917
5918#ifdef PTT_SOCK_SVC_ENABLE
5919 //Initialize the PTT service
5920 if(ptt_sock_activate_svc(pHddCtx) != 0)
5921 {
5922 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5923 goto err_nl_srv;
5924 }
5925#endif
5926
Jeff Johnson295189b2012-06-20 16:38:30 -07005927 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005928 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005929 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005930 /* Action frame registered in one adapter which will
5931 * applicable to all interfaces
5932 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005933 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005934 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005935
5936 mutex_init(&pHddCtx->sap_lock);
5937
5938 pHddCtx->isLoadUnloadInProgress = FALSE;
5939
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005940#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005941#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5942 /* Initialize the wake lcok */
5943 wake_lock_init(&pHddCtx->rx_wake_lock,
5944 WAKE_LOCK_SUSPEND,
5945 "qcom_rx_wakelock");
5946#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005947 /* Initialize the wake lcok */
5948 wake_lock_init(&pHddCtx->sap_wake_lock,
5949 WAKE_LOCK_SUSPEND,
5950 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005951#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005952
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005953 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5954 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005955
5956 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5957 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305958
Jeff Johnsone7245742012-09-05 17:12:55 -07005959 // Initialize the restart logic
5960 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305961
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305962 if (!VOS_IS_STATUS_SUCCESS( vos_timer_init( &pHddCtx->hdd_p2p_go_conn_is_in_progress,
5963 VOS_TIMER_TYPE_SW, wlan_hdd_p2p_go_connection_in_progresscb, pAdapter) ) )
5964 {
5965 hddLog(VOS_TRACE_LEVEL_ERROR,
5966 "%s: vos timer init failed for hdd_p2p_go_conn_is_in_progress", __func__);
5967 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005968 goto success;
5969
5970err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07005971#ifdef WLAN_KD_READY_NOTIFIER
5972 nl_srv_exit(pHddCtx->ptt_pid);
5973#else
Jeff Johnson295189b2012-06-20 16:38:30 -07005974 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005975#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07005976err_reg_netdev:
5977 unregister_netdevice_notifier(&hdd_netdev_notifier);
5978
5979err_free_power_on_lock:
5980 free_riva_power_on_lock("wlan");
5981
5982err_unregister_pmops:
5983 hddDevTmUnregisterNotifyCallback(pHddCtx);
5984 hddDeregisterPmOps(pHddCtx);
5985
5986#ifdef WLAN_BTAMP_FEATURE
5987err_bap_stop:
5988 WLANBAP_Stop(pVosContext);
5989#endif
5990
5991#ifdef WLAN_BTAMP_FEATURE
5992err_bap_close:
5993 WLANBAP_Close(pVosContext);
5994#endif
5995
Jeff Johnson295189b2012-06-20 16:38:30 -07005996err_close_adapter:
5997 hdd_close_all_adapters( pHddCtx );
5998
5999err_vosstop:
6000 vos_stop(pVosContext);
6001
6002err_vosclose:
6003 status = vos_sched_close( pVosContext );
6004 if (!VOS_IS_STATUS_SUCCESS(status)) {
6005 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
6006 "%s: Failed to close VOSS Scheduler", __func__);
6007 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
6008 }
6009 vos_close(pVosContext );
6010
Jeff Johnson295189b2012-06-20 16:38:30 -07006011err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006012 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006013
6014err_wdclose:
6015 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6016 vos_watchdog_close(pVosContext);
6017
Jeff Johnson295189b2012-06-20 16:38:30 -07006018err_wiphy_reg:
6019 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006020
6021err_config:
6022 kfree(pHddCtx->cfg_ini);
6023 pHddCtx->cfg_ini= NULL;
6024
6025err_free_hdd_context:
6026 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07006027 wiphy_free(wiphy) ;
6028 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006029 VOS_BUG(1);
6030
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08006031 if (hdd_is_ssr_required())
6032 {
6033 /* WDI timeout had happened during load, so SSR is needed here */
6034 subsystem_restart("wcnss");
6035 msleep(5000);
6036 }
6037 hdd_set_ssr_required (VOS_FALSE);
6038
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006039 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006040
6041success:
6042 EXIT();
6043 return 0;
6044}
6045
6046/**---------------------------------------------------------------------------
6047
Jeff Johnson32d95a32012-09-10 13:15:23 -07006048 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07006049
Jeff Johnson32d95a32012-09-10 13:15:23 -07006050 This is the driver entry point - called in different timeline depending
6051 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07006052
6053 \param - None
6054
6055 \return - 0 for success, non zero for failure
6056
6057 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07006058static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006059{
6060 VOS_STATUS status;
6061 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006062 struct device *dev = NULL;
6063 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006064#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6065 int max_retries = 0;
6066#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006067
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306068#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6069 vos_wconn_trace_init();
6070#endif
6071
Jeff Johnson295189b2012-06-20 16:38:30 -07006072 ENTER();
6073
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006074#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006075 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07006076#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006077
6078 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
6079 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
6080
6081 //Power Up Libra WLAN card first if not already powered up
6082 status = vos_chipPowerUp(NULL,NULL,NULL);
6083 if (!VOS_IS_STATUS_SUCCESS(status))
6084 {
6085 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
6086 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306087#ifdef WLAN_OPEN_SOURCE
6088 wake_lock_destroy(&wlan_wake_lock);
6089#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006090 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006091 }
6092
Jeff Johnson295189b2012-06-20 16:38:30 -07006093#ifdef ANI_BUS_TYPE_PCI
6094
6095 dev = wcnss_wlan_get_device();
6096
6097#endif // ANI_BUS_TYPE_PCI
6098
6099#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006100
6101#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6102 /* wait until WCNSS driver downloads NV */
6103 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6104 msleep(1000);
6105 }
6106 if (max_retries >= 5) {
6107 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306108#ifdef WLAN_OPEN_SOURCE
6109 wake_lock_destroy(&wlan_wake_lock);
6110#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006111 return -ENODEV;
6112 }
6113#endif
6114
Jeff Johnson295189b2012-06-20 16:38:30 -07006115 dev = wcnss_wlan_get_device();
6116#endif // ANI_BUS_TYPE_PLATFORM
6117
6118
6119 do {
6120 if (NULL == dev) {
6121 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6122 ret_status = -1;
6123 break;
6124 }
6125
6126#ifdef MEMORY_DEBUG
6127 vos_mem_init();
6128#endif
6129
6130#ifdef TIMER_MANAGER
6131 vos_timer_manager_init();
6132#endif
6133
6134 /* Preopen VOSS so that it is ready to start at least SAL */
6135 status = vos_preOpen(&pVosContext);
6136
6137 if (!VOS_IS_STATUS_SUCCESS(status))
6138 {
6139 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6140 ret_status = -1;
6141 break;
6142 }
6143
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006144#ifndef MODULE
6145 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6146 */
6147 hdd_set_conparam((v_UINT_t)con_mode);
6148#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006149
6150 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006151 if (hdd_wlan_startup(dev))
6152 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006153 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006154 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006155 vos_preClose( &pVosContext );
6156 ret_status = -1;
6157 break;
6158 }
6159
6160 /* Cancel the vote for XO Core ON
6161 * This is done here for safety purposes in case we re-initialize without turning
6162 * it OFF in any error scenario.
6163 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006164 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006165 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006166 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006167 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6168 {
6169 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6170 " Power consumed will be high\n");
6171 }
6172 } while (0);
6173
6174 if (0 != ret_status)
6175 {
6176 //Assert Deep sleep signal now to put Libra HW in lowest power state
6177 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6178 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6179
6180 //Vote off any PMIC voltage supplies
6181 vos_chipPowerDown(NULL, NULL, NULL);
6182#ifdef TIMER_MANAGER
6183 vos_timer_exit();
6184#endif
6185#ifdef MEMORY_DEBUG
6186 vos_mem_exit();
6187#endif
6188
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006189#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006190 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006191#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006192 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6193 }
6194 else
6195 {
6196 //Send WLAN UP indication to Nlink Service
6197 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6198
6199 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07006200 }
6201
6202 EXIT();
6203
6204 return ret_status;
6205}
6206
Jeff Johnson32d95a32012-09-10 13:15:23 -07006207/**---------------------------------------------------------------------------
6208
6209 \brief hdd_module_init() - Init Function
6210
6211 This is the driver entry point (invoked when module is loaded using insmod)
6212
6213 \param - None
6214
6215 \return - 0 for success, non zero for failure
6216
6217 --------------------------------------------------------------------------*/
6218#ifdef MODULE
6219static int __init hdd_module_init ( void)
6220{
6221 return hdd_driver_init();
6222}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006223#else /* #ifdef MODULE */
6224static int __init hdd_module_init ( void)
6225{
6226 /* Driver initialization is delayed to fwpath_changed_handler */
6227 return 0;
6228}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006229#endif /* #ifdef MODULE */
6230
Jeff Johnson295189b2012-06-20 16:38:30 -07006231
6232/**---------------------------------------------------------------------------
6233
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006234 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006235
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006236 This is the driver exit point (invoked when module is unloaded using rmmod
6237 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006238
6239 \param - None
6240
6241 \return - None
6242
6243 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006244static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006245{
6246 hdd_context_t *pHddCtx = NULL;
6247 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006248 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006249
6250 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6251
6252 //Get the global vos context
6253 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6254
6255 if(!pVosContext)
6256 {
6257 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6258 goto done;
6259 }
6260
6261 //Get the HDD context.
6262 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6263
6264 if(!pHddCtx)
6265 {
6266 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6267 }
6268 else
6269 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006270 while(isWDresetInProgress()) {
6271 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6272 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006273 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006274
6275 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6276 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6277 "%s:SSR never completed, fatal error", __func__);
6278 VOS_BUG(0);
6279 }
6280 }
6281
Jeff Johnson295189b2012-06-20 16:38:30 -07006282
6283 pHddCtx->isLoadUnloadInProgress = TRUE;
6284 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6285
6286 //Do all the cleanup before deregistering the driver
6287 hdd_wlan_exit(pHddCtx);
6288 }
6289
Jeff Johnson295189b2012-06-20 16:38:30 -07006290 vos_preClose( &pVosContext );
6291
6292#ifdef TIMER_MANAGER
6293 vos_timer_exit();
6294#endif
6295#ifdef MEMORY_DEBUG
6296 vos_mem_exit();
6297#endif
6298
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306299#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6300 vos_wconn_trace_exit();
6301#endif
6302
Jeff Johnson295189b2012-06-20 16:38:30 -07006303done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006304#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006305 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006306#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006307 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6308}
6309
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006310/**---------------------------------------------------------------------------
6311
6312 \brief hdd_module_exit() - Exit function
6313
6314 This is the driver exit point (invoked when module is unloaded using rmmod)
6315
6316 \param - None
6317
6318 \return - None
6319
6320 --------------------------------------------------------------------------*/
6321static void __exit hdd_module_exit(void)
6322{
6323 hdd_driver_exit();
6324}
6325
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006326#ifdef MODULE
6327static int fwpath_changed_handler(const char *kmessage,
6328 struct kernel_param *kp)
6329{
Jeff Johnson76052702013-04-16 13:55:05 -07006330 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006331}
6332
6333static int con_mode_handler(const char *kmessage,
6334 struct kernel_param *kp)
6335{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006336 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006337}
6338#else /* #ifdef MODULE */
6339/**---------------------------------------------------------------------------
6340
Jeff Johnson76052702013-04-16 13:55:05 -07006341 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006342
Jeff Johnson76052702013-04-16 13:55:05 -07006343 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006344 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006345 - invoked when module parameter fwpath is modified from userspace to signal
6346 initializing the WLAN driver or when con_mode is modified from userspace
6347 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006348
6349 \return - 0 for success, non zero for failure
6350
6351 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006352static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006353{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006354 int ret_status;
6355
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006356 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006357 ret_status = hdd_driver_init();
6358 wlan_hdd_inited = ret_status ? 0 : 1;
6359 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006360 }
6361
6362 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006363
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006364 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006365
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006366 ret_status = hdd_driver_init();
6367 wlan_hdd_inited = ret_status ? 0 : 1;
6368 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006369}
6370
Jeff Johnson295189b2012-06-20 16:38:30 -07006371/**---------------------------------------------------------------------------
6372
Jeff Johnson76052702013-04-16 13:55:05 -07006373 \brief fwpath_changed_handler() - Handler Function
6374
6375 Handle changes to the fwpath parameter
6376
6377 \return - 0 for success, non zero for failure
6378
6379 --------------------------------------------------------------------------*/
6380static int fwpath_changed_handler(const char *kmessage,
6381 struct kernel_param *kp)
6382{
6383 int ret;
6384
6385 ret = param_set_copystring(kmessage, kp);
6386 if (0 == ret)
6387 ret = kickstart_driver();
6388 return ret;
6389}
6390
6391/**---------------------------------------------------------------------------
6392
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006393 \brief con_mode_handler() -
6394
6395 Handler function for module param con_mode when it is changed by userspace
6396 Dynamically linked - do nothing
6397 Statically linked - exit and init driver, as in rmmod and insmod
6398
Jeff Johnson76052702013-04-16 13:55:05 -07006399 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006400
Jeff Johnson76052702013-04-16 13:55:05 -07006401 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006402
6403 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006404static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006405{
Jeff Johnson76052702013-04-16 13:55:05 -07006406 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006407
Jeff Johnson76052702013-04-16 13:55:05 -07006408 ret = param_set_int(kmessage, kp);
6409 if (0 == ret)
6410 ret = kickstart_driver();
6411 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006412}
6413#endif /* #ifdef MODULE */
6414
6415/**---------------------------------------------------------------------------
6416
Jeff Johnson295189b2012-06-20 16:38:30 -07006417 \brief hdd_get_conparam() -
6418
6419 This is the driver exit point (invoked when module is unloaded using rmmod)
6420
6421 \param - None
6422
6423 \return - tVOS_CON_MODE
6424
6425 --------------------------------------------------------------------------*/
6426tVOS_CON_MODE hdd_get_conparam ( void )
6427{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006428#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006429 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006430#else
6431 return (tVOS_CON_MODE)curr_con_mode;
6432#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006433}
6434void hdd_set_conparam ( v_UINT_t newParam )
6435{
6436 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006437#ifndef MODULE
6438 curr_con_mode = con_mode;
6439#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006440}
6441/**---------------------------------------------------------------------------
6442
6443 \brief hdd_softap_sta_deauth() - function
6444
6445 This to take counter measure to handle deauth req from HDD
6446
6447 \param - pAdapter - Pointer to the HDD
6448
6449 \param - enable - boolean value
6450
6451 \return - None
6452
6453 --------------------------------------------------------------------------*/
6454
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006455VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006456{
Jeff Johnson295189b2012-06-20 16:38:30 -07006457 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006458 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006459
6460 ENTER();
6461
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306462 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006463
6464 //Ignore request to deauth bcmc station
6465 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006466 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006467
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006468 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006469
6470 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006471 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006472}
6473
6474/**---------------------------------------------------------------------------
6475
6476 \brief hdd_softap_sta_disassoc() - function
6477
6478 This to take counter measure to handle deauth req from HDD
6479
6480 \param - pAdapter - Pointer to the HDD
6481
6482 \param - enable - boolean value
6483
6484 \return - None
6485
6486 --------------------------------------------------------------------------*/
6487
6488void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6489{
6490 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6491
6492 ENTER();
6493
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306494 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006495
6496 //Ignore request to disassoc bcmc station
6497 if( pDestMacAddress[0] & 0x1 )
6498 return;
6499
6500 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6501}
6502
6503void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6504{
6505 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6506
6507 ENTER();
6508
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306509 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006510
6511 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6512}
6513
Jeff Johnson295189b2012-06-20 16:38:30 -07006514/**---------------------------------------------------------------------------
6515 *
6516 * \brief hdd_get__concurrency_mode() -
6517 *
6518 *
6519 * \param - None
6520 *
6521 * \return - CONCURRENCY MODE
6522 *
6523 * --------------------------------------------------------------------------*/
6524tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6525{
6526 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6527 hdd_context_t *pHddCtx;
6528
6529 if (NULL != pVosContext)
6530 {
6531 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6532 if (NULL != pHddCtx)
6533 {
6534 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6535 }
6536 }
6537
6538 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006539 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006540 return VOS_STA;
6541}
6542
6543/* Decide whether to allow/not the apps power collapse.
6544 * Allow apps power collapse if we are in connected state.
6545 * if not, allow only if we are in IMPS */
6546v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6547{
6548 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006549 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006550 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006551 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6552 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6553 hdd_adapter_t *pAdapter = NULL;
6554 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006555 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006556
Jeff Johnson295189b2012-06-20 16:38:30 -07006557 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6558 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006559
Yathish9f22e662012-12-10 14:21:35 -08006560 concurrent_state = hdd_get_concurrency_mode();
6561
6562#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6563 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6564 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6565 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6566 return TRUE;
6567#endif
6568
Jeff Johnson295189b2012-06-20 16:38:30 -07006569 /*loop through all adapters. TBD fix for Concurrency */
6570 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6571 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6572 {
6573 pAdapter = pAdapterNode->pAdapter;
6574 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6575 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6576 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006577 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006578 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006579 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006580 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6581 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006582 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006583 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006584 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6585 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006586 return FALSE;
6587 }
6588 }
6589 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6590 pAdapterNode = pNext;
6591 }
6592 return TRUE;
6593}
6594
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006595/* Decides whether to send suspend notification to Riva
6596 * if any adapter is in BMPS; then it is required */
6597v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6598{
6599 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6600 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6601
6602 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6603 {
6604 return TRUE;
6605 }
6606 return FALSE;
6607}
6608
Jeff Johnson295189b2012-06-20 16:38:30 -07006609void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6610{
6611 switch(mode)
6612 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006613 case VOS_STA_MODE:
6614 case VOS_P2P_CLIENT_MODE:
6615 case VOS_P2P_GO_MODE:
6616 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006617 pHddCtx->concurrency_mode |= (1 << mode);
6618 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006619 break;
6620 default:
6621 break;
6622
6623 }
6624 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6625 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6626}
6627
6628
6629void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6630{
6631 switch(mode)
6632 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006633 case VOS_STA_MODE:
6634 case VOS_P2P_CLIENT_MODE:
6635 case VOS_P2P_GO_MODE:
6636 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006637 pHddCtx->no_of_sessions[mode]--;
6638 if (!(pHddCtx->no_of_sessions[mode]))
6639 pHddCtx->concurrency_mode &= (~(1 << mode));
6640 break;
6641 default:
6642 break;
6643 }
6644 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6645 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6646}
6647
Jeff Johnsone7245742012-09-05 17:12:55 -07006648/**---------------------------------------------------------------------------
6649 *
6650 * \brief wlan_hdd_restart_init
6651 *
6652 * This function initalizes restart timer/flag. An internal function.
6653 *
6654 * \param - pHddCtx
6655 *
6656 * \return - None
6657 *
6658 * --------------------------------------------------------------------------*/
6659
6660static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6661{
6662 /* Initialize */
6663 pHddCtx->hdd_restart_retries = 0;
6664 atomic_set(&pHddCtx->isRestartInProgress, 0);
6665 vos_timer_init(&pHddCtx->hdd_restart_timer,
6666 VOS_TIMER_TYPE_SW,
6667 wlan_hdd_restart_timer_cb,
6668 pHddCtx);
6669}
6670/**---------------------------------------------------------------------------
6671 *
6672 * \brief wlan_hdd_restart_deinit
6673 *
6674 * This function cleans up the resources used. An internal function.
6675 *
6676 * \param - pHddCtx
6677 *
6678 * \return - None
6679 *
6680 * --------------------------------------------------------------------------*/
6681
6682static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6683{
6684
6685 VOS_STATUS vos_status;
6686 /* Block any further calls */
6687 atomic_set(&pHddCtx->isRestartInProgress, 1);
6688 /* Cleanup */
6689 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6690 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006691 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006692 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6693 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006694 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006695
6696}
6697
6698/**---------------------------------------------------------------------------
6699 *
6700 * \brief wlan_hdd_framework_restart
6701 *
6702 * This function uses a cfg80211 API to start a framework initiated WLAN
6703 * driver module unload/load.
6704 *
6705 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6706 *
6707 *
6708 * \param - pHddCtx
6709 *
6710 * \return - VOS_STATUS_SUCCESS: Success
6711 * VOS_STATUS_E_EMPTY: Adapter is Empty
6712 * VOS_STATUS_E_NOMEM: No memory
6713
6714 * --------------------------------------------------------------------------*/
6715
6716static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6717{
6718 VOS_STATUS status = VOS_STATUS_SUCCESS;
6719 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006720 int len = (sizeof (struct ieee80211_mgmt));
6721 struct ieee80211_mgmt *mgmt = NULL;
6722
6723 /* Prepare the DEAUTH managment frame with reason code */
6724 mgmt = kzalloc(len, GFP_KERNEL);
6725 if(mgmt == NULL)
6726 {
6727 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6728 "%s: memory allocation failed (%d bytes)", __func__, len);
6729 return VOS_STATUS_E_NOMEM;
6730 }
6731 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006732
6733 /* Iterate over all adapters/devices */
6734 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6735 do
6736 {
6737 if( (status == VOS_STATUS_SUCCESS) &&
6738 pAdapterNode &&
6739 pAdapterNode->pAdapter)
6740 {
6741 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6742 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6743 pAdapterNode->pAdapter->dev->name,
6744 pAdapterNode->pAdapter->device_mode,
6745 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006746 /*
6747 * CFG80211 event to restart the driver
6748 *
6749 * 'cfg80211_send_unprot_deauth' sends a
6750 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6751 * of SME(Linux Kernel) state machine.
6752 *
6753 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6754 * the driver.
6755 *
6756 */
6757
6758 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006759 }
6760 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6761 pAdapterNode = pNext;
6762 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6763
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006764
6765 /* Free the allocated management frame */
6766 kfree(mgmt);
6767
Jeff Johnsone7245742012-09-05 17:12:55 -07006768 /* Retry until we unload or reach max count */
6769 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6770 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6771
6772 return status;
6773
6774}
6775/**---------------------------------------------------------------------------
6776 *
6777 * \brief wlan_hdd_restart_timer_cb
6778 *
6779 * Restart timer callback. An internal function.
6780 *
6781 * \param - User data:
6782 *
6783 * \return - None
6784 *
6785 * --------------------------------------------------------------------------*/
6786
6787void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6788{
6789 hdd_context_t *pHddCtx = usrDataForCallback;
6790 wlan_hdd_framework_restart(pHddCtx);
6791 return;
6792
6793}
6794
6795
6796/**---------------------------------------------------------------------------
6797 *
6798 * \brief wlan_hdd_restart_driver
6799 *
6800 * This function sends an event to supplicant to restart the WLAN driver.
6801 *
6802 * This function is called from vos_wlanRestart.
6803 *
6804 * \param - pHddCtx
6805 *
6806 * \return - VOS_STATUS_SUCCESS: Success
6807 * VOS_STATUS_E_EMPTY: Adapter is Empty
6808 * VOS_STATUS_E_ALREADY: Request already in progress
6809
6810 * --------------------------------------------------------------------------*/
6811VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6812{
6813 VOS_STATUS status = VOS_STATUS_SUCCESS;
6814
6815 /* A tight check to make sure reentrancy */
6816 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6817 {
6818 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6819 "%s: WLAN restart is already in progress", __func__);
6820
6821 return VOS_STATUS_E_ALREADY;
6822 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006823 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006824#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006825 wcnss_reset_intr();
6826#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006827
Jeff Johnsone7245742012-09-05 17:12:55 -07006828 return status;
6829}
6830
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006831/*
6832 * API to find if there is any STA or P2P-Client is connected
6833 */
6834VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6835{
6836 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6837}
Jeff Johnsone7245742012-09-05 17:12:55 -07006838
Jeff Johnson295189b2012-06-20 16:38:30 -07006839//Register the module init/exit functions
6840module_init(hdd_module_init);
6841module_exit(hdd_module_exit);
6842
6843MODULE_LICENSE("Dual BSD/GPL");
6844MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6845MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6846
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006847module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6848 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006849
Jeff Johnson76052702013-04-16 13:55:05 -07006850module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006851 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);