blob: 605b7120e558986be2816bb090631ef114d65390 [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 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002055 else {
2056 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2057 __func__, command);
2058 }
2059
Jeff Johnson295189b2012-06-20 16:38:30 -07002060 }
2061exit:
2062 if (command)
2063 {
2064 kfree(command);
2065 }
2066 return ret;
2067}
2068
Srinivas Girigowdade697412013-02-14 16:31:48 -08002069#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2070void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2071{
2072 eCsrBand band = -1;
2073 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2074 switch (band)
2075 {
2076 case eCSR_BAND_ALL:
2077 *pBand = WLAN_HDD_UI_BAND_AUTO;
2078 break;
2079
2080 case eCSR_BAND_24:
2081 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2082 break;
2083
2084 case eCSR_BAND_5G:
2085 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2086 break;
2087
2088 default:
2089 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2090 *pBand = -1;
2091 break;
2092 }
2093}
2094
2095/**---------------------------------------------------------------------------
2096
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002097 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2098
2099 This function parses the send action frame data passed in the format
2100 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2101
2102 \param - pValue Pointer to input country code revision
2103 \param - pTargetApBssid Pointer to target Ap bssid
2104 \param - pChannel Pointer to the Target AP channel
2105 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2106 \param - pBuf Pointer to data
2107 \param - pBufLen Pointer to data length
2108
2109 \return - 0 for success non-zero for failure
2110
2111 --------------------------------------------------------------------------*/
2112VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2113 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2114{
2115 tANI_U8 *inPtr = pValue;
2116 tANI_U8 *dataEnd;
2117 int tempInt;
2118 int j = 0;
2119 int i = 0;
2120 int v = 0;
2121 tANI_U8 tempBuf[32];
2122 tANI_U8 tempByte = 0;
2123
2124 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2125 /*no argument after the command*/
2126 if (NULL == inPtr)
2127 {
2128 return -EINVAL;
2129 }
2130
2131 /*no space after the command*/
2132 else if (SPACE_ASCII_VALUE != *inPtr)
2133 {
2134 return -EINVAL;
2135 }
2136
2137 /*removing empty spaces*/
2138 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2139
2140 /*no argument followed by spaces*/
2141 if ('\0' == *inPtr)
2142 {
2143 return -EINVAL;
2144 }
2145
2146 /*getting the first argument ie the target AP bssid */
2147 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2148 {
2149 return -EINVAL;
2150 }
2151 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2152 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2153 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2154
2155 /* point to the next argument */
2156 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2157 /*no argument after the command*/
2158 if (NULL == inPtr) return -EINVAL;
2159
2160 /*removing empty spaces*/
2161 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2162
2163 /*no argument followed by spaces*/
2164 if ('\0' == *inPtr)
2165 {
2166 return -EINVAL;
2167 }
2168
2169 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002170 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002171 v = kstrtos32(tempBuf, 10, &tempInt);
2172 if ( v < 0) return -EINVAL;
2173
2174 *pChannel = tempInt;
2175
2176 /* point to the next argument */
2177 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2178 /*no argument after the command*/
2179 if (NULL == inPtr) return -EINVAL;
2180 /*removing empty spaces*/
2181 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2182
2183 /*no argument followed by spaces*/
2184 if ('\0' == *inPtr)
2185 {
2186 return -EINVAL;
2187 }
2188
2189 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002190 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002191 v = kstrtos32(tempBuf, 10, &tempInt);
2192 if ( v < 0) return -EINVAL;
2193
2194 *pDwellTime = tempInt;
2195
2196 /* point to the next argument */
2197 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2198 /*no argument after the command*/
2199 if (NULL == inPtr) return -EINVAL;
2200 /*removing empty spaces*/
2201 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2202
2203 /*no argument followed by spaces*/
2204 if ('\0' == *inPtr)
2205 {
2206 return -EINVAL;
2207 }
2208
2209 /* find the length of data */
2210 dataEnd = inPtr;
2211 while(('\0' != *dataEnd) )
2212 {
2213 dataEnd++;
2214 ++(*pBufLen);
2215 }
2216 if ( *pBufLen <= 0) return -EINVAL;
2217
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002218 /* Allocate the number of bytes based on the number of input characters
2219 whether it is even or odd.
2220 if the number of input characters are even, then we need N/2 byte.
2221 if the number of input characters are odd, then we need do (N+1)/2 to
2222 compensate rounding off.
2223 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2224 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2225 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002226 if (NULL == *pBuf)
2227 {
2228 hddLog(VOS_TRACE_LEVEL_FATAL,
2229 "%s: vos_mem_alloc failed ", __func__);
2230 return -EINVAL;
2231 }
2232
2233 /* the buffer received from the upper layer is character buffer,
2234 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2235 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2236 and f0 in 3rd location */
2237 for (i = 0, j = 0; j < *pBufLen; j += 2)
2238 {
2239 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2240 (*pBuf)[i++] = tempByte;
2241 }
2242 *pBufLen = i;
2243 return VOS_STATUS_SUCCESS;
2244}
2245
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002246/**---------------------------------------------------------------------------
2247
Srinivas Girigowdade697412013-02-14 16:31:48 -08002248 \brief hdd_parse_countryrev() - HDD Parse country code revision
2249
2250 This function parses the country code revision passed in the format
2251 SETCOUNTRYREV<space><Country code><space>revision
2252
2253 \param - pValue Pointer to input country code revision
2254 \param - pCountryCode Pointer to local output array to record country code
2255 \param - pRevision Pointer to store revision integer number
2256
2257 \return - 0 for success non-zero for failure
2258
2259 --------------------------------------------------------------------------*/
2260VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
2261{
2262 tANI_U8 *inPtr = pValue;
2263 int tempInt;
2264
2265 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2266 /*no argument after the command*/
2267 if (NULL == inPtr)
2268 {
2269 return -EINVAL;
2270 }
2271
2272 /*no space after the command*/
2273 else if (SPACE_ASCII_VALUE != *inPtr)
2274 {
2275 return -EINVAL;
2276 }
2277
2278 /*removing empty spaces*/
2279 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
2280
2281 /*no argument followed by spaces*/
2282 if ('\0' == *inPtr)
2283 {
2284 return -EINVAL;
2285 }
2286
2287 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07002288 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002289
2290 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2291 "Country code is : %s", pCountryCode);
2292
2293 /*inPtr pointing to the beginning of first space after country code */
2294 inPtr = strpbrk( inPtr, " " );
2295 /*no revision number after the country code argument */
2296 if (NULL == inPtr)
2297 {
2298 return -EINVAL;
2299 }
2300
2301 inPtr++;
2302
2303 /*removing empty space*/
2304 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2305
2306 /*no channel list after the number of channels argument and spaces*/
2307 if (0 == strncmp(pCountryCode, "KR", 2))
2308 {
2309 if ('\0' == *inPtr)
2310 {
2311 return -EINVAL;
2312 }
2313
2314 sscanf(inPtr, "%d", &tempInt);
2315 *pRevision = tempInt;
2316 }
2317 else
2318 {
2319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2320 "Revision input is required only for Country KR");
2321 return -EINVAL;
2322 }
2323 return VOS_STATUS_SUCCESS;
2324}
2325
2326/**---------------------------------------------------------------------------
2327
2328 \brief hdd_parse_channellist() - HDD Parse channel list
2329
2330 This function parses the channel list passed in the format
2331 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002332 if the Number of channels (N) does not match with the actual number of channels passed
2333 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2334 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2335 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2336 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002337
2338 \param - pValue Pointer to input channel list
2339 \param - ChannelList Pointer to local output array to record channel list
2340 \param - pNumChannels Pointer to number of roam scan channels
2341
2342 \return - 0 for success non-zero for failure
2343
2344 --------------------------------------------------------------------------*/
2345VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2346{
2347 tANI_U8 *inPtr = pValue;
2348 int tempInt;
2349 int j = 0;
2350 int v = 0;
2351 char buf[32];
2352
2353 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2354 /*no argument after the command*/
2355 if (NULL == inPtr)
2356 {
2357 return -EINVAL;
2358 }
2359
2360 /*no space after the command*/
2361 else if (SPACE_ASCII_VALUE != *inPtr)
2362 {
2363 return -EINVAL;
2364 }
2365
2366 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002367 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002368
2369 /*no argument followed by spaces*/
2370 if ('\0' == *inPtr)
2371 {
2372 return -EINVAL;
2373 }
2374
2375 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002376 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002377 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002378 if ((v < 0) ||
2379 (tempInt <= 0) ||
2380 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2381 {
2382 return -EINVAL;
2383 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002384
2385 *pNumChannels = tempInt;
2386
2387 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2388 "Number of channels are: %d", *pNumChannels);
2389
2390 for (j = 0; j < (*pNumChannels); j++)
2391 {
2392 /*inPtr pointing to the beginning of first space after number of channels*/
2393 inPtr = strpbrk( inPtr, " " );
2394 /*no channel list after the number of channels argument*/
2395 if (NULL == inPtr)
2396 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002397 if (0 != j)
2398 {
2399 *pNumChannels = j;
2400 return VOS_STATUS_SUCCESS;
2401 }
2402 else
2403 {
2404 return -EINVAL;
2405 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002406 }
2407
2408 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002409 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002410
2411 /*no channel list after the number of channels argument and spaces*/
2412 if ( '\0' == *inPtr )
2413 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002414 if (0 != j)
2415 {
2416 *pNumChannels = j;
2417 return VOS_STATUS_SUCCESS;
2418 }
2419 else
2420 {
2421 return -EINVAL;
2422 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002423 }
2424
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002425 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002426 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002427 if ((v < 0) ||
2428 (tempInt <= 0) ||
2429 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2430 {
2431 return -EINVAL;
2432 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002433 pChannelList[j] = tempInt;
2434
2435 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2436 "Channel %d added to preferred channel list",
2437 pChannelList[j] );
2438 }
2439
Srinivas Girigowdade697412013-02-14 16:31:48 -08002440 return VOS_STATUS_SUCCESS;
2441}
2442
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002443
2444/**---------------------------------------------------------------------------
2445
2446 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2447
2448 This function parses the reasoc command data passed in the format
2449 REASSOC<space><bssid><space><channel>
2450
2451 \param - pValue Pointer to input country code revision
2452 \param - pTargetApBssid Pointer to target Ap bssid
2453 \param - pChannel Pointer to the Target AP channel
2454
2455 \return - 0 for success non-zero for failure
2456
2457 --------------------------------------------------------------------------*/
2458VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2459{
2460 tANI_U8 *inPtr = pValue;
2461 int tempInt;
2462 int v = 0;
2463 tANI_U8 tempBuf[32];
2464
2465 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2466 /*no argument after the command*/
2467 if (NULL == inPtr)
2468 {
2469 return -EINVAL;
2470 }
2471
2472 /*no space after the command*/
2473 else if (SPACE_ASCII_VALUE != *inPtr)
2474 {
2475 return -EINVAL;
2476 }
2477
2478 /*removing empty spaces*/
2479 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2480
2481 /*no argument followed by spaces*/
2482 if ('\0' == *inPtr)
2483 {
2484 return -EINVAL;
2485 }
2486
2487 /*getting the first argument ie the target AP bssid */
2488 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2489 {
2490 return -EINVAL;
2491 }
2492 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2493 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2494 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2495
2496 /* point to the next argument */
2497 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2498 /*no argument after the command*/
2499 if (NULL == inPtr) return -EINVAL;
2500
2501 /*removing empty spaces*/
2502 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2503
2504 /*no argument followed by spaces*/
2505 if ('\0' == *inPtr)
2506 {
2507 return -EINVAL;
2508 }
2509
2510 /*getting the next argument ie the channel number */
2511 sscanf(inPtr, "%s ", tempBuf);
2512 v = kstrtos32(tempBuf, 10, &tempInt);
2513 if ( v < 0) return -EINVAL;
2514
2515 *pChannel = tempInt;
2516 return VOS_STATUS_SUCCESS;
2517}
2518
2519#endif
2520
Jeff Johnson295189b2012-06-20 16:38:30 -07002521/**---------------------------------------------------------------------------
2522
2523 \brief hdd_open() - HDD Open function
2524
2525 This is called in response to ifconfig up
2526
2527 \param - dev Pointer to net_device structure
2528
2529 \return - 0 for success non-zero for failure
2530
2531 --------------------------------------------------------------------------*/
2532int hdd_open (struct net_device *dev)
2533{
2534 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2535 hdd_context_t *pHddCtx;
2536 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2537 VOS_STATUS status;
2538 v_BOOL_t in_standby = TRUE;
2539
2540 if (NULL == pAdapter)
2541 {
2542 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002543 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002544 return -ENODEV;
2545 }
2546
2547 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2548 if (NULL == pHddCtx)
2549 {
2550 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002551 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002552 return -ENODEV;
2553 }
2554
2555 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2556 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2557 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002558 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2559 {
2560 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302561 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002562 in_standby = FALSE;
2563 break;
2564 }
2565 else
2566 {
2567 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2568 pAdapterNode = pNext;
2569 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002570 }
2571
2572 if (TRUE == in_standby)
2573 {
2574 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2575 {
2576 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2577 "wlan out of power save", __func__);
2578 return -EINVAL;
2579 }
2580 }
2581
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002582 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002583 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2584 {
2585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002586 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002587 /* Enable TX queues only when we are connected */
2588 netif_tx_start_all_queues(dev);
2589 }
2590
2591 return 0;
2592}
2593
2594int hdd_mon_open (struct net_device *dev)
2595{
2596 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2597
2598 if(pAdapter == NULL) {
2599 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002600 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002601 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002602 }
2603
2604 netif_start_queue(dev);
2605
2606 return 0;
2607}
2608/**---------------------------------------------------------------------------
2609
2610 \brief hdd_stop() - HDD stop function
2611
2612 This is called in response to ifconfig down
2613
2614 \param - dev Pointer to net_device structure
2615
2616 \return - 0 for success non-zero for failure
2617
2618 --------------------------------------------------------------------------*/
2619
2620int hdd_stop (struct net_device *dev)
2621{
2622 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2623 hdd_context_t *pHddCtx;
2624 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2625 VOS_STATUS status;
2626 v_BOOL_t enter_standby = TRUE;
2627
2628 ENTER();
2629
2630 if (NULL == pAdapter)
2631 {
2632 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002633 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002634 return -ENODEV;
2635 }
2636
2637 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2638 if (NULL == pHddCtx)
2639 {
2640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002641 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002642 return -ENODEV;
2643 }
2644
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002645 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002646 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2647 netif_tx_disable(pAdapter->dev);
2648 netif_carrier_off(pAdapter->dev);
2649
2650
2651 /* SoftAP ifaces should never go in power save mode
2652 making sure same here. */
2653 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2654 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002655 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002656 )
2657 {
2658 /* SoftAP mode, so return from here */
2659 EXIT();
2660 return 0;
2661 }
2662
2663 /* Find if any iface is up then
2664 if any iface is up then can't put device to sleep/ power save mode. */
2665 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2666 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2667 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002668 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2669 {
2670 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302671 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002672 enter_standby = FALSE;
2673 break;
2674 }
2675 else
2676 {
2677 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2678 pAdapterNode = pNext;
2679 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002680 }
2681
2682 if (TRUE == enter_standby)
2683 {
2684 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2685 "entering standby", __func__);
2686 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2687 {
2688 /*log and return success*/
2689 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2690 "wlan in power save", __func__);
2691 }
2692 }
2693
2694 EXIT();
2695 return 0;
2696}
2697
2698/**---------------------------------------------------------------------------
2699
2700 \brief hdd_uninit() - HDD uninit function
2701
2702 This is called during the netdev unregister to uninitialize all data
2703associated with the device
2704
2705 \param - dev Pointer to net_device structure
2706
2707 \return - void
2708
2709 --------------------------------------------------------------------------*/
2710static void hdd_uninit (struct net_device *dev)
2711{
2712 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2713
2714 ENTER();
2715
2716 do
2717 {
2718 if (NULL == pAdapter)
2719 {
2720 hddLog(VOS_TRACE_LEVEL_FATAL,
2721 "%s: NULL pAdapter", __func__);
2722 break;
2723 }
2724
2725 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2726 {
2727 hddLog(VOS_TRACE_LEVEL_FATAL,
2728 "%s: Invalid magic", __func__);
2729 break;
2730 }
2731
2732 if (NULL == pAdapter->pHddCtx)
2733 {
2734 hddLog(VOS_TRACE_LEVEL_FATAL,
2735 "%s: NULL pHddCtx", __func__);
2736 break;
2737 }
2738
2739 if (dev != pAdapter->dev)
2740 {
2741 hddLog(VOS_TRACE_LEVEL_FATAL,
2742 "%s: Invalid device reference", __func__);
2743 /* we haven't validated all cases so let this go for now */
2744 }
2745
2746 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2747
2748 /* after uninit our adapter structure will no longer be valid */
2749 pAdapter->dev = NULL;
2750 pAdapter->magic = 0;
2751 } while (0);
2752
2753 EXIT();
2754}
2755
2756/**---------------------------------------------------------------------------
2757
2758 \brief hdd_release_firmware() -
2759
2760 This function calls the release firmware API to free the firmware buffer.
2761
2762 \param - pFileName Pointer to the File Name.
2763 pCtx - Pointer to the adapter .
2764
2765
2766 \return - 0 for success, non zero for failure
2767
2768 --------------------------------------------------------------------------*/
2769
2770VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2771{
2772 VOS_STATUS status = VOS_STATUS_SUCCESS;
2773 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2774 ENTER();
2775
2776
2777 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2778
2779 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2780
2781 if(pHddCtx->fw) {
2782 release_firmware(pHddCtx->fw);
2783 pHddCtx->fw = NULL;
2784 }
2785 else
2786 status = VOS_STATUS_E_FAILURE;
2787 }
2788 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2789 if(pHddCtx->nv) {
2790 release_firmware(pHddCtx->nv);
2791 pHddCtx->nv = NULL;
2792 }
2793 else
2794 status = VOS_STATUS_E_FAILURE;
2795
2796 }
2797
2798 EXIT();
2799 return status;
2800}
2801
2802/**---------------------------------------------------------------------------
2803
2804 \brief hdd_request_firmware() -
2805
2806 This function reads the firmware file using the request firmware
2807 API and returns the the firmware data and the firmware file size.
2808
2809 \param - pfileName - Pointer to the file name.
2810 - pCtx - Pointer to the adapter .
2811 - ppfw_data - Pointer to the pointer of the firmware data.
2812 - pSize - Pointer to the file size.
2813
2814 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2815
2816 --------------------------------------------------------------------------*/
2817
2818
2819VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2820{
2821 int status;
2822 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2823 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2824 ENTER();
2825
2826 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2827
2828 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2829
2830 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2831 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2832 __func__, pfileName);
2833 retval = VOS_STATUS_E_FAILURE;
2834 }
2835
2836 else {
2837 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2838 *pSize = pHddCtx->fw->size;
2839 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2840 __func__, *pSize);
2841 }
2842 }
2843 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2844
2845 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2846
2847 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2848 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2849 __func__, pfileName);
2850 retval = VOS_STATUS_E_FAILURE;
2851 }
2852
2853 else {
2854 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2855 *pSize = pHddCtx->nv->size;
2856 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2857 __func__, *pSize);
2858 }
2859 }
2860
2861 EXIT();
2862 return retval;
2863}
2864/**---------------------------------------------------------------------------
2865 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2866
2867 This is the function invoked by SME to inform the result of a full power
2868 request issued by HDD
2869
2870 \param - callbackcontext - Pointer to cookie
2871 status - result of request
2872
2873 \return - None
2874
2875--------------------------------------------------------------------------*/
2876void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2877{
2878 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2879
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002880 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002881 if(&pHddCtx->full_pwr_comp_var)
2882 {
2883 complete(&pHddCtx->full_pwr_comp_var);
2884 }
2885}
2886
2887/**---------------------------------------------------------------------------
2888
2889 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2890
2891 This is the function invoked by SME to inform the result of BMPS
2892 request issued by HDD
2893
2894 \param - callbackcontext - Pointer to cookie
2895 status - result of request
2896
2897 \return - None
2898
2899--------------------------------------------------------------------------*/
2900void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2901{
2902
2903 struct completion *completion_var = (struct completion*) callbackContext;
2904
2905 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2906 if(completion_var != NULL)
2907 {
2908 complete(completion_var);
2909 }
2910}
2911
2912/**---------------------------------------------------------------------------
2913
2914 \brief hdd_get_cfg_file_size() -
2915
2916 This function reads the configuration file using the request firmware
2917 API and returns the configuration file size.
2918
2919 \param - pCtx - Pointer to the adapter .
2920 - pFileName - Pointer to the file name.
2921 - pBufSize - Pointer to the buffer size.
2922
2923 \return - 0 for success, non zero for failure
2924
2925 --------------------------------------------------------------------------*/
2926
2927VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2928{
2929 int status;
2930 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2931
2932 ENTER();
2933
2934 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2935
2936 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2937 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2938 status = VOS_STATUS_E_FAILURE;
2939 }
2940 else {
2941 *pBufSize = pHddCtx->fw->size;
2942 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2943 release_firmware(pHddCtx->fw);
2944 pHddCtx->fw = NULL;
2945 }
2946
2947 EXIT();
2948 return VOS_STATUS_SUCCESS;
2949}
2950
2951/**---------------------------------------------------------------------------
2952
2953 \brief hdd_read_cfg_file() -
2954
2955 This function reads the configuration file using the request firmware
2956 API and returns the cfg data and the buffer size of the configuration file.
2957
2958 \param - pCtx - Pointer to the adapter .
2959 - pFileName - Pointer to the file name.
2960 - pBuffer - Pointer to the data buffer.
2961 - pBufSize - Pointer to the buffer size.
2962
2963 \return - 0 for success, non zero for failure
2964
2965 --------------------------------------------------------------------------*/
2966
2967VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2968 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2969{
2970 int status;
2971 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2972
2973 ENTER();
2974
2975 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2976
2977 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2978 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2979 return VOS_STATUS_E_FAILURE;
2980 }
2981 else {
2982 if(*pBufSize != pHddCtx->fw->size) {
2983 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2984 "file size", __func__);
2985 release_firmware(pHddCtx->fw);
2986 pHddCtx->fw = NULL;
2987 return VOS_STATUS_E_FAILURE;
2988 }
2989 else {
2990 if(pBuffer) {
2991 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2992 }
2993 release_firmware(pHddCtx->fw);
2994 pHddCtx->fw = NULL;
2995 }
2996 }
2997
2998 EXIT();
2999
3000 return VOS_STATUS_SUCCESS;
3001}
3002
3003/**---------------------------------------------------------------------------
3004
Jeff Johnson295189b2012-06-20 16:38:30 -07003005 \brief hdd_set_mac_address() -
3006
3007 This function sets the user specified mac address using
3008 the command ifconfig wlanX hw ether <mac adress>.
3009
3010 \param - dev - Pointer to the net device.
3011 - addr - Pointer to the sockaddr.
3012 \return - 0 for success, non zero for failure
3013
3014 --------------------------------------------------------------------------*/
3015
3016static int hdd_set_mac_address(struct net_device *dev, void *addr)
3017{
3018 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3019 struct sockaddr *psta_mac_addr = addr;
3020 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3021
3022 ENTER();
3023
3024 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
3025
3026#ifdef HDD_SESSIONIZE
3027 // set the MAC address though the STA ID CFG.
3028 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
3029 (v_U8_t *)&pAdapter->macAddressCurrent,
3030 sizeof( pAdapter->macAddressCurrent ),
3031 hdd_set_mac_addr_cb, VOS_FALSE );
3032#endif
3033
3034 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
3035
3036 EXIT();
3037 return halStatus;
3038}
3039
3040tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
3041{
3042 int i;
3043 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3044 {
3045 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
3046 break;
3047 }
3048
3049 if( VOS_MAX_CONCURRENCY_PERSONA == i)
3050 return NULL;
3051
3052 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
3053 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
3054}
3055
3056void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
3057{
3058 int i;
3059 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3060 {
3061 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
3062 {
3063 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
3064 break;
3065 }
3066 }
3067 return;
3068}
3069
3070#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3071 static struct net_device_ops wlan_drv_ops = {
3072 .ndo_open = hdd_open,
3073 .ndo_stop = hdd_stop,
3074 .ndo_uninit = hdd_uninit,
3075 .ndo_start_xmit = hdd_hard_start_xmit,
3076 .ndo_tx_timeout = hdd_tx_timeout,
3077 .ndo_get_stats = hdd_stats,
3078 .ndo_do_ioctl = hdd_ioctl,
3079 .ndo_set_mac_address = hdd_set_mac_address,
3080 .ndo_select_queue = hdd_select_queue,
3081#ifdef WLAN_FEATURE_PACKET_FILTERING
3082#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3083 .ndo_set_rx_mode = hdd_set_multicast_list,
3084#else
3085 .ndo_set_multicast_list = hdd_set_multicast_list,
3086#endif //LINUX_VERSION_CODE
3087#endif
3088 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003089 static struct net_device_ops wlan_mon_drv_ops = {
3090 .ndo_open = hdd_mon_open,
3091 .ndo_stop = hdd_stop,
3092 .ndo_uninit = hdd_uninit,
3093 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3094 .ndo_tx_timeout = hdd_tx_timeout,
3095 .ndo_get_stats = hdd_stats,
3096 .ndo_do_ioctl = hdd_ioctl,
3097 .ndo_set_mac_address = hdd_set_mac_address,
3098 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003099
3100#endif
3101
3102void hdd_set_station_ops( struct net_device *pWlanDev )
3103{
3104#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3105 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3106 pWlanDev->netdev_ops = &wlan_drv_ops;
3107#else
3108 pWlanDev->open = hdd_open;
3109 pWlanDev->stop = hdd_stop;
3110 pWlanDev->uninit = hdd_uninit;
3111 pWlanDev->hard_start_xmit = NULL;
3112 pWlanDev->tx_timeout = hdd_tx_timeout;
3113 pWlanDev->get_stats = hdd_stats;
3114 pWlanDev->do_ioctl = hdd_ioctl;
3115 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3116 pWlanDev->set_mac_address = hdd_set_mac_address;
3117#endif
3118}
3119
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003120static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003121{
3122 struct net_device *pWlanDev = NULL;
3123 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003124 /*
3125 * cfg80211 initialization and registration....
3126 */
3127 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3128
Jeff Johnson295189b2012-06-20 16:38:30 -07003129 if(pWlanDev != NULL)
3130 {
3131
3132 //Save the pointer to the net_device in the HDD adapter
3133 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3134
Jeff Johnson295189b2012-06-20 16:38:30 -07003135 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3136
3137 pAdapter->dev = pWlanDev;
3138 pAdapter->pHddCtx = pHddCtx;
3139 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3140
3141 init_completion(&pAdapter->session_open_comp_var);
3142 init_completion(&pAdapter->session_close_comp_var);
3143 init_completion(&pAdapter->disconnect_comp_var);
3144 init_completion(&pAdapter->linkup_event_var);
3145 init_completion(&pAdapter->cancel_rem_on_chan_var);
3146 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003147#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3148 init_completion(&pAdapter->offchannel_tx_event);
3149#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003150 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003151#ifdef FEATURE_WLAN_TDLS
3152 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003153 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003154 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303155 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003156#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003157 init_completion(&pHddCtx->mc_sus_event_var);
3158 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303159 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003160 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003161
Jeff Johnson295189b2012-06-20 16:38:30 -07003162 pAdapter->isLinkUpSvcNeeded = FALSE;
3163 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3164 //Init the net_device structure
3165 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3166
3167 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3168 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3169 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3170 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3171
3172 hdd_set_station_ops( pAdapter->dev );
3173
3174 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003175 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3176 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3177 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003178 /* set pWlanDev's parent to underlying device */
3179 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3180 }
3181
3182 return pAdapter;
3183}
3184
3185VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3186{
3187 struct net_device *pWlanDev = pAdapter->dev;
3188 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3189 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3190 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3191
3192 if( rtnl_lock_held )
3193 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003194 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003195 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3196 {
3197 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3198 return VOS_STATUS_E_FAILURE;
3199 }
3200 }
3201 if (register_netdevice(pWlanDev))
3202 {
3203 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3204 return VOS_STATUS_E_FAILURE;
3205 }
3206 }
3207 else
3208 {
3209 if(register_netdev(pWlanDev))
3210 {
3211 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3212 return VOS_STATUS_E_FAILURE;
3213 }
3214 }
3215 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3216
3217 return VOS_STATUS_SUCCESS;
3218}
3219
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003220static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003221{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003222 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003223
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003224 if (NULL == pAdapter)
3225 {
3226 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3227 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003228 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003229
3230 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3231 {
3232 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3233 return eHAL_STATUS_NOT_INITIALIZED;
3234 }
3235
3236 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3237
3238 /* need to make sure all of our scheduled work has completed.
3239 * This callback is called from MC thread context, so it is safe to
3240 * to call below flush workqueue API from here.
3241 */
3242 flush_scheduled_work();
3243
3244 /* We can be blocked while waiting for scheduled work to be
3245 * flushed, and the adapter structure can potentially be freed, in
3246 * which case the magic will have been reset. So make sure the
3247 * magic is still good, and hence the adapter structure is still
3248 * valid, before signaling completion */
3249 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3250 {
3251 complete(&pAdapter->session_close_comp_var);
3252 }
3253
Jeff Johnson295189b2012-06-20 16:38:30 -07003254 return eHAL_STATUS_SUCCESS;
3255}
3256
3257VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3258{
3259 struct net_device *pWlanDev = pAdapter->dev;
3260 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3261 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3262 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3263 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3264 int rc = 0;
3265
3266 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003267 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003268 //Open a SME session for future operation
3269 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003270 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003271 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3272 {
3273 hddLog(VOS_TRACE_LEVEL_FATAL,
3274 "sme_OpenSession() failed with status code %08d [x%08lx]",
3275 halStatus, halStatus );
3276 status = VOS_STATUS_E_FAILURE;
3277 goto error_sme_open;
3278 }
3279
3280 //Block on a completion variable. Can't wait forever though.
3281 rc = wait_for_completion_interruptible_timeout(
3282 &pAdapter->session_open_comp_var,
3283 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3284 if (!rc)
3285 {
3286 hddLog(VOS_TRACE_LEVEL_FATAL,
3287 "Session is not opened within timeout period code %08d", rc );
3288 status = VOS_STATUS_E_FAILURE;
3289 goto error_sme_open;
3290 }
3291
3292 // Register wireless extensions
3293 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3294 {
3295 hddLog(VOS_TRACE_LEVEL_FATAL,
3296 "hdd_register_wext() failed with status code %08d [x%08lx]",
3297 halStatus, halStatus );
3298 status = VOS_STATUS_E_FAILURE;
3299 goto error_register_wext;
3300 }
3301 //Safe to register the hard_start_xmit function again
3302#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3303 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3304#else
3305 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3306#endif
3307
3308 //Set the Connection State to Not Connected
3309 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3310
3311 //Set the default operation channel
3312 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3313
3314 /* Make the default Auth Type as OPEN*/
3315 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3316
3317 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3318 {
3319 hddLog(VOS_TRACE_LEVEL_FATAL,
3320 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3321 status, status );
3322 goto error_init_txrx;
3323 }
3324
3325 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3326
3327 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3328 {
3329 hddLog(VOS_TRACE_LEVEL_FATAL,
3330 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3331 status, status );
3332 goto error_wmm_init;
3333 }
3334
3335 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3336
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003337#ifdef FEATURE_WLAN_TDLS
3338 if(0 != wlan_hdd_tdls_init(pAdapter))
3339 {
3340 status = VOS_STATUS_E_FAILURE;
3341 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3342 goto error_tdls_init;
3343 }
3344 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3345#endif
3346
Jeff Johnson295189b2012-06-20 16:38:30 -07003347 return VOS_STATUS_SUCCESS;
3348
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003349#ifdef FEATURE_WLAN_TDLS
3350error_tdls_init:
3351 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3352 hdd_wmm_adapter_close(pAdapter);
3353#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003354error_wmm_init:
3355 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3356 hdd_deinit_tx_rx(pAdapter);
3357error_init_txrx:
3358 hdd_UnregisterWext(pWlanDev);
3359error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003360 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003361 {
3362 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003363 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003364 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003365 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003366 {
3367 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003368 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003369 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003370 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003371 }
3372}
3373error_sme_open:
3374 return status;
3375}
3376
Jeff Johnson295189b2012-06-20 16:38:30 -07003377void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3378{
3379 hdd_cfg80211_state_t *cfgState;
3380
3381 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3382
3383 if( NULL != cfgState->buf )
3384 {
3385 int rc;
3386 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3387 rc = wait_for_completion_interruptible_timeout(
3388 &pAdapter->tx_action_cnf_event,
3389 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3390 if(!rc)
3391 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003392 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003393 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3394 }
3395 }
3396 return;
3397}
Jeff Johnson295189b2012-06-20 16:38:30 -07003398
3399void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3400{
3401 ENTER();
3402 switch ( pAdapter->device_mode )
3403 {
3404 case WLAN_HDD_INFRA_STATION:
3405 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003406 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003407 {
3408 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3409 {
3410 hdd_deinit_tx_rx( pAdapter );
3411 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3412 }
3413
3414 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3415 {
3416 hdd_wmm_adapter_close( pAdapter );
3417 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3418 }
3419
Jeff Johnson295189b2012-06-20 16:38:30 -07003420 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003421#ifdef FEATURE_WLAN_TDLS
3422 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3423 {
3424 wlan_hdd_tdls_exit(pAdapter);
3425 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3426 }
3427#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003428
3429 break;
3430 }
3431
3432 case WLAN_HDD_SOFTAP:
3433 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003434 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003435 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003436
3437 hdd_unregister_hostapd(pAdapter);
3438 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003439 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003440 break;
3441 }
3442
3443 case WLAN_HDD_MONITOR:
3444 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003445 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003446 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3447 {
3448 hdd_deinit_tx_rx( pAdapter );
3449 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3450 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003451 if(NULL != pAdapterforTx)
3452 {
3453 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3454 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003455 break;
3456 }
3457
3458
3459 default:
3460 break;
3461 }
3462
3463 EXIT();
3464}
3465
3466void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3467{
3468 struct net_device *pWlanDev = pAdapter->dev;
3469
3470 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3471 if( rtnl_held )
3472 {
3473 unregister_netdevice(pWlanDev);
3474 }
3475 else
3476 {
3477 unregister_netdev(pWlanDev);
3478 }
3479 // note that the pAdapter is no longer valid at this point
3480 // since the memory has been reclaimed
3481 }
3482
3483}
3484
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003485void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3486{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303487 VOS_STATUS status;
3488 hdd_adapter_t *pAdapter = NULL;
3489 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003490
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303491 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003492
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303493 /*loop through all adapters.*/
3494 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003495 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303496 pAdapter = pAdapterNode->pAdapter;
3497 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3498 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003499
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303500 { // we skip this registration for modes other than STA and P2P client modes.
3501 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3502 pAdapterNode = pNext;
3503 continue;
3504 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003505
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303506 //Apply Dynamic DTIM For P2P
3507 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3508 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3509 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3510 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3511 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3512 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3513 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3514 (eConnectionState_Associated ==
3515 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3516 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3517 {
3518 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003519
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303520 powerRequest.uIgnoreDTIM = 1;
3521 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3522
3523 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3524 {
3525 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3526 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3527 }
3528 else
3529 {
3530 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3531 }
3532
3533 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3534 * specified during Enter/Exit BMPS when LCD off*/
3535 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3536 NULL, eANI_BOOLEAN_FALSE);
3537 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3538 NULL, eANI_BOOLEAN_FALSE);
3539
3540 /* switch to the DTIM specified in cfg.ini */
3541 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3542 "Switch to DTIM %d", powerRequest.uListenInterval);
3543 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3544 break;
3545
3546 }
3547
3548 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3549 pAdapterNode = pNext;
3550 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003551}
3552
3553void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3554{
3555 /*Switch back to DTIM 1*/
3556 tSirSetPowerParamsReq powerRequest = { 0 };
3557
3558 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3559 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003560 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003561
3562 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3563 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3564 NULL, eANI_BOOLEAN_FALSE);
3565 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3566 NULL, eANI_BOOLEAN_FALSE);
3567
3568 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3569 "Switch to DTIM%d",powerRequest.uListenInterval);
3570 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3571
3572}
3573
Jeff Johnson295189b2012-06-20 16:38:30 -07003574VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3575{
3576 VOS_STATUS status = VOS_STATUS_SUCCESS;
3577
3578 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3579 {
3580 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3581 }
3582
3583 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3584 {
3585 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3586 }
3587
3588 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3589 {
3590 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3591 }
3592
3593 return status;
3594}
3595
3596VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3597{
3598 hdd_adapter_t *pAdapter = NULL;
3599 eHalStatus halStatus;
3600 VOS_STATUS status = VOS_STATUS_E_INVAL;
3601 v_BOOL_t disableBmps = FALSE;
3602 v_BOOL_t disableImps = FALSE;
3603
3604 switch(session_type)
3605 {
3606 case WLAN_HDD_INFRA_STATION:
3607 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003608 case WLAN_HDD_P2P_CLIENT:
3609 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003610 //Exit BMPS -> Is Sta/P2P Client is already connected
3611 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3612 if((NULL != pAdapter)&&
3613 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3614 {
3615 disableBmps = TRUE;
3616 }
3617
3618 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3619 if((NULL != pAdapter)&&
3620 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3621 {
3622 disableBmps = TRUE;
3623 }
3624
3625 //Exit both Bmps and Imps incase of Go/SAP Mode
3626 if((WLAN_HDD_SOFTAP == session_type) ||
3627 (WLAN_HDD_P2P_GO == session_type))
3628 {
3629 disableBmps = TRUE;
3630 disableImps = TRUE;
3631 }
3632
3633 if(TRUE == disableImps)
3634 {
3635 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3636 {
3637 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3638 }
3639 }
3640
3641 if(TRUE == disableBmps)
3642 {
3643 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3644 {
3645 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3646
3647 if(eHAL_STATUS_SUCCESS != halStatus)
3648 {
3649 status = VOS_STATUS_E_FAILURE;
3650 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3651 VOS_ASSERT(0);
3652 return status;
3653 }
3654 }
3655
3656 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3657 {
3658 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3659
3660 if(eHAL_STATUS_SUCCESS != halStatus)
3661 {
3662 status = VOS_STATUS_E_FAILURE;
3663 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3664 VOS_ASSERT(0);
3665 return status;
3666 }
3667 }
3668 }
3669
3670 if((TRUE == disableBmps) ||
3671 (TRUE == disableImps))
3672 {
3673 /* Now, get the chip into Full Power now */
3674 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3675 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3676 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3677
3678 if(halStatus != eHAL_STATUS_SUCCESS)
3679 {
3680 if(halStatus == eHAL_STATUS_PMC_PENDING)
3681 {
3682 //Block on a completion variable. Can't wait forever though
3683 wait_for_completion_interruptible_timeout(
3684 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3685 }
3686 else
3687 {
3688 status = VOS_STATUS_E_FAILURE;
3689 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3690 VOS_ASSERT(0);
3691 return status;
3692 }
3693 }
3694
3695 status = VOS_STATUS_SUCCESS;
3696 }
3697
3698 break;
3699 }
3700 return status;
3701}
3702
3703hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003704 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003705 tANI_U8 rtnl_held )
3706{
3707 hdd_adapter_t *pAdapter = NULL;
3708 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3709 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3710 VOS_STATUS exitbmpsStatus;
3711
3712 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3713
3714 //Disable BMPS incase of Concurrency
3715 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3716
3717 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3718 {
3719 //Fail to Exit BMPS
3720 VOS_ASSERT(0);
3721 return NULL;
3722 }
3723
3724 switch(session_type)
3725 {
3726 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003727 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003728 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003729 {
3730 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3731
3732 if( NULL == pAdapter )
3733 return NULL;
3734
Jeff Johnsone7245742012-09-05 17:12:55 -07003735 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3736 NL80211_IFTYPE_P2P_CLIENT:
3737 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003738
Jeff Johnson295189b2012-06-20 16:38:30 -07003739 pAdapter->device_mode = session_type;
3740
3741 status = hdd_init_station_mode( pAdapter );
3742 if( VOS_STATUS_SUCCESS != status )
3743 goto err_free_netdev;
3744
3745 status = hdd_register_interface( pAdapter, rtnl_held );
3746 if( VOS_STATUS_SUCCESS != status )
3747 {
3748 hdd_deinit_adapter(pHddCtx, pAdapter);
3749 goto err_free_netdev;
3750 }
3751 //Stop the Interface TX queue.
3752 netif_tx_disable(pAdapter->dev);
3753 //netif_tx_disable(pWlanDev);
3754 netif_carrier_off(pAdapter->dev);
3755
3756 break;
3757 }
3758
Jeff Johnson295189b2012-06-20 16:38:30 -07003759 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003760 case WLAN_HDD_SOFTAP:
3761 {
3762 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3763 if( NULL == pAdapter )
3764 return NULL;
3765
Jeff Johnson295189b2012-06-20 16:38:30 -07003766 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3767 NL80211_IFTYPE_AP:
3768 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003769 pAdapter->device_mode = session_type;
3770
3771 status = hdd_init_ap_mode(pAdapter);
3772 if( VOS_STATUS_SUCCESS != status )
3773 goto err_free_netdev;
3774
3775 status = hdd_register_hostapd( pAdapter, rtnl_held );
3776 if( VOS_STATUS_SUCCESS != status )
3777 {
3778 hdd_deinit_adapter(pHddCtx, pAdapter);
3779 goto err_free_netdev;
3780 }
3781
3782 netif_tx_disable(pAdapter->dev);
3783 netif_carrier_off(pAdapter->dev);
3784
3785 hdd_set_conparam( 1 );
3786 break;
3787 }
3788 case WLAN_HDD_MONITOR:
3789 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003790 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3791 if( NULL == pAdapter )
3792 return NULL;
3793
3794 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3795 pAdapter->device_mode = session_type;
3796 status = hdd_register_interface( pAdapter, rtnl_held );
3797#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3798 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3799#else
3800 pAdapter->dev->open = hdd_mon_open;
3801 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3802#endif
3803 hdd_init_tx_rx( pAdapter );
3804 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3805 //Set adapter to be used for data tx. It will use either GO or softap.
3806 pAdapter->sessionCtx.monitor.pAdapterForTx =
3807 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003808 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3809 {
3810 pAdapter->sessionCtx.monitor.pAdapterForTx =
3811 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3812 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003813 /* This workqueue will be used to transmit management packet over
3814 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003815 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3816 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3817 return NULL;
3818 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003819
Jeff Johnson295189b2012-06-20 16:38:30 -07003820 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3821 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003822 }
3823 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003824 case WLAN_HDD_FTM:
3825 {
3826 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3827
3828 if( NULL == pAdapter )
3829 return NULL;
3830 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3831 * message while loading driver in FTM mode. */
3832 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3833 pAdapter->device_mode = session_type;
3834 status = hdd_register_interface( pAdapter, rtnl_held );
3835 }
3836 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003837 default:
3838 {
3839 VOS_ASSERT(0);
3840 return NULL;
3841 }
3842 }
3843
3844
3845 if( VOS_STATUS_SUCCESS == status )
3846 {
3847 //Add it to the hdd's session list.
3848 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3849 if( NULL == pHddAdapterNode )
3850 {
3851 status = VOS_STATUS_E_NOMEM;
3852 }
3853 else
3854 {
3855 pHddAdapterNode->pAdapter = pAdapter;
3856 status = hdd_add_adapter_back ( pHddCtx,
3857 pHddAdapterNode );
3858 }
3859 }
3860
3861 if( VOS_STATUS_SUCCESS != status )
3862 {
3863 if( NULL != pAdapter )
3864 {
3865 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3866 pAdapter = NULL;
3867 }
3868 if( NULL != pHddAdapterNode )
3869 {
3870 vos_mem_free( pHddAdapterNode );
3871 }
3872
3873 goto resume_bmps;
3874 }
3875
3876 if(VOS_STATUS_SUCCESS == status)
3877 {
3878 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3879
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003880 //Initialize the WoWL service
3881 if(!hdd_init_wowl(pAdapter))
3882 {
3883 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3884 goto err_free_netdev;
3885 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003886 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003887 return pAdapter;
3888
3889err_free_netdev:
3890 free_netdev(pAdapter->dev);
3891 wlan_hdd_release_intf_addr( pHddCtx,
3892 pAdapter->macAddressCurrent.bytes );
3893
3894resume_bmps:
3895 //If bmps disabled enable it
3896 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3897 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303898 if (pHddCtx->hdd_wlan_suspended)
3899 {
3900 hdd_set_pwrparams(pHddCtx);
3901 }
3902 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003903 }
3904 return NULL;
3905}
3906
3907VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3908 tANI_U8 rtnl_held )
3909{
3910 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3911 VOS_STATUS status;
3912
3913 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3914 if( VOS_STATUS_SUCCESS != status )
3915 return status;
3916
3917 while ( pCurrent->pAdapter != pAdapter )
3918 {
3919 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3920 if( VOS_STATUS_SUCCESS != status )
3921 break;
3922
3923 pCurrent = pNext;
3924 }
3925 pAdapterNode = pCurrent;
3926 if( VOS_STATUS_SUCCESS == status )
3927 {
3928 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3929 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3930 hdd_remove_adapter( pHddCtx, pAdapterNode );
3931 vos_mem_free( pAdapterNode );
3932
Jeff Johnson295189b2012-06-20 16:38:30 -07003933
3934 /* If there is a single session of STA/P2P client, re-enable BMPS */
3935 if ((!vos_concurrent_sessions_running()) &&
3936 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3937 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3938 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303939 if (pHddCtx->hdd_wlan_suspended)
3940 {
3941 hdd_set_pwrparams(pHddCtx);
3942 }
3943 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003944 }
3945
3946 return VOS_STATUS_SUCCESS;
3947 }
3948
3949 return VOS_STATUS_E_FAILURE;
3950}
3951
3952VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3953{
3954 hdd_adapter_list_node_t *pHddAdapterNode;
3955 VOS_STATUS status;
3956
3957 ENTER();
3958
3959 do
3960 {
3961 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3962 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3963 {
3964 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3965 vos_mem_free( pHddAdapterNode );
3966 }
3967 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3968
3969 EXIT();
3970
3971 return VOS_STATUS_SUCCESS;
3972}
3973
3974void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3975{
3976 v_U8_t addIE[1] = {0};
3977
3978 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3979 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3980 eANI_BOOLEAN_FALSE) )
3981 {
3982 hddLog(LOGE,
3983 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3984 }
3985
3986 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3987 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3988 eANI_BOOLEAN_FALSE) )
3989 {
3990 hddLog(LOGE,
3991 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3992 }
3993
3994 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3995 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3996 eANI_BOOLEAN_FALSE) )
3997 {
3998 hddLog(LOGE,
3999 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
4000 }
4001}
4002
4003VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4004{
4005 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4006 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4007 union iwreq_data wrqu;
4008
4009 ENTER();
4010
4011 switch(pAdapter->device_mode)
4012 {
4013 case WLAN_HDD_INFRA_STATION:
4014 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004015 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004016 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4017 {
4018 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
4019 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4020 pAdapter->sessionId,
4021 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
4022 else
4023 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4024 pAdapter->sessionId,
4025 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4026 //success implies disconnect command got queued up successfully
4027 if(halStatus == eHAL_STATUS_SUCCESS)
4028 {
4029 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
4030 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4031 }
4032 memset(&wrqu, '\0', sizeof(wrqu));
4033 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4034 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4035 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
4036 }
4037 else
4038 {
4039 hdd_abort_mac_scan(pHddCtx);
4040 }
4041
4042 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
4043 {
4044 INIT_COMPLETION(pAdapter->session_close_comp_var);
4045 if (eHAL_STATUS_SUCCESS ==
4046 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
4047 hdd_smeCloseSessionCallback, pAdapter))
4048 {
4049 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004050 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004051 &pAdapter->session_close_comp_var,
4052 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4053 }
4054 }
4055
4056 break;
4057
4058 case WLAN_HDD_SOFTAP:
4059 case WLAN_HDD_P2P_GO:
4060 //Any softap specific cleanup here...
4061 mutex_lock(&pHddCtx->sap_lock);
4062 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4063 {
4064 VOS_STATUS status;
4065 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4066
4067 //Stop Bss.
4068 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4069 if (VOS_IS_STATUS_SUCCESS(status))
4070 {
4071 hdd_hostapd_state_t *pHostapdState =
4072 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4073
4074 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4075
4076 if (!VOS_IS_STATUS_SUCCESS(status))
4077 {
4078 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004079 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004080 }
4081 }
4082 else
4083 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004084 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004085 }
4086 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4087
4088 if (eHAL_STATUS_FAILURE ==
4089 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4090 0, NULL, eANI_BOOLEAN_FALSE))
4091 {
4092 hddLog(LOGE,
4093 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004094 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004095 }
4096
4097 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4098 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4099 eANI_BOOLEAN_FALSE) )
4100 {
4101 hddLog(LOGE,
4102 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4103 }
4104
4105 // Reset WNI_CFG_PROBE_RSP Flags
4106 wlan_hdd_reset_prob_rspies(pAdapter);
4107 kfree(pAdapter->sessionCtx.ap.beacon);
4108 pAdapter->sessionCtx.ap.beacon = NULL;
4109 }
4110 mutex_unlock(&pHddCtx->sap_lock);
4111 break;
4112 case WLAN_HDD_MONITOR:
4113 break;
4114 default:
4115 break;
4116 }
4117
4118 EXIT();
4119 return VOS_STATUS_SUCCESS;
4120}
4121
4122VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4123{
4124 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4125 VOS_STATUS status;
4126 hdd_adapter_t *pAdapter;
4127
4128 ENTER();
4129
4130 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4131
4132 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4133 {
4134 pAdapter = pAdapterNode->pAdapter;
4135 netif_tx_disable(pAdapter->dev);
4136 netif_carrier_off(pAdapter->dev);
4137
4138 hdd_stop_adapter( pHddCtx, pAdapter );
4139
4140 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4141 pAdapterNode = pNext;
4142 }
4143
4144 EXIT();
4145
4146 return VOS_STATUS_SUCCESS;
4147}
4148
4149VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4150{
4151 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4152 VOS_STATUS status;
4153 hdd_adapter_t *pAdapter;
4154
4155 ENTER();
4156
4157 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4158
4159 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4160 {
4161 pAdapter = pAdapterNode->pAdapter;
4162 netif_tx_disable(pAdapter->dev);
4163 netif_carrier_off(pAdapter->dev);
4164
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004165 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
4166
Jeff Johnson295189b2012-06-20 16:38:30 -07004167 hdd_deinit_tx_rx(pAdapter);
4168 hdd_wmm_adapter_close(pAdapter);
4169
4170 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4171 pAdapterNode = pNext;
4172 }
4173
4174 EXIT();
4175
4176 return VOS_STATUS_SUCCESS;
4177}
4178
4179VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4180{
4181 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4182 VOS_STATUS status;
4183 hdd_adapter_t *pAdapter;
4184 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304185 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004186
4187 ENTER();
4188
4189 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4190
4191 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4192 {
4193 pAdapter = pAdapterNode->pAdapter;
4194
4195 switch(pAdapter->device_mode)
4196 {
4197 case WLAN_HDD_INFRA_STATION:
4198 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004199 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304200
4201 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4202
Jeff Johnson295189b2012-06-20 16:38:30 -07004203 hdd_init_station_mode(pAdapter);
4204 /* Open the gates for HDD to receive Wext commands */
4205 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004206 pHddCtx->scan_info.mScanPending = FALSE;
4207 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004208
4209 //Trigger the initial scan
4210 hdd_wlan_initial_scan(pAdapter);
4211
4212 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304213 if (eConnectionState_Associated == connState ||
4214 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004215 {
4216 union iwreq_data wrqu;
4217 memset(&wrqu, '\0', sizeof(wrqu));
4218 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4219 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4220 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07004221 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004222
Jeff Johnson295189b2012-06-20 16:38:30 -07004223 /* indicate disconnected event to nl80211 */
4224 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4225 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004226 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304227 else if (eConnectionState_Connecting == connState)
4228 {
4229 /*
4230 * Indicate connect failure to supplicant if we were in the
4231 * process of connecting
4232 */
4233 cfg80211_connect_result(pAdapter->dev, NULL,
4234 NULL, 0, NULL, 0,
4235 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4236 GFP_KERNEL);
4237 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004238 break;
4239
4240 case WLAN_HDD_SOFTAP:
4241 /* softAP can handle SSR */
4242 break;
4243
4244 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004245 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4246 __func__);
4247 /* event supplicant to restart */
4248 cfg80211_del_sta(pAdapter->dev,
4249 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004250 break;
4251
4252 case WLAN_HDD_MONITOR:
4253 /* monitor interface start */
4254 break;
4255 default:
4256 break;
4257 }
4258
4259 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4260 pAdapterNode = pNext;
4261 }
4262
4263 EXIT();
4264
4265 return VOS_STATUS_SUCCESS;
4266}
4267
4268VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4269{
4270 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4271 hdd_adapter_t *pAdapter;
4272 VOS_STATUS status;
4273 v_U32_t roamId;
4274
4275 ENTER();
4276
4277 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4278
4279 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4280 {
4281 pAdapter = pAdapterNode->pAdapter;
4282
4283 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4284 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4285 {
4286 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4287 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4288
4289 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4290 init_completion(&pAdapter->disconnect_comp_var);
4291 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4292 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4293
4294 wait_for_completion_interruptible_timeout(
4295 &pAdapter->disconnect_comp_var,
4296 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4297
4298 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4299 pHddCtx->isAmpAllowed = VOS_FALSE;
4300 sme_RoamConnect(pHddCtx->hHal,
4301 pAdapter->sessionId, &(pWextState->roamProfile),
4302 &roamId);
4303 }
4304
4305 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4306 pAdapterNode = pNext;
4307 }
4308
4309 EXIT();
4310
4311 return VOS_STATUS_SUCCESS;
4312}
4313
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004314void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4315{
4316 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4317 VOS_STATUS status;
4318 hdd_adapter_t *pAdapter;
4319 hdd_station_ctx_t *pHddStaCtx;
4320 hdd_ap_ctx_t *pHddApCtx;
4321 hdd_hostapd_state_t * pHostapdState;
4322 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4323 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4324 const char *p2pMode = "DEV";
4325 const char *ccMode = "Standalone";
4326 int n;
4327
4328 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4329 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4330 {
4331 pAdapter = pAdapterNode->pAdapter;
4332 switch (pAdapter->device_mode) {
4333 case WLAN_HDD_INFRA_STATION:
4334 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4335 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4336 staChannel = pHddStaCtx->conn_info.operationChannel;
4337 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4338 }
4339 break;
4340 case WLAN_HDD_P2P_CLIENT:
4341 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4342 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4343 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4344 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4345 p2pMode = "CLI";
4346 }
4347 break;
4348 case WLAN_HDD_P2P_GO:
4349 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4350 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4351 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4352 p2pChannel = pHddApCtx->operatingChannel;
4353 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4354 }
4355 p2pMode = "GO";
4356 break;
4357 case WLAN_HDD_SOFTAP:
4358 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4359 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4360 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4361 apChannel = pHddApCtx->operatingChannel;
4362 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4363 }
4364 break;
4365 default:
4366 break;
4367 }
4368 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4369 pAdapterNode = pNext;
4370 }
4371 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4372 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4373 }
4374 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4375 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4376 if (p2pChannel > 0) {
4377 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4378 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4379 }
4380 if (apChannel > 0) {
4381 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4382 apChannel, MAC_ADDR_ARRAY(apBssid));
4383 }
4384
4385 if (p2pChannel > 0 && apChannel > 0) {
4386 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4387 }
4388}
4389
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004390bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004391{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004392 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004393}
4394
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004395/* Once SSR is disabled then it cannot be set. */
4396void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004397{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004398 if (HDD_SSR_DISABLED == isSsrRequired)
4399 return;
4400
Jeff Johnson295189b2012-06-20 16:38:30 -07004401 isSsrRequired = value;
4402}
4403
4404VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4405 hdd_adapter_list_node_t** ppAdapterNode)
4406{
4407 VOS_STATUS status;
4408 spin_lock(&pHddCtx->hddAdapters.lock);
4409 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4410 (hdd_list_node_t**) ppAdapterNode );
4411 spin_unlock(&pHddCtx->hddAdapters.lock);
4412 return status;
4413}
4414
4415VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4416 hdd_adapter_list_node_t* pAdapterNode,
4417 hdd_adapter_list_node_t** pNextAdapterNode)
4418{
4419 VOS_STATUS status;
4420 spin_lock(&pHddCtx->hddAdapters.lock);
4421 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4422 (hdd_list_node_t*) pAdapterNode,
4423 (hdd_list_node_t**)pNextAdapterNode );
4424
4425 spin_unlock(&pHddCtx->hddAdapters.lock);
4426 return status;
4427}
4428
4429VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4430 hdd_adapter_list_node_t* pAdapterNode)
4431{
4432 VOS_STATUS status;
4433 spin_lock(&pHddCtx->hddAdapters.lock);
4434 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4435 &pAdapterNode->node );
4436 spin_unlock(&pHddCtx->hddAdapters.lock);
4437 return status;
4438}
4439
4440VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4441 hdd_adapter_list_node_t** ppAdapterNode)
4442{
4443 VOS_STATUS status;
4444 spin_lock(&pHddCtx->hddAdapters.lock);
4445 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4446 (hdd_list_node_t**) ppAdapterNode );
4447 spin_unlock(&pHddCtx->hddAdapters.lock);
4448 return status;
4449}
4450
4451VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4452 hdd_adapter_list_node_t* pAdapterNode)
4453{
4454 VOS_STATUS status;
4455 spin_lock(&pHddCtx->hddAdapters.lock);
4456 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4457 (hdd_list_node_t*) pAdapterNode );
4458 spin_unlock(&pHddCtx->hddAdapters.lock);
4459 return status;
4460}
4461
4462VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4463 hdd_adapter_list_node_t* pAdapterNode)
4464{
4465 VOS_STATUS status;
4466 spin_lock(&pHddCtx->hddAdapters.lock);
4467 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4468 (hdd_list_node_t*) pAdapterNode );
4469 spin_unlock(&pHddCtx->hddAdapters.lock);
4470 return status;
4471}
4472
4473hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4474 tSirMacAddr macAddr )
4475{
4476 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4477 hdd_adapter_t *pAdapter;
4478 VOS_STATUS status;
4479
4480 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4481
4482 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4483 {
4484 pAdapter = pAdapterNode->pAdapter;
4485
4486 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4487 macAddr, sizeof(tSirMacAddr) ) )
4488 {
4489 return pAdapter;
4490 }
4491 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4492 pAdapterNode = pNext;
4493 }
4494
4495 return NULL;
4496
4497}
4498
4499hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4500{
4501 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4502 hdd_adapter_t *pAdapter;
4503 VOS_STATUS status;
4504
4505 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4506
4507 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4508 {
4509 pAdapter = pAdapterNode->pAdapter;
4510
4511 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4512 IFNAMSIZ ) )
4513 {
4514 return pAdapter;
4515 }
4516 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4517 pAdapterNode = pNext;
4518 }
4519
4520 return NULL;
4521
4522}
4523
4524hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4525{
4526 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4527 hdd_adapter_t *pAdapter;
4528 VOS_STATUS status;
4529
4530 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4531
4532 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4533 {
4534 pAdapter = pAdapterNode->pAdapter;
4535
4536 if( pAdapter && (mode == pAdapter->device_mode) )
4537 {
4538 return pAdapter;
4539 }
4540 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4541 pAdapterNode = pNext;
4542 }
4543
4544 return NULL;
4545
4546}
4547
4548//Remove this function later
4549hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4550{
4551 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4552 hdd_adapter_t *pAdapter;
4553 VOS_STATUS status;
4554
4555 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4556
4557 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4558 {
4559 pAdapter = pAdapterNode->pAdapter;
4560
4561 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4562 {
4563 return pAdapter;
4564 }
4565
4566 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4567 pAdapterNode = pNext;
4568 }
4569
4570 return NULL;
4571
4572}
4573
Jeff Johnson295189b2012-06-20 16:38:30 -07004574/**---------------------------------------------------------------------------
4575
4576 \brief hdd_set_monitor_tx_adapter() -
4577
4578 This API initializes the adapter to be used while transmitting on monitor
4579 adapter.
4580
4581 \param - pHddCtx - Pointer to the HDD context.
4582 pAdapter - Adapter that will used for TX. This can be NULL.
4583 \return - None.
4584 --------------------------------------------------------------------------*/
4585void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4586{
4587 hdd_adapter_t *pMonAdapter;
4588
4589 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4590
4591 if( NULL != pMonAdapter )
4592 {
4593 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4594 }
4595}
Jeff Johnson295189b2012-06-20 16:38:30 -07004596/**---------------------------------------------------------------------------
4597
4598 \brief hdd_select_queue() -
4599
4600 This API returns the operating channel of the requested device mode
4601
4602 \param - pHddCtx - Pointer to the HDD context.
4603 - mode - Device mode for which operating channel is required
4604 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4605 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4606 \return - channel number. "0" id the requested device is not found OR it is not connected.
4607 --------------------------------------------------------------------------*/
4608v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4609{
4610 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4611 VOS_STATUS status;
4612 hdd_adapter_t *pAdapter;
4613 v_U8_t operatingChannel = 0;
4614
4615 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4616
4617 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4618 {
4619 pAdapter = pAdapterNode->pAdapter;
4620
4621 if( mode == pAdapter->device_mode )
4622 {
4623 switch(pAdapter->device_mode)
4624 {
4625 case WLAN_HDD_INFRA_STATION:
4626 case WLAN_HDD_P2P_CLIENT:
4627 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4628 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4629 break;
4630 case WLAN_HDD_SOFTAP:
4631 case WLAN_HDD_P2P_GO:
4632 /*softap connection info */
4633 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4634 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4635 break;
4636 default:
4637 break;
4638 }
4639
4640 break; //Found the device of interest. break the loop
4641 }
4642
4643 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4644 pAdapterNode = pNext;
4645 }
4646 return operatingChannel;
4647}
4648
4649#ifdef WLAN_FEATURE_PACKET_FILTERING
4650/**---------------------------------------------------------------------------
4651
4652 \brief hdd_set_multicast_list() -
4653
4654 This used to set the multicast address list.
4655
4656 \param - dev - Pointer to the WLAN device.
4657 - skb - Pointer to OS packet (sk_buff).
4658 \return - success/fail
4659
4660 --------------------------------------------------------------------------*/
4661static void hdd_set_multicast_list(struct net_device *dev)
4662{
4663 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004664 int mc_count;
4665 int i = 0;
4666 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304667
4668 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004669 {
4670 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304671 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004672 return;
4673 }
4674
4675 if (dev->flags & IFF_ALLMULTI)
4676 {
4677 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004678 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304679 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004680 }
4681 else
4682 {
4683 mc_count = netdev_mc_count(dev);
4684 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004685 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004686 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4687 {
4688 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004689 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304690 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004691 return;
4692 }
4693
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304694 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004695
4696 netdev_for_each_mc_addr(ha, dev) {
4697 if (i == mc_count)
4698 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304699 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4700 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4701 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004702 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304703 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004704 i++;
4705 }
4706 }
4707 return;
4708}
4709#endif
4710
4711/**---------------------------------------------------------------------------
4712
4713 \brief hdd_select_queue() -
4714
4715 This function is registered with the Linux OS for network
4716 core to decide which queue to use first.
4717
4718 \param - dev - Pointer to the WLAN device.
4719 - skb - Pointer to OS packet (sk_buff).
4720 \return - ac, Queue Index/access category corresponding to UP in IP header
4721
4722 --------------------------------------------------------------------------*/
4723v_U16_t hdd_select_queue(struct net_device *dev,
4724 struct sk_buff *skb)
4725{
4726 return hdd_wmm_select_queue(dev, skb);
4727}
4728
4729
4730/**---------------------------------------------------------------------------
4731
4732 \brief hdd_wlan_initial_scan() -
4733
4734 This function triggers the initial scan
4735
4736 \param - pAdapter - Pointer to the HDD adapter.
4737
4738 --------------------------------------------------------------------------*/
4739void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4740{
4741 tCsrScanRequest scanReq;
4742 tCsrChannelInfo channelInfo;
4743 eHalStatus halStatus;
4744 unsigned long scanId;
4745 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4746
4747 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4748 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4749 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4750
4751 if(sme_Is11dSupported(pHddCtx->hHal))
4752 {
4753 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4754 if ( HAL_STATUS_SUCCESS( halStatus ) )
4755 {
4756 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4757 if( !scanReq.ChannelInfo.ChannelList )
4758 {
4759 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4760 vos_mem_free(channelInfo.ChannelList);
4761 return;
4762 }
4763 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4764 channelInfo.numOfChannels);
4765 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4766 vos_mem_free(channelInfo.ChannelList);
4767 }
4768
4769 scanReq.scanType = eSIR_PASSIVE_SCAN;
4770 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4771 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4772 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4773 }
4774 else
4775 {
4776 scanReq.scanType = eSIR_ACTIVE_SCAN;
4777 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4778 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4779 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4780 }
4781
4782 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4783 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4784 {
4785 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4786 __func__, halStatus );
4787 }
4788
4789 if(sme_Is11dSupported(pHddCtx->hHal))
4790 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4791}
4792
4793struct fullPowerContext
4794{
4795 struct completion completion;
4796 unsigned int magic;
4797};
4798#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4799
4800/**---------------------------------------------------------------------------
4801
4802 \brief hdd_full_power_callback() - HDD full power callback function
4803
4804 This is the function invoked by SME to inform the result of a full power
4805 request issued by HDD
4806
4807 \param - callbackcontext - Pointer to cookie
4808 \param - status - result of request
4809
4810 \return - None
4811
4812 --------------------------------------------------------------------------*/
4813static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4814{
4815 struct fullPowerContext *pContext = callbackContext;
4816
4817 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304818 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004819
4820 if (NULL == callbackContext)
4821 {
4822 hddLog(VOS_TRACE_LEVEL_ERROR,
4823 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004824 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004825 return;
4826 }
4827
4828 /* there is a race condition that exists between this callback function
4829 and the caller since the caller could time out either before or
4830 while this code is executing. we'll assume the timeout hasn't
4831 occurred, but we'll verify that right before we save our work */
4832
4833 if (POWER_CONTEXT_MAGIC != pContext->magic)
4834 {
4835 /* the caller presumably timed out so there is nothing we can do */
4836 hddLog(VOS_TRACE_LEVEL_WARN,
4837 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004838 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004839 return;
4840 }
4841
4842 /* the race is on. caller could have timed out immediately after
4843 we verified the magic, but if so, caller will wait a short time
4844 for us to notify the caller, so the context will stay valid */
4845 complete(&pContext->completion);
4846}
4847
4848/**---------------------------------------------------------------------------
4849
4850 \brief hdd_wlan_exit() - HDD WLAN exit function
4851
4852 This is the driver exit point (invoked during rmmod)
4853
4854 \param - pHddCtx - Pointer to the HDD Context
4855
4856 \return - None
4857
4858 --------------------------------------------------------------------------*/
4859void hdd_wlan_exit(hdd_context_t *pHddCtx)
4860{
4861 eHalStatus halStatus;
4862 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4863 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304864 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004865 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004866 struct fullPowerContext powerContext;
4867 long lrc;
4868
4869 ENTER();
4870
Jeff Johnson88ba7742013-02-27 14:36:02 -08004871 if (VOS_FTM_MODE != hdd_get_conparam())
4872 {
4873 // Unloading, restart logic is no more required.
4874 wlan_hdd_restart_deinit(pHddCtx);
4875 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004876
Jeff Johnson295189b2012-06-20 16:38:30 -07004877 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004878 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004879 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004880 {
4881 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4882 WLAN_HDD_INFRA_STATION);
4883 if (pAdapter == NULL)
4884 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4885
4886 if (pAdapter != NULL)
4887 {
4888 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4889 hdd_UnregisterWext(pAdapter->dev);
4890 }
4891 }
4892 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004893
Jeff Johnson295189b2012-06-20 16:38:30 -07004894 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004895 {
4896 wlan_hdd_ftm_close(pHddCtx);
4897 goto free_hdd_ctx;
4898 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004899 //Stop the Interface TX queue.
4900 //netif_tx_disable(pWlanDev);
4901 //netif_carrier_off(pWlanDev);
4902
Jeff Johnson295189b2012-06-20 16:38:30 -07004903 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4904 {
4905 pAdapter = hdd_get_adapter(pHddCtx,
4906 WLAN_HDD_SOFTAP);
4907 }
4908 else
4909 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004910 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004911 {
4912 pAdapter = hdd_get_adapter(pHddCtx,
4913 WLAN_HDD_INFRA_STATION);
4914 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004915 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004916 /* DeRegister with platform driver as client for Suspend/Resume */
4917 vosStatus = hddDeregisterPmOps(pHddCtx);
4918 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4919 {
4920 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4921 VOS_ASSERT(0);
4922 }
4923
4924 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4925 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4926 {
4927 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4928 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004929
4930 // Cancel any outstanding scan requests. We are about to close all
4931 // of our adapters, but an adapter structure is what SME passes back
4932 // to our callback function. Hence if there are any outstanding scan
4933 // requests then there is a race condition between when the adapter
4934 // is closed and when the callback is invoked. We try to resolve that
4935 // race condition here by canceling any outstanding scans before we
4936 // close the adapters.
4937 // Note that the scans may be cancelled in an asynchronous manner, so
4938 // ideally there needs to be some kind of synchronization. Rather than
4939 // introduce a new synchronization here, we will utilize the fact that
4940 // we are about to Request Full Power, and since that is synchronized,
4941 // the expectation is that by the time Request Full Power has completed,
4942 // all scans will be cancelled.
4943 hdd_abort_mac_scan( pHddCtx );
4944
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05304945 //Stop the timer if already running
4946 if (VOS_TIMER_STATE_RUNNING ==
4947 vos_timer_getCurrentState(&pHddCtx->hdd_p2p_go_conn_is_in_progress))
4948 {
4949 vos_timer_stop(&pHddCtx->hdd_p2p_go_conn_is_in_progress);
4950 }
4951
4952 // Destroy hdd_p2p_go_conn_is_in_progress timer
4953 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
4954 &pHddCtx->hdd_p2p_go_conn_is_in_progress)))
4955 {
4956 hddLog(VOS_TRACE_LEVEL_ERROR,
4957 "%s: Cannot deallocate p2p connection timer", __func__);
4958 }
4959
Jeff Johnson295189b2012-06-20 16:38:30 -07004960 //Disable IMPS/BMPS as we do not want the device to enter any power
4961 //save mode during shutdown
4962 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4963 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4964 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4965
4966 //Ensure that device is in full power as we will touch H/W during vos_Stop
4967 init_completion(&powerContext.completion);
4968 powerContext.magic = POWER_CONTEXT_MAGIC;
4969
4970 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4971 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4972
4973 if (eHAL_STATUS_SUCCESS != halStatus)
4974 {
4975 if (eHAL_STATUS_PMC_PENDING == halStatus)
4976 {
4977 /* request was sent -- wait for the response */
4978 lrc = wait_for_completion_interruptible_timeout(
4979 &powerContext.completion,
4980 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4981 /* either we have a response or we timed out
4982 either way, first invalidate our magic */
4983 powerContext.magic = 0;
4984 if (lrc <= 0)
4985 {
4986 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004987 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004988 /* there is a race condition such that the callback
4989 function could be executing at the same time we are. of
4990 primary concern is if the callback function had already
4991 verified the "magic" but hasn't yet set the completion
4992 variable. Since the completion variable is on our
4993 stack, we'll delay just a bit to make sure the data is
4994 still valid if that is the case */
4995 msleep(50);
4996 }
4997 }
4998 else
4999 {
5000 hddLog(VOS_TRACE_LEVEL_ERROR,
5001 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005002 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07005003 VOS_ASSERT(0);
5004 /* continue -- need to clean up as much as possible */
5005 }
5006 }
5007
5008 // Unregister the Net Device Notifier
5009 unregister_netdevice_notifier(&hdd_netdev_notifier);
5010
Jeff Johnson295189b2012-06-20 16:38:30 -07005011 hdd_stop_all_adapters( pHddCtx );
5012
Jeff Johnson295189b2012-06-20 16:38:30 -07005013#ifdef WLAN_BTAMP_FEATURE
5014 vosStatus = WLANBAP_Stop(pVosContext);
5015 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5016 {
5017 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5018 "%s: Failed to stop BAP",__func__);
5019 }
5020#endif //WLAN_BTAMP_FEATURE
5021
5022 //Stop all the modules
5023 vosStatus = vos_stop( pVosContext );
5024 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5025 {
5026 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5027 "%s: Failed to stop VOSS",__func__);
5028 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5029 }
5030
Jeff Johnson295189b2012-06-20 16:38:30 -07005031 //Assert Deep sleep signal now to put Libra HW in lowest power state
5032 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5033 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5034
5035 //Vote off any PMIC voltage supplies
5036 vos_chipPowerDown(NULL, NULL, NULL);
5037
5038 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
5039
Leo Chang59cdc7e2013-07-10 10:08:21 -07005040
Jeff Johnson295189b2012-06-20 16:38:30 -07005041 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07005042 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005043
5044 //Close the scheduler before calling vos_close to make sure no thread is
5045 // scheduled after the each module close is called i.e after all the data
5046 // structures are freed.
5047 vosStatus = vos_sched_close( pVosContext );
5048 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
5049 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5050 "%s: Failed to close VOSS Scheduler",__func__);
5051 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5052 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005053#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005054#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5055 /* Destroy the wake lock */
5056 wake_lock_destroy(&pHddCtx->rx_wake_lock);
5057#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005058 /* Destroy the wake lock */
5059 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005060#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005061
5062 //Close VOSS
5063 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
5064 vos_close(pVosContext);
5065
Jeff Johnson295189b2012-06-20 16:38:30 -07005066 //Close Watchdog
5067 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5068 vos_watchdog_close(pVosContext);
5069
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305070 //Clean up HDD Nlink Service
5071 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07005072#ifdef WLAN_KD_READY_NOTIFIER
5073 nl_srv_exit(pHddCtx->ptt_pid);
5074#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305075 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005076#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305077
Jeff Johnson295189b2012-06-20 16:38:30 -07005078 /* Cancel the vote for XO Core ON.
5079 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5080 * exited at this point
5081 */
5082 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5083 " when WLAN is turned OFF\n");
5084 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5085 {
5086 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5087 " Not returning failure."
5088 " Power consumed will be high\n");
5089 }
5090
5091 hdd_close_all_adapters( pHddCtx );
5092
5093
5094 //Free up dynamically allocated members inside HDD Adapter
5095 kfree(pHddCtx->cfg_ini);
5096 pHddCtx->cfg_ini= NULL;
5097
5098 /* free the power on lock from platform driver */
5099 if (free_riva_power_on_lock("wlan"))
5100 {
5101 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5102 __func__);
5103 }
5104
Jeff Johnson88ba7742013-02-27 14:36:02 -08005105free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08005106 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005107 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005108 if (hdd_is_ssr_required())
5109 {
5110 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005111 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005112 msleep(5000);
5113 }
5114 hdd_set_ssr_required (VOS_FALSE);
5115}
5116
5117
5118/**---------------------------------------------------------------------------
5119
5120 \brief hdd_update_config_from_nv() - Function to update the contents of
5121 the running configuration with parameters taken from NV storage
5122
5123 \param - pHddCtx - Pointer to the HDD global context
5124
5125 \return - VOS_STATUS_SUCCESS if successful
5126
5127 --------------------------------------------------------------------------*/
5128static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5129{
Jeff Johnson295189b2012-06-20 16:38:30 -07005130 v_BOOL_t itemIsValid = VOS_FALSE;
5131 VOS_STATUS status;
5132 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5133 v_U8_t macLoop;
5134
5135 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5136 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5137 if(status != VOS_STATUS_SUCCESS)
5138 {
5139 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5140 return VOS_STATUS_E_FAILURE;
5141 }
5142
5143 if (itemIsValid == VOS_TRUE)
5144 {
5145 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5146 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5147 VOS_MAX_CONCURRENCY_PERSONA);
5148 if(status != VOS_STATUS_SUCCESS)
5149 {
5150 /* Get MAC from NV fail, not update CFG info
5151 * INI MAC value will be used for MAC setting */
5152 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5153 return VOS_STATUS_E_FAILURE;
5154 }
5155
5156 /* If first MAC is not valid, treat all others are not valid
5157 * Then all MACs will be got from ini file */
5158 if(vos_is_macaddr_zero(&macFromNV[0]))
5159 {
5160 /* MAC address in NV file is not configured yet */
5161 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5162 return VOS_STATUS_E_INVAL;
5163 }
5164
5165 /* Get MAC address from NV, update CFG info */
5166 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5167 {
5168 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5169 {
5170 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5171 /* This MAC is not valid, skip it
5172 * This MAC will be got from ini file */
5173 }
5174 else
5175 {
5176 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5177 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5178 VOS_MAC_ADDR_SIZE);
5179 }
5180 }
5181 }
5182 else
5183 {
5184 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5185 return VOS_STATUS_E_FAILURE;
5186 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005187
Jeff Johnson295189b2012-06-20 16:38:30 -07005188
5189 return VOS_STATUS_SUCCESS;
5190}
5191
5192/**---------------------------------------------------------------------------
5193
5194 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5195
5196 \param - pAdapter - Pointer to the HDD
5197
5198 \return - None
5199
5200 --------------------------------------------------------------------------*/
5201VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5202{
5203 eHalStatus halStatus;
5204 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305205 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005206
Jeff Johnson295189b2012-06-20 16:38:30 -07005207
5208 // Send ready indication to the HDD. This will kick off the MAC
5209 // into a 'running' state and should kick off an initial scan.
5210 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5211 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5212 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305213 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005214 "code %08d [x%08x]",__func__, halStatus, halStatus );
5215 return VOS_STATUS_E_FAILURE;
5216 }
5217
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305218 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005219 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5220 // And RIVA will crash
5221 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5222 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305223 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5224 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5225
5226
Jeff Johnson295189b2012-06-20 16:38:30 -07005227 return VOS_STATUS_SUCCESS;
5228}
5229
Jeff Johnson295189b2012-06-20 16:38:30 -07005230/* wake lock APIs for HDD */
5231void hdd_prevent_suspend(void)
5232{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005233#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005234 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005235#else
5236 wcnss_prevent_suspend();
5237#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005238}
5239
5240void hdd_allow_suspend(void)
5241{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005242#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005243 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005244#else
5245 wcnss_allow_suspend();
5246#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005247}
5248
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005249void hdd_allow_suspend_timeout(v_U32_t timeout)
5250{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005251#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005252 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005253#else
5254 /* Do nothing as there is no API in wcnss for timeout*/
5255#endif
5256}
5257
Jeff Johnson295189b2012-06-20 16:38:30 -07005258/**---------------------------------------------------------------------------
5259
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005260 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5261 information between Host and Riva
5262
5263 This function gets reported version of FW
5264 It also finds the version of Riva headers used to compile the host
5265 It compares the above two and prints a warning if they are different
5266 It gets the SW and HW version string
5267 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5268 indicating the features they support through a bitmap
5269
5270 \param - pHddCtx - Pointer to HDD context
5271
5272 \return - void
5273
5274 --------------------------------------------------------------------------*/
5275
5276void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5277{
5278
5279 tSirVersionType versionCompiled;
5280 tSirVersionType versionReported;
5281 tSirVersionString versionString;
5282 tANI_U8 fwFeatCapsMsgSupported = 0;
5283 VOS_STATUS vstatus;
5284
5285 /* retrieve and display WCNSS version information */
5286 do {
5287
5288 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5289 &versionCompiled);
5290 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5291 {
5292 hddLog(VOS_TRACE_LEVEL_FATAL,
5293 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005294 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005295 break;
5296 }
5297
5298 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5299 &versionReported);
5300 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5301 {
5302 hddLog(VOS_TRACE_LEVEL_FATAL,
5303 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005304 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005305 break;
5306 }
5307
5308 if ((versionCompiled.major != versionReported.major) ||
5309 (versionCompiled.minor != versionReported.minor) ||
5310 (versionCompiled.version != versionReported.version) ||
5311 (versionCompiled.revision != versionReported.revision))
5312 {
5313 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5314 "Host expected %u.%u.%u.%u\n",
5315 WLAN_MODULE_NAME,
5316 (int)versionReported.major,
5317 (int)versionReported.minor,
5318 (int)versionReported.version,
5319 (int)versionReported.revision,
5320 (int)versionCompiled.major,
5321 (int)versionCompiled.minor,
5322 (int)versionCompiled.version,
5323 (int)versionCompiled.revision);
5324 }
5325 else
5326 {
5327 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5328 WLAN_MODULE_NAME,
5329 (int)versionReported.major,
5330 (int)versionReported.minor,
5331 (int)versionReported.version,
5332 (int)versionReported.revision);
5333 }
5334
5335 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5336 versionString,
5337 sizeof(versionString));
5338 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5339 {
5340 hddLog(VOS_TRACE_LEVEL_FATAL,
5341 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005342 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005343 break;
5344 }
5345
5346 pr_info("%s: WCNSS software version %s\n",
5347 WLAN_MODULE_NAME, versionString);
5348
5349 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5350 versionString,
5351 sizeof(versionString));
5352 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5353 {
5354 hddLog(VOS_TRACE_LEVEL_FATAL,
5355 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005356 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005357 break;
5358 }
5359
5360 pr_info("%s: WCNSS hardware version %s\n",
5361 WLAN_MODULE_NAME, versionString);
5362
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005363 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5364 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005365 send the message only if it the riva is 1.1
5366 minor numbers for different riva branches:
5367 0 -> (1.0)Mainline Build
5368 1 -> (1.1)Mainline Build
5369 2->(1.04) Stability Build
5370 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005371 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005372 ((versionReported.minor>=1) && (versionReported.version>=1)))
5373 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5374 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005375
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005376 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005377 {
5378#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5379 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5380 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5381#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005382 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005383 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005384
5385 } while (0);
5386
5387}
5388
5389/**---------------------------------------------------------------------------
5390
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305391 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5392
5393 \param - pHddCtx - Pointer to the hdd context
5394
5395 \return - true if hardware supports 5GHz
5396
5397 --------------------------------------------------------------------------*/
5398static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5399{
5400 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5401 * then hardware support 5Ghz.
5402 */
5403 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5404 {
5405 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5406 return true;
5407 }
5408 else
5409 {
5410 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5411 __func__);
5412 return false;
5413 }
5414}
5415
5416
5417/**---------------------------------------------------------------------------
5418
Jeff Johnson295189b2012-06-20 16:38:30 -07005419 \brief hdd_wlan_startup() - HDD init function
5420
5421 This is the driver startup code executed once a WLAN device has been detected
5422
5423 \param - dev - Pointer to the underlying device
5424
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005425 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005426
5427 --------------------------------------------------------------------------*/
5428
5429int hdd_wlan_startup(struct device *dev )
5430{
5431 VOS_STATUS status;
5432 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005433 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005434 hdd_context_t *pHddCtx = NULL;
5435 v_CONTEXT_t pVosContext= NULL;
5436#ifdef WLAN_BTAMP_FEATURE
5437 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5438 WLANBAP_ConfigType btAmpConfig;
5439 hdd_config_t *pConfig;
5440#endif
5441 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005442 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005443
5444 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005445 /*
5446 * cfg80211: wiphy allocation
5447 */
5448 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5449
5450 if(wiphy == NULL)
5451 {
5452 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005453 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005454 }
5455
5456 pHddCtx = wiphy_priv(wiphy);
5457
Jeff Johnson295189b2012-06-20 16:38:30 -07005458 //Initialize the adapter context to zeros.
5459 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5460
Jeff Johnson295189b2012-06-20 16:38:30 -07005461 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005462 hdd_prevent_suspend();
5463 pHddCtx->isLoadUnloadInProgress = TRUE;
5464
5465 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5466
5467 /*Get vos context here bcoz vos_open requires it*/
5468 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5469
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005470 if(pVosContext == NULL)
5471 {
5472 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5473 goto err_free_hdd_context;
5474 }
5475
Jeff Johnson295189b2012-06-20 16:38:30 -07005476 //Save the Global VOSS context in adapter context for future.
5477 pHddCtx->pvosContext = pVosContext;
5478
5479 //Save the adapter context in global context for future.
5480 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5481
Jeff Johnson295189b2012-06-20 16:38:30 -07005482 pHddCtx->parent_dev = dev;
5483
5484 init_completion(&pHddCtx->full_pwr_comp_var);
5485 init_completion(&pHddCtx->standby_comp_var);
5486 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005487 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005488 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005489
5490 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5491
5492 // Load all config first as TL config is needed during vos_open
5493 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5494 if(pHddCtx->cfg_ini == NULL)
5495 {
5496 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5497 goto err_free_hdd_context;
5498 }
5499
5500 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5501
5502 // Read and parse the qcom_cfg.ini file
5503 status = hdd_parse_config_ini( pHddCtx );
5504 if ( VOS_STATUS_SUCCESS != status )
5505 {
5506 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5507 __func__, WLAN_INI_FILE);
5508 goto err_config;
5509 }
5510
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305511 /* INI has been read, initialise the configuredMcastBcastFilter with
5512 * INI value as this will serve as the default value
5513 */
5514 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5515 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5516 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305517
5518 if (false == hdd_is_5g_supported(pHddCtx))
5519 {
5520 //5Ghz is not supported.
5521 if (1 != pHddCtx->cfg_ini->nBandCapability)
5522 {
5523 hddLog(VOS_TRACE_LEVEL_INFO,
5524 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5525 pHddCtx->cfg_ini->nBandCapability = 1;
5526 }
5527 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005528 /*
5529 * cfg80211: Initialization and registration ...
5530 */
5531 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5532 {
5533 hddLog(VOS_TRACE_LEVEL_FATAL,
5534 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5535 goto err_wiphy_reg;
5536 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005537
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005538 // Update VOS trace levels based upon the cfg.ini
5539 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5540 pHddCtx->cfg_ini->vosTraceEnableBAP);
5541 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5542 pHddCtx->cfg_ini->vosTraceEnableTL);
5543 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5544 pHddCtx->cfg_ini->vosTraceEnableWDI);
5545 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5546 pHddCtx->cfg_ini->vosTraceEnableHDD);
5547 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5548 pHddCtx->cfg_ini->vosTraceEnableSME);
5549 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5550 pHddCtx->cfg_ini->vosTraceEnablePE);
5551 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5552 pHddCtx->cfg_ini->vosTraceEnableWDA);
5553 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5554 pHddCtx->cfg_ini->vosTraceEnableSYS);
5555 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5556 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005557 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5558 pHddCtx->cfg_ini->vosTraceEnableSAP);
5559 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5560 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005561
Jeff Johnson295189b2012-06-20 16:38:30 -07005562 // Update WDI trace levels based upon the cfg.ini
5563 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5564 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5565 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5566 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5567 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5568 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5569 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5570 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005571
Jeff Johnson88ba7742013-02-27 14:36:02 -08005572 if (VOS_FTM_MODE == hdd_get_conparam())
5573 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005574 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5575 {
5576 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5577 goto err_free_hdd_context;
5578 }
5579 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5580 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005581 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005582
Jeff Johnson88ba7742013-02-27 14:36:02 -08005583 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005584 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5585 {
5586 status = vos_watchdog_open(pVosContext,
5587 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5588
5589 if(!VOS_IS_STATUS_SUCCESS( status ))
5590 {
5591 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005592 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005593 }
5594 }
5595
5596 pHddCtx->isLogpInProgress = FALSE;
5597 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5598
Jeff Johnson295189b2012-06-20 16:38:30 -07005599 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5600 if(!VOS_IS_STATUS_SUCCESS(status))
5601 {
5602 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005603 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005604 }
5605
Jeff Johnson295189b2012-06-20 16:38:30 -07005606 status = vos_open( &pVosContext, 0);
5607 if ( !VOS_IS_STATUS_SUCCESS( status ))
5608 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005609 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5610 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005611 }
5612
Jeff Johnson295189b2012-06-20 16:38:30 -07005613 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5614
5615 if ( NULL == pHddCtx->hHal )
5616 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005617 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005618 goto err_vosclose;
5619 }
5620
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005621 status = vos_preStart( pHddCtx->pvosContext );
5622 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5623 {
5624 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5625 goto err_vosclose;
5626 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005627
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005628 /* Note that the vos_preStart() sequence triggers the cfg download.
5629 The cfg download must occur before we update the SME config
5630 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005631 status = hdd_set_sme_config( pHddCtx );
5632
5633 if ( VOS_STATUS_SUCCESS != status )
5634 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005635 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5636 goto err_vosclose;
5637 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005638
5639 //Initialize the WMM module
5640 status = hdd_wmm_init(pHddCtx);
5641 if (!VOS_IS_STATUS_SUCCESS(status))
5642 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005643 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005644 goto err_vosclose;
5645 }
5646
Jeff Johnson295189b2012-06-20 16:38:30 -07005647 /* In the integrated architecture we update the configuration from
5648 the INI file and from NV before vOSS has been started so that
5649 the final contents are available to send down to the cCPU */
5650
5651 // Apply the cfg.ini to cfg.dat
5652 if (FALSE == hdd_update_config_dat(pHddCtx))
5653 {
5654 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5655 goto err_vosclose;
5656 }
5657
5658 // Apply the NV to cfg.dat
5659 /* Prima Update MAC address only at here */
5660 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5661 {
5662#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5663 /* There was not a valid set of MAC Addresses in NV. See if the
5664 default addresses were modified by the cfg.ini settings. If so,
5665 we'll use them, but if not, we'll autogenerate a set of MAC
5666 addresses based upon the device serial number */
5667
5668 static const v_MACADDR_t default_address =
5669 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5670 unsigned int serialno;
5671 int i;
5672
5673 serialno = wcnss_get_serial_number();
5674 if ((0 != serialno) &&
5675 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5676 sizeof(default_address))))
5677 {
5678 /* cfg.ini has the default address, invoke autogen logic */
5679
5680 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5681 bytes of the serial number that can be used to generate
5682 the other 3 bytes of the MAC address. Mask off all but
5683 the lower 3 bytes (this will also make sure we don't
5684 overflow in the next step) */
5685 serialno &= 0x00FFFFFF;
5686
5687 /* we need a unique address for each session */
5688 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5689
5690 /* autogen all addresses */
5691 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5692 {
5693 /* start with the entire default address */
5694 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5695 /* then replace the lower 3 bytes */
5696 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5697 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5698 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5699
5700 serialno++;
5701 }
5702
5703 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5704 MAC_ADDRESS_STR,
5705 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5706 }
5707 else
5708#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5709 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005710 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005711 "%s: Invalid MAC address in NV, using MAC from ini file "
5712 MAC_ADDRESS_STR, __func__,
5713 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5714 }
5715 }
5716 {
5717 eHalStatus halStatus;
5718 // Set the MAC Address
5719 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5720 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5721 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5722 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5723
5724 if (!HAL_STATUS_SUCCESS( halStatus ))
5725 {
5726 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5727 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005728 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005729 }
5730 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005731
5732 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5733 Note: Firmware image will be read and downloaded inside vos_start API */
5734 status = vos_start( pHddCtx->pvosContext );
5735 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5736 {
5737 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5738 goto err_vosclose;
5739 }
5740
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005741 /* Exchange capability info between Host and FW and also get versioning info from FW */
5742 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005743
5744 status = hdd_post_voss_start_config( pHddCtx );
5745 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5746 {
5747 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5748 __func__);
5749 goto err_vosstop;
5750 }
5751
Jeff Johnson295189b2012-06-20 16:38:30 -07005752 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5753 {
5754 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5755 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5756 }
5757 else
5758 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005759 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5760 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5761 if (pAdapter != NULL)
5762 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305763 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005764 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305765 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5766 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5767 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005768
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305769 /* Generate the P2P Device Address. This consists of the device's
5770 * primary MAC address with the locally administered bit set.
5771 */
5772 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005773 }
5774 else
5775 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305776 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5777 if (p2p_dev_addr != NULL)
5778 {
5779 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5780 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5781 }
5782 else
5783 {
5784 hddLog(VOS_TRACE_LEVEL_FATAL,
5785 "%s: Failed to allocate mac_address for p2p_device",
5786 __func__);
5787 goto err_close_adapter;
5788 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005789 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005790
5791 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5792 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5793 if ( NULL == pP2pAdapter )
5794 {
5795 hddLog(VOS_TRACE_LEVEL_FATAL,
5796 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005797 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005798 goto err_close_adapter;
5799 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005800 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005801 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005802
5803 if( pAdapter == NULL )
5804 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005805 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5806 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005807 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005808
Jeff Johnson295189b2012-06-20 16:38:30 -07005809#ifdef WLAN_BTAMP_FEATURE
5810 vStatus = WLANBAP_Open(pVosContext);
5811 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5812 {
5813 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5814 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005815 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005816 }
5817
5818 vStatus = BSL_Init(pVosContext);
5819 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5820 {
5821 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5822 "%s: Failed to Init BSL",__func__);
5823 goto err_bap_close;
5824 }
5825 vStatus = WLANBAP_Start(pVosContext);
5826 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5827 {
5828 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5829 "%s: Failed to start TL",__func__);
5830 goto err_bap_close;
5831 }
5832
5833 pConfig = pHddCtx->cfg_ini;
5834 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5835 status = WLANBAP_SetConfig(&btAmpConfig);
5836
5837#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005838
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005839#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5840 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5841 {
5842 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5843 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5844 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5845 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5846 }
5847#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005848#ifdef FEATURE_WLAN_SCAN_PNO
5849 /*SME must send channel update configuration to RIVA*/
5850 sme_UpdateChannelConfig(pHddCtx->hHal);
5851#endif
5852
Jeff Johnson295189b2012-06-20 16:38:30 -07005853 /* Register with platform driver as client for Suspend/Resume */
5854 status = hddRegisterPmOps(pHddCtx);
5855 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5856 {
5857 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5858#ifdef WLAN_BTAMP_FEATURE
5859 goto err_bap_stop;
5860#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005861 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005862#endif //WLAN_BTAMP_FEATURE
5863 }
5864
5865 /* Register TM level change handler function to the platform */
5866 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5867 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5868 {
5869 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5870 goto err_unregister_pmops;
5871 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005872
5873 /* register for riva power on lock to platform driver */
5874 if (req_riva_power_on_lock("wlan"))
5875 {
5876 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5877 __func__);
5878 goto err_unregister_pmops;
5879 }
5880
Jeff Johnson295189b2012-06-20 16:38:30 -07005881 // register net device notifier for device change notification
5882 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5883
5884 if(ret < 0)
5885 {
5886 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5887 goto err_free_power_on_lock;
5888 }
5889
5890 //Initialize the nlink service
5891 if(nl_srv_init() != 0)
5892 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305893 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005894 goto err_reg_netdev;
5895 }
5896
5897 //Initialize the BTC service
5898 if(btc_activate_service(pHddCtx) != 0)
5899 {
5900 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5901 goto err_nl_srv;
5902 }
5903
5904#ifdef PTT_SOCK_SVC_ENABLE
5905 //Initialize the PTT service
5906 if(ptt_sock_activate_svc(pHddCtx) != 0)
5907 {
5908 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5909 goto err_nl_srv;
5910 }
5911#endif
5912
Jeff Johnson295189b2012-06-20 16:38:30 -07005913 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005914 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005915 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005916 /* Action frame registered in one adapter which will
5917 * applicable to all interfaces
5918 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005919 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005920 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005921
5922 mutex_init(&pHddCtx->sap_lock);
5923
5924 pHddCtx->isLoadUnloadInProgress = FALSE;
5925
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005926#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005927#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5928 /* Initialize the wake lcok */
5929 wake_lock_init(&pHddCtx->rx_wake_lock,
5930 WAKE_LOCK_SUSPEND,
5931 "qcom_rx_wakelock");
5932#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005933 /* Initialize the wake lcok */
5934 wake_lock_init(&pHddCtx->sap_wake_lock,
5935 WAKE_LOCK_SUSPEND,
5936 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005937#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005938
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005939 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5940 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005941
5942 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5943 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305944
Jeff Johnsone7245742012-09-05 17:12:55 -07005945 // Initialize the restart logic
5946 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305947
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305948 if (!VOS_IS_STATUS_SUCCESS( vos_timer_init( &pHddCtx->hdd_p2p_go_conn_is_in_progress,
5949 VOS_TIMER_TYPE_SW, wlan_hdd_p2p_go_connection_in_progresscb, pAdapter) ) )
5950 {
5951 hddLog(VOS_TRACE_LEVEL_ERROR,
5952 "%s: vos timer init failed for hdd_p2p_go_conn_is_in_progress", __func__);
5953 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005954 goto success;
5955
5956err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07005957#ifdef WLAN_KD_READY_NOTIFIER
5958 nl_srv_exit(pHddCtx->ptt_pid);
5959#else
Jeff Johnson295189b2012-06-20 16:38:30 -07005960 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07005961#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07005962err_reg_netdev:
5963 unregister_netdevice_notifier(&hdd_netdev_notifier);
5964
5965err_free_power_on_lock:
5966 free_riva_power_on_lock("wlan");
5967
5968err_unregister_pmops:
5969 hddDevTmUnregisterNotifyCallback(pHddCtx);
5970 hddDeregisterPmOps(pHddCtx);
5971
5972#ifdef WLAN_BTAMP_FEATURE
5973err_bap_stop:
5974 WLANBAP_Stop(pVosContext);
5975#endif
5976
5977#ifdef WLAN_BTAMP_FEATURE
5978err_bap_close:
5979 WLANBAP_Close(pVosContext);
5980#endif
5981
Jeff Johnson295189b2012-06-20 16:38:30 -07005982err_close_adapter:
5983 hdd_close_all_adapters( pHddCtx );
5984
5985err_vosstop:
5986 vos_stop(pVosContext);
5987
5988err_vosclose:
5989 status = vos_sched_close( pVosContext );
5990 if (!VOS_IS_STATUS_SUCCESS(status)) {
5991 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5992 "%s: Failed to close VOSS Scheduler", __func__);
5993 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5994 }
5995 vos_close(pVosContext );
5996
Jeff Johnson295189b2012-06-20 16:38:30 -07005997err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005998 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005999
6000err_wdclose:
6001 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6002 vos_watchdog_close(pVosContext);
6003
Jeff Johnson295189b2012-06-20 16:38:30 -07006004err_wiphy_reg:
6005 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006006
6007err_config:
6008 kfree(pHddCtx->cfg_ini);
6009 pHddCtx->cfg_ini= NULL;
6010
6011err_free_hdd_context:
6012 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07006013 wiphy_free(wiphy) ;
6014 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006015 VOS_BUG(1);
6016
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08006017 if (hdd_is_ssr_required())
6018 {
6019 /* WDI timeout had happened during load, so SSR is needed here */
6020 subsystem_restart("wcnss");
6021 msleep(5000);
6022 }
6023 hdd_set_ssr_required (VOS_FALSE);
6024
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006025 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006026
6027success:
6028 EXIT();
6029 return 0;
6030}
6031
6032/**---------------------------------------------------------------------------
6033
Jeff Johnson32d95a32012-09-10 13:15:23 -07006034 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07006035
Jeff Johnson32d95a32012-09-10 13:15:23 -07006036 This is the driver entry point - called in different timeline depending
6037 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07006038
6039 \param - None
6040
6041 \return - 0 for success, non zero for failure
6042
6043 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07006044static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006045{
6046 VOS_STATUS status;
6047 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006048 struct device *dev = NULL;
6049 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006050#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6051 int max_retries = 0;
6052#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006053
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306054#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6055 vos_wconn_trace_init();
6056#endif
6057
Jeff Johnson295189b2012-06-20 16:38:30 -07006058 ENTER();
6059
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006060#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006061 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07006062#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006063
6064 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
6065 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
6066
6067 //Power Up Libra WLAN card first if not already powered up
6068 status = vos_chipPowerUp(NULL,NULL,NULL);
6069 if (!VOS_IS_STATUS_SUCCESS(status))
6070 {
6071 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
6072 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306073#ifdef WLAN_OPEN_SOURCE
6074 wake_lock_destroy(&wlan_wake_lock);
6075#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006076 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006077 }
6078
Jeff Johnson295189b2012-06-20 16:38:30 -07006079#ifdef ANI_BUS_TYPE_PCI
6080
6081 dev = wcnss_wlan_get_device();
6082
6083#endif // ANI_BUS_TYPE_PCI
6084
6085#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006086
6087#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6088 /* wait until WCNSS driver downloads NV */
6089 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6090 msleep(1000);
6091 }
6092 if (max_retries >= 5) {
6093 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306094#ifdef WLAN_OPEN_SOURCE
6095 wake_lock_destroy(&wlan_wake_lock);
6096#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006097 return -ENODEV;
6098 }
6099#endif
6100
Jeff Johnson295189b2012-06-20 16:38:30 -07006101 dev = wcnss_wlan_get_device();
6102#endif // ANI_BUS_TYPE_PLATFORM
6103
6104
6105 do {
6106 if (NULL == dev) {
6107 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6108 ret_status = -1;
6109 break;
6110 }
6111
6112#ifdef MEMORY_DEBUG
6113 vos_mem_init();
6114#endif
6115
6116#ifdef TIMER_MANAGER
6117 vos_timer_manager_init();
6118#endif
6119
6120 /* Preopen VOSS so that it is ready to start at least SAL */
6121 status = vos_preOpen(&pVosContext);
6122
6123 if (!VOS_IS_STATUS_SUCCESS(status))
6124 {
6125 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6126 ret_status = -1;
6127 break;
6128 }
6129
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006130#ifndef MODULE
6131 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6132 */
6133 hdd_set_conparam((v_UINT_t)con_mode);
6134#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006135
6136 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006137 if (hdd_wlan_startup(dev))
6138 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006139 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006140 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006141 vos_preClose( &pVosContext );
6142 ret_status = -1;
6143 break;
6144 }
6145
6146 /* Cancel the vote for XO Core ON
6147 * This is done here for safety purposes in case we re-initialize without turning
6148 * it OFF in any error scenario.
6149 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006150 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006151 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006152 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006153 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6154 {
6155 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6156 " Power consumed will be high\n");
6157 }
6158 } while (0);
6159
6160 if (0 != ret_status)
6161 {
6162 //Assert Deep sleep signal now to put Libra HW in lowest power state
6163 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6164 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6165
6166 //Vote off any PMIC voltage supplies
6167 vos_chipPowerDown(NULL, NULL, NULL);
6168#ifdef TIMER_MANAGER
6169 vos_timer_exit();
6170#endif
6171#ifdef MEMORY_DEBUG
6172 vos_mem_exit();
6173#endif
6174
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006175#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006176 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006177#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006178 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6179 }
6180 else
6181 {
6182 //Send WLAN UP indication to Nlink Service
6183 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6184
6185 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07006186 }
6187
6188 EXIT();
6189
6190 return ret_status;
6191}
6192
Jeff Johnson32d95a32012-09-10 13:15:23 -07006193/**---------------------------------------------------------------------------
6194
6195 \brief hdd_module_init() - Init Function
6196
6197 This is the driver entry point (invoked when module is loaded using insmod)
6198
6199 \param - None
6200
6201 \return - 0 for success, non zero for failure
6202
6203 --------------------------------------------------------------------------*/
6204#ifdef MODULE
6205static int __init hdd_module_init ( void)
6206{
6207 return hdd_driver_init();
6208}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006209#else /* #ifdef MODULE */
6210static int __init hdd_module_init ( void)
6211{
6212 /* Driver initialization is delayed to fwpath_changed_handler */
6213 return 0;
6214}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006215#endif /* #ifdef MODULE */
6216
Jeff Johnson295189b2012-06-20 16:38:30 -07006217
6218/**---------------------------------------------------------------------------
6219
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006220 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006221
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006222 This is the driver exit point (invoked when module is unloaded using rmmod
6223 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006224
6225 \param - None
6226
6227 \return - None
6228
6229 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006230static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006231{
6232 hdd_context_t *pHddCtx = NULL;
6233 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006234 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006235
6236 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6237
6238 //Get the global vos context
6239 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6240
6241 if(!pVosContext)
6242 {
6243 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6244 goto done;
6245 }
6246
6247 //Get the HDD context.
6248 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6249
6250 if(!pHddCtx)
6251 {
6252 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6253 }
6254 else
6255 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006256 while(isWDresetInProgress()) {
6257 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6258 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006259 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006260
6261 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6262 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6263 "%s:SSR never completed, fatal error", __func__);
6264 VOS_BUG(0);
6265 }
6266 }
6267
Jeff Johnson295189b2012-06-20 16:38:30 -07006268
6269 pHddCtx->isLoadUnloadInProgress = TRUE;
6270 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6271
6272 //Do all the cleanup before deregistering the driver
6273 hdd_wlan_exit(pHddCtx);
6274 }
6275
Jeff Johnson295189b2012-06-20 16:38:30 -07006276 vos_preClose( &pVosContext );
6277
6278#ifdef TIMER_MANAGER
6279 vos_timer_exit();
6280#endif
6281#ifdef MEMORY_DEBUG
6282 vos_mem_exit();
6283#endif
6284
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306285#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6286 vos_wconn_trace_exit();
6287#endif
6288
Jeff Johnson295189b2012-06-20 16:38:30 -07006289done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006290#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006291 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006292#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006293 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6294}
6295
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006296/**---------------------------------------------------------------------------
6297
6298 \brief hdd_module_exit() - Exit function
6299
6300 This is the driver exit point (invoked when module is unloaded using rmmod)
6301
6302 \param - None
6303
6304 \return - None
6305
6306 --------------------------------------------------------------------------*/
6307static void __exit hdd_module_exit(void)
6308{
6309 hdd_driver_exit();
6310}
6311
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006312#ifdef MODULE
6313static int fwpath_changed_handler(const char *kmessage,
6314 struct kernel_param *kp)
6315{
Jeff Johnson76052702013-04-16 13:55:05 -07006316 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006317}
6318
6319static int con_mode_handler(const char *kmessage,
6320 struct kernel_param *kp)
6321{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006322 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006323}
6324#else /* #ifdef MODULE */
6325/**---------------------------------------------------------------------------
6326
Jeff Johnson76052702013-04-16 13:55:05 -07006327 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006328
Jeff Johnson76052702013-04-16 13:55:05 -07006329 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006330 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006331 - invoked when module parameter fwpath is modified from userspace to signal
6332 initializing the WLAN driver or when con_mode is modified from userspace
6333 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006334
6335 \return - 0 for success, non zero for failure
6336
6337 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006338static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006339{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006340 int ret_status;
6341
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006342 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006343 ret_status = hdd_driver_init();
6344 wlan_hdd_inited = ret_status ? 0 : 1;
6345 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006346 }
6347
6348 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006349
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006350 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006351
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006352 ret_status = hdd_driver_init();
6353 wlan_hdd_inited = ret_status ? 0 : 1;
6354 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006355}
6356
Jeff Johnson295189b2012-06-20 16:38:30 -07006357/**---------------------------------------------------------------------------
6358
Jeff Johnson76052702013-04-16 13:55:05 -07006359 \brief fwpath_changed_handler() - Handler Function
6360
6361 Handle changes to the fwpath parameter
6362
6363 \return - 0 for success, non zero for failure
6364
6365 --------------------------------------------------------------------------*/
6366static int fwpath_changed_handler(const char *kmessage,
6367 struct kernel_param *kp)
6368{
6369 int ret;
6370
6371 ret = param_set_copystring(kmessage, kp);
6372 if (0 == ret)
6373 ret = kickstart_driver();
6374 return ret;
6375}
6376
6377/**---------------------------------------------------------------------------
6378
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006379 \brief con_mode_handler() -
6380
6381 Handler function for module param con_mode when it is changed by userspace
6382 Dynamically linked - do nothing
6383 Statically linked - exit and init driver, as in rmmod and insmod
6384
Jeff Johnson76052702013-04-16 13:55:05 -07006385 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006386
Jeff Johnson76052702013-04-16 13:55:05 -07006387 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006388
6389 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006390static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006391{
Jeff Johnson76052702013-04-16 13:55:05 -07006392 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006393
Jeff Johnson76052702013-04-16 13:55:05 -07006394 ret = param_set_int(kmessage, kp);
6395 if (0 == ret)
6396 ret = kickstart_driver();
6397 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006398}
6399#endif /* #ifdef MODULE */
6400
6401/**---------------------------------------------------------------------------
6402
Jeff Johnson295189b2012-06-20 16:38:30 -07006403 \brief hdd_get_conparam() -
6404
6405 This is the driver exit point (invoked when module is unloaded using rmmod)
6406
6407 \param - None
6408
6409 \return - tVOS_CON_MODE
6410
6411 --------------------------------------------------------------------------*/
6412tVOS_CON_MODE hdd_get_conparam ( void )
6413{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006414#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006415 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006416#else
6417 return (tVOS_CON_MODE)curr_con_mode;
6418#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006419}
6420void hdd_set_conparam ( v_UINT_t newParam )
6421{
6422 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006423#ifndef MODULE
6424 curr_con_mode = con_mode;
6425#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006426}
6427/**---------------------------------------------------------------------------
6428
6429 \brief hdd_softap_sta_deauth() - function
6430
6431 This to take counter measure to handle deauth req from HDD
6432
6433 \param - pAdapter - Pointer to the HDD
6434
6435 \param - enable - boolean value
6436
6437 \return - None
6438
6439 --------------------------------------------------------------------------*/
6440
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006441VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006442{
Jeff Johnson295189b2012-06-20 16:38:30 -07006443 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006444 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006445
6446 ENTER();
6447
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306448 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006449
6450 //Ignore request to deauth bcmc station
6451 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006452 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006453
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006454 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006455
6456 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006457 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006458}
6459
6460/**---------------------------------------------------------------------------
6461
6462 \brief hdd_softap_sta_disassoc() - function
6463
6464 This to take counter measure to handle deauth req from HDD
6465
6466 \param - pAdapter - Pointer to the HDD
6467
6468 \param - enable - boolean value
6469
6470 \return - None
6471
6472 --------------------------------------------------------------------------*/
6473
6474void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6475{
6476 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6477
6478 ENTER();
6479
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306480 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006481
6482 //Ignore request to disassoc bcmc station
6483 if( pDestMacAddress[0] & 0x1 )
6484 return;
6485
6486 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6487}
6488
6489void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6490{
6491 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6492
6493 ENTER();
6494
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306495 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006496
6497 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6498}
6499
Jeff Johnson295189b2012-06-20 16:38:30 -07006500/**---------------------------------------------------------------------------
6501 *
6502 * \brief hdd_get__concurrency_mode() -
6503 *
6504 *
6505 * \param - None
6506 *
6507 * \return - CONCURRENCY MODE
6508 *
6509 * --------------------------------------------------------------------------*/
6510tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6511{
6512 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6513 hdd_context_t *pHddCtx;
6514
6515 if (NULL != pVosContext)
6516 {
6517 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6518 if (NULL != pHddCtx)
6519 {
6520 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6521 }
6522 }
6523
6524 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006525 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006526 return VOS_STA;
6527}
6528
6529/* Decide whether to allow/not the apps power collapse.
6530 * Allow apps power collapse if we are in connected state.
6531 * if not, allow only if we are in IMPS */
6532v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6533{
6534 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006535 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006536 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006537 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6538 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6539 hdd_adapter_t *pAdapter = NULL;
6540 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006541 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006542
Jeff Johnson295189b2012-06-20 16:38:30 -07006543 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6544 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006545
Yathish9f22e662012-12-10 14:21:35 -08006546 concurrent_state = hdd_get_concurrency_mode();
6547
6548#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6549 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6550 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6551 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6552 return TRUE;
6553#endif
6554
Jeff Johnson295189b2012-06-20 16:38:30 -07006555 /*loop through all adapters. TBD fix for Concurrency */
6556 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6557 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6558 {
6559 pAdapter = pAdapterNode->pAdapter;
6560 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6561 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6562 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006563 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006564 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006565 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006566 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6567 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006568 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006569 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006570 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6571 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006572 return FALSE;
6573 }
6574 }
6575 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6576 pAdapterNode = pNext;
6577 }
6578 return TRUE;
6579}
6580
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006581/* Decides whether to send suspend notification to Riva
6582 * if any adapter is in BMPS; then it is required */
6583v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6584{
6585 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6586 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6587
6588 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6589 {
6590 return TRUE;
6591 }
6592 return FALSE;
6593}
6594
Jeff Johnson295189b2012-06-20 16:38:30 -07006595void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6596{
6597 switch(mode)
6598 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006599 case VOS_STA_MODE:
6600 case VOS_P2P_CLIENT_MODE:
6601 case VOS_P2P_GO_MODE:
6602 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006603 pHddCtx->concurrency_mode |= (1 << mode);
6604 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006605 break;
6606 default:
6607 break;
6608
6609 }
6610 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6611 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6612}
6613
6614
6615void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6616{
6617 switch(mode)
6618 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006619 case VOS_STA_MODE:
6620 case VOS_P2P_CLIENT_MODE:
6621 case VOS_P2P_GO_MODE:
6622 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006623 pHddCtx->no_of_sessions[mode]--;
6624 if (!(pHddCtx->no_of_sessions[mode]))
6625 pHddCtx->concurrency_mode &= (~(1 << mode));
6626 break;
6627 default:
6628 break;
6629 }
6630 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6631 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6632}
6633
Jeff Johnsone7245742012-09-05 17:12:55 -07006634/**---------------------------------------------------------------------------
6635 *
6636 * \brief wlan_hdd_restart_init
6637 *
6638 * This function initalizes restart timer/flag. An internal function.
6639 *
6640 * \param - pHddCtx
6641 *
6642 * \return - None
6643 *
6644 * --------------------------------------------------------------------------*/
6645
6646static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6647{
6648 /* Initialize */
6649 pHddCtx->hdd_restart_retries = 0;
6650 atomic_set(&pHddCtx->isRestartInProgress, 0);
6651 vos_timer_init(&pHddCtx->hdd_restart_timer,
6652 VOS_TIMER_TYPE_SW,
6653 wlan_hdd_restart_timer_cb,
6654 pHddCtx);
6655}
6656/**---------------------------------------------------------------------------
6657 *
6658 * \brief wlan_hdd_restart_deinit
6659 *
6660 * This function cleans up the resources used. An internal function.
6661 *
6662 * \param - pHddCtx
6663 *
6664 * \return - None
6665 *
6666 * --------------------------------------------------------------------------*/
6667
6668static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6669{
6670
6671 VOS_STATUS vos_status;
6672 /* Block any further calls */
6673 atomic_set(&pHddCtx->isRestartInProgress, 1);
6674 /* Cleanup */
6675 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6676 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006677 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006678 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6679 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006680 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006681
6682}
6683
6684/**---------------------------------------------------------------------------
6685 *
6686 * \brief wlan_hdd_framework_restart
6687 *
6688 * This function uses a cfg80211 API to start a framework initiated WLAN
6689 * driver module unload/load.
6690 *
6691 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6692 *
6693 *
6694 * \param - pHddCtx
6695 *
6696 * \return - VOS_STATUS_SUCCESS: Success
6697 * VOS_STATUS_E_EMPTY: Adapter is Empty
6698 * VOS_STATUS_E_NOMEM: No memory
6699
6700 * --------------------------------------------------------------------------*/
6701
6702static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6703{
6704 VOS_STATUS status = VOS_STATUS_SUCCESS;
6705 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006706 int len = (sizeof (struct ieee80211_mgmt));
6707 struct ieee80211_mgmt *mgmt = NULL;
6708
6709 /* Prepare the DEAUTH managment frame with reason code */
6710 mgmt = kzalloc(len, GFP_KERNEL);
6711 if(mgmt == NULL)
6712 {
6713 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6714 "%s: memory allocation failed (%d bytes)", __func__, len);
6715 return VOS_STATUS_E_NOMEM;
6716 }
6717 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006718
6719 /* Iterate over all adapters/devices */
6720 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6721 do
6722 {
6723 if( (status == VOS_STATUS_SUCCESS) &&
6724 pAdapterNode &&
6725 pAdapterNode->pAdapter)
6726 {
6727 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6728 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6729 pAdapterNode->pAdapter->dev->name,
6730 pAdapterNode->pAdapter->device_mode,
6731 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006732 /*
6733 * CFG80211 event to restart the driver
6734 *
6735 * 'cfg80211_send_unprot_deauth' sends a
6736 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6737 * of SME(Linux Kernel) state machine.
6738 *
6739 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6740 * the driver.
6741 *
6742 */
6743
6744 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006745 }
6746 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6747 pAdapterNode = pNext;
6748 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6749
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006750
6751 /* Free the allocated management frame */
6752 kfree(mgmt);
6753
Jeff Johnsone7245742012-09-05 17:12:55 -07006754 /* Retry until we unload or reach max count */
6755 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6756 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6757
6758 return status;
6759
6760}
6761/**---------------------------------------------------------------------------
6762 *
6763 * \brief wlan_hdd_restart_timer_cb
6764 *
6765 * Restart timer callback. An internal function.
6766 *
6767 * \param - User data:
6768 *
6769 * \return - None
6770 *
6771 * --------------------------------------------------------------------------*/
6772
6773void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6774{
6775 hdd_context_t *pHddCtx = usrDataForCallback;
6776 wlan_hdd_framework_restart(pHddCtx);
6777 return;
6778
6779}
6780
6781
6782/**---------------------------------------------------------------------------
6783 *
6784 * \brief wlan_hdd_restart_driver
6785 *
6786 * This function sends an event to supplicant to restart the WLAN driver.
6787 *
6788 * This function is called from vos_wlanRestart.
6789 *
6790 * \param - pHddCtx
6791 *
6792 * \return - VOS_STATUS_SUCCESS: Success
6793 * VOS_STATUS_E_EMPTY: Adapter is Empty
6794 * VOS_STATUS_E_ALREADY: Request already in progress
6795
6796 * --------------------------------------------------------------------------*/
6797VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6798{
6799 VOS_STATUS status = VOS_STATUS_SUCCESS;
6800
6801 /* A tight check to make sure reentrancy */
6802 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6803 {
6804 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6805 "%s: WLAN restart is already in progress", __func__);
6806
6807 return VOS_STATUS_E_ALREADY;
6808 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006809 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006810#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006811 wcnss_reset_intr();
6812#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006813
Jeff Johnsone7245742012-09-05 17:12:55 -07006814 return status;
6815}
6816
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006817/*
6818 * API to find if there is any STA or P2P-Client is connected
6819 */
6820VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6821{
6822 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6823}
Jeff Johnsone7245742012-09-05 17:12:55 -07006824
Jeff Johnson295189b2012-06-20 16:38:30 -07006825//Register the module init/exit functions
6826module_init(hdd_module_init);
6827module_exit(hdd_module_exit);
6828
6829MODULE_LICENSE("Dual BSD/GPL");
6830MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6831MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6832
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006833module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6834 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006835
Jeff Johnson76052702013-04-16 13:55:05 -07006836module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006837 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);