blob: ed27ee932da5893f03973176ab534e646c8aa14f [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
Jeff Johnson295189b2012-06-20 16:38:30 -07005040 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07005041 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005042
5043 //Close the scheduler before calling vos_close to make sure no thread is
5044 // scheduled after the each module close is called i.e after all the data
5045 // structures are freed.
5046 vosStatus = vos_sched_close( pVosContext );
5047 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
5048 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5049 "%s: Failed to close VOSS Scheduler",__func__);
5050 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5051 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005052#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005053#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5054 /* Destroy the wake lock */
5055 wake_lock_destroy(&pHddCtx->rx_wake_lock);
5056#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005057 /* Destroy the wake lock */
5058 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005059#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005060
5061 //Close VOSS
5062 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
5063 vos_close(pVosContext);
5064
Jeff Johnson295189b2012-06-20 16:38:30 -07005065 //Close Watchdog
5066 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5067 vos_watchdog_close(pVosContext);
5068
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305069 //Clean up HDD Nlink Service
5070 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
5071 nl_srv_exit();
5072
Jeff Johnson295189b2012-06-20 16:38:30 -07005073 /* Cancel the vote for XO Core ON.
5074 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5075 * exited at this point
5076 */
5077 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5078 " when WLAN is turned OFF\n");
5079 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5080 {
5081 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5082 " Not returning failure."
5083 " Power consumed will be high\n");
5084 }
5085
5086 hdd_close_all_adapters( pHddCtx );
5087
5088
5089 //Free up dynamically allocated members inside HDD Adapter
5090 kfree(pHddCtx->cfg_ini);
5091 pHddCtx->cfg_ini= NULL;
5092
5093 /* free the power on lock from platform driver */
5094 if (free_riva_power_on_lock("wlan"))
5095 {
5096 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5097 __func__);
5098 }
5099
Jeff Johnson88ba7742013-02-27 14:36:02 -08005100free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08005101 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005102 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005103 if (hdd_is_ssr_required())
5104 {
5105 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005106 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005107 msleep(5000);
5108 }
5109 hdd_set_ssr_required (VOS_FALSE);
5110}
5111
5112
5113/**---------------------------------------------------------------------------
5114
5115 \brief hdd_update_config_from_nv() - Function to update the contents of
5116 the running configuration with parameters taken from NV storage
5117
5118 \param - pHddCtx - Pointer to the HDD global context
5119
5120 \return - VOS_STATUS_SUCCESS if successful
5121
5122 --------------------------------------------------------------------------*/
5123static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5124{
Jeff Johnson295189b2012-06-20 16:38:30 -07005125 v_BOOL_t itemIsValid = VOS_FALSE;
5126 VOS_STATUS status;
5127 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5128 v_U8_t macLoop;
5129
5130 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5131 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5132 if(status != VOS_STATUS_SUCCESS)
5133 {
5134 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5135 return VOS_STATUS_E_FAILURE;
5136 }
5137
5138 if (itemIsValid == VOS_TRUE)
5139 {
5140 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5141 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5142 VOS_MAX_CONCURRENCY_PERSONA);
5143 if(status != VOS_STATUS_SUCCESS)
5144 {
5145 /* Get MAC from NV fail, not update CFG info
5146 * INI MAC value will be used for MAC setting */
5147 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5148 return VOS_STATUS_E_FAILURE;
5149 }
5150
5151 /* If first MAC is not valid, treat all others are not valid
5152 * Then all MACs will be got from ini file */
5153 if(vos_is_macaddr_zero(&macFromNV[0]))
5154 {
5155 /* MAC address in NV file is not configured yet */
5156 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5157 return VOS_STATUS_E_INVAL;
5158 }
5159
5160 /* Get MAC address from NV, update CFG info */
5161 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5162 {
5163 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5164 {
5165 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5166 /* This MAC is not valid, skip it
5167 * This MAC will be got from ini file */
5168 }
5169 else
5170 {
5171 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5172 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5173 VOS_MAC_ADDR_SIZE);
5174 }
5175 }
5176 }
5177 else
5178 {
5179 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5180 return VOS_STATUS_E_FAILURE;
5181 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005182
Jeff Johnson295189b2012-06-20 16:38:30 -07005183
5184 return VOS_STATUS_SUCCESS;
5185}
5186
5187/**---------------------------------------------------------------------------
5188
5189 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5190
5191 \param - pAdapter - Pointer to the HDD
5192
5193 \return - None
5194
5195 --------------------------------------------------------------------------*/
5196VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5197{
5198 eHalStatus halStatus;
5199 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305200 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005201
Jeff Johnson295189b2012-06-20 16:38:30 -07005202
5203 // Send ready indication to the HDD. This will kick off the MAC
5204 // into a 'running' state and should kick off an initial scan.
5205 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5206 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5207 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305208 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005209 "code %08d [x%08x]",__func__, halStatus, halStatus );
5210 return VOS_STATUS_E_FAILURE;
5211 }
5212
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305213 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005214 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5215 // And RIVA will crash
5216 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5217 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305218 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5219 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5220
5221
Jeff Johnson295189b2012-06-20 16:38:30 -07005222 return VOS_STATUS_SUCCESS;
5223}
5224
Jeff Johnson295189b2012-06-20 16:38:30 -07005225/* wake lock APIs for HDD */
5226void hdd_prevent_suspend(void)
5227{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005228#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005229 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005230#else
5231 wcnss_prevent_suspend();
5232#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005233}
5234
5235void hdd_allow_suspend(void)
5236{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005237#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005238 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005239#else
5240 wcnss_allow_suspend();
5241#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005242}
5243
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005244void hdd_allow_suspend_timeout(v_U32_t timeout)
5245{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005246#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005247 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005248#else
5249 /* Do nothing as there is no API in wcnss for timeout*/
5250#endif
5251}
5252
Jeff Johnson295189b2012-06-20 16:38:30 -07005253/**---------------------------------------------------------------------------
5254
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005255 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5256 information between Host and Riva
5257
5258 This function gets reported version of FW
5259 It also finds the version of Riva headers used to compile the host
5260 It compares the above two and prints a warning if they are different
5261 It gets the SW and HW version string
5262 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5263 indicating the features they support through a bitmap
5264
5265 \param - pHddCtx - Pointer to HDD context
5266
5267 \return - void
5268
5269 --------------------------------------------------------------------------*/
5270
5271void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5272{
5273
5274 tSirVersionType versionCompiled;
5275 tSirVersionType versionReported;
5276 tSirVersionString versionString;
5277 tANI_U8 fwFeatCapsMsgSupported = 0;
5278 VOS_STATUS vstatus;
5279
5280 /* retrieve and display WCNSS version information */
5281 do {
5282
5283 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5284 &versionCompiled);
5285 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5286 {
5287 hddLog(VOS_TRACE_LEVEL_FATAL,
5288 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005289 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005290 break;
5291 }
5292
5293 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5294 &versionReported);
5295 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5296 {
5297 hddLog(VOS_TRACE_LEVEL_FATAL,
5298 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005299 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005300 break;
5301 }
5302
5303 if ((versionCompiled.major != versionReported.major) ||
5304 (versionCompiled.minor != versionReported.minor) ||
5305 (versionCompiled.version != versionReported.version) ||
5306 (versionCompiled.revision != versionReported.revision))
5307 {
5308 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5309 "Host expected %u.%u.%u.%u\n",
5310 WLAN_MODULE_NAME,
5311 (int)versionReported.major,
5312 (int)versionReported.minor,
5313 (int)versionReported.version,
5314 (int)versionReported.revision,
5315 (int)versionCompiled.major,
5316 (int)versionCompiled.minor,
5317 (int)versionCompiled.version,
5318 (int)versionCompiled.revision);
5319 }
5320 else
5321 {
5322 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5323 WLAN_MODULE_NAME,
5324 (int)versionReported.major,
5325 (int)versionReported.minor,
5326 (int)versionReported.version,
5327 (int)versionReported.revision);
5328 }
5329
5330 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5331 versionString,
5332 sizeof(versionString));
5333 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5334 {
5335 hddLog(VOS_TRACE_LEVEL_FATAL,
5336 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005337 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005338 break;
5339 }
5340
5341 pr_info("%s: WCNSS software version %s\n",
5342 WLAN_MODULE_NAME, versionString);
5343
5344 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5345 versionString,
5346 sizeof(versionString));
5347 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5348 {
5349 hddLog(VOS_TRACE_LEVEL_FATAL,
5350 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005351 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005352 break;
5353 }
5354
5355 pr_info("%s: WCNSS hardware version %s\n",
5356 WLAN_MODULE_NAME, versionString);
5357
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005358 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5359 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005360 send the message only if it the riva is 1.1
5361 minor numbers for different riva branches:
5362 0 -> (1.0)Mainline Build
5363 1 -> (1.1)Mainline Build
5364 2->(1.04) Stability Build
5365 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005366 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005367 ((versionReported.minor>=1) && (versionReported.version>=1)))
5368 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5369 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005370
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005371 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005372 {
5373#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5374 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5375 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5376#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005377 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005378 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005379
5380 } while (0);
5381
5382}
5383
5384/**---------------------------------------------------------------------------
5385
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305386 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5387
5388 \param - pHddCtx - Pointer to the hdd context
5389
5390 \return - true if hardware supports 5GHz
5391
5392 --------------------------------------------------------------------------*/
5393static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5394{
5395 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5396 * then hardware support 5Ghz.
5397 */
5398 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5399 {
5400 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5401 return true;
5402 }
5403 else
5404 {
5405 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5406 __func__);
5407 return false;
5408 }
5409}
5410
5411
5412/**---------------------------------------------------------------------------
5413
Jeff Johnson295189b2012-06-20 16:38:30 -07005414 \brief hdd_wlan_startup() - HDD init function
5415
5416 This is the driver startup code executed once a WLAN device has been detected
5417
5418 \param - dev - Pointer to the underlying device
5419
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005420 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005421
5422 --------------------------------------------------------------------------*/
5423
5424int hdd_wlan_startup(struct device *dev )
5425{
5426 VOS_STATUS status;
5427 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005428 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005429 hdd_context_t *pHddCtx = NULL;
5430 v_CONTEXT_t pVosContext= NULL;
5431#ifdef WLAN_BTAMP_FEATURE
5432 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5433 WLANBAP_ConfigType btAmpConfig;
5434 hdd_config_t *pConfig;
5435#endif
5436 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005437 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005438
5439 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005440 /*
5441 * cfg80211: wiphy allocation
5442 */
5443 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5444
5445 if(wiphy == NULL)
5446 {
5447 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005448 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005449 }
5450
5451 pHddCtx = wiphy_priv(wiphy);
5452
Jeff Johnson295189b2012-06-20 16:38:30 -07005453 //Initialize the adapter context to zeros.
5454 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5455
Jeff Johnson295189b2012-06-20 16:38:30 -07005456 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005457 hdd_prevent_suspend();
5458 pHddCtx->isLoadUnloadInProgress = TRUE;
5459
5460 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5461
5462 /*Get vos context here bcoz vos_open requires it*/
5463 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5464
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005465 if(pVosContext == NULL)
5466 {
5467 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5468 goto err_free_hdd_context;
5469 }
5470
Jeff Johnson295189b2012-06-20 16:38:30 -07005471 //Save the Global VOSS context in adapter context for future.
5472 pHddCtx->pvosContext = pVosContext;
5473
5474 //Save the adapter context in global context for future.
5475 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5476
Jeff Johnson295189b2012-06-20 16:38:30 -07005477 pHddCtx->parent_dev = dev;
5478
5479 init_completion(&pHddCtx->full_pwr_comp_var);
5480 init_completion(&pHddCtx->standby_comp_var);
5481 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005482 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005483 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005484
5485 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5486
5487 // Load all config first as TL config is needed during vos_open
5488 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5489 if(pHddCtx->cfg_ini == NULL)
5490 {
5491 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5492 goto err_free_hdd_context;
5493 }
5494
5495 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5496
5497 // Read and parse the qcom_cfg.ini file
5498 status = hdd_parse_config_ini( pHddCtx );
5499 if ( VOS_STATUS_SUCCESS != status )
5500 {
5501 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5502 __func__, WLAN_INI_FILE);
5503 goto err_config;
5504 }
5505
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305506 /* INI has been read, initialise the configuredMcastBcastFilter with
5507 * INI value as this will serve as the default value
5508 */
5509 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5510 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5511 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305512
5513 if (false == hdd_is_5g_supported(pHddCtx))
5514 {
5515 //5Ghz is not supported.
5516 if (1 != pHddCtx->cfg_ini->nBandCapability)
5517 {
5518 hddLog(VOS_TRACE_LEVEL_INFO,
5519 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5520 pHddCtx->cfg_ini->nBandCapability = 1;
5521 }
5522 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005523 /*
5524 * cfg80211: Initialization and registration ...
5525 */
5526 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5527 {
5528 hddLog(VOS_TRACE_LEVEL_FATAL,
5529 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5530 goto err_wiphy_reg;
5531 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005532
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005533 // Update VOS trace levels based upon the cfg.ini
5534 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5535 pHddCtx->cfg_ini->vosTraceEnableBAP);
5536 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5537 pHddCtx->cfg_ini->vosTraceEnableTL);
5538 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5539 pHddCtx->cfg_ini->vosTraceEnableWDI);
5540 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5541 pHddCtx->cfg_ini->vosTraceEnableHDD);
5542 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5543 pHddCtx->cfg_ini->vosTraceEnableSME);
5544 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5545 pHddCtx->cfg_ini->vosTraceEnablePE);
5546 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5547 pHddCtx->cfg_ini->vosTraceEnableWDA);
5548 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5549 pHddCtx->cfg_ini->vosTraceEnableSYS);
5550 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5551 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005552 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5553 pHddCtx->cfg_ini->vosTraceEnableSAP);
5554 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5555 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005556
Jeff Johnson295189b2012-06-20 16:38:30 -07005557 // Update WDI trace levels based upon the cfg.ini
5558 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5559 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5560 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5561 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5562 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5563 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5564 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5565 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005566
Jeff Johnson88ba7742013-02-27 14:36:02 -08005567 if (VOS_FTM_MODE == hdd_get_conparam())
5568 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005569 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5570 {
5571 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5572 goto err_free_hdd_context;
5573 }
5574 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5575 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005576 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005577
Jeff Johnson88ba7742013-02-27 14:36:02 -08005578 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005579 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5580 {
5581 status = vos_watchdog_open(pVosContext,
5582 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5583
5584 if(!VOS_IS_STATUS_SUCCESS( status ))
5585 {
5586 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005587 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005588 }
5589 }
5590
5591 pHddCtx->isLogpInProgress = FALSE;
5592 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5593
Jeff Johnson295189b2012-06-20 16:38:30 -07005594 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5595 if(!VOS_IS_STATUS_SUCCESS(status))
5596 {
5597 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005598 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005599 }
5600
Jeff Johnson295189b2012-06-20 16:38:30 -07005601 status = vos_open( &pVosContext, 0);
5602 if ( !VOS_IS_STATUS_SUCCESS( status ))
5603 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005604 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5605 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005606 }
5607
Jeff Johnson295189b2012-06-20 16:38:30 -07005608 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5609
5610 if ( NULL == pHddCtx->hHal )
5611 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005612 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005613 goto err_vosclose;
5614 }
5615
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005616 status = vos_preStart( pHddCtx->pvosContext );
5617 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5618 {
5619 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5620 goto err_vosclose;
5621 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005622
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005623 /* Note that the vos_preStart() sequence triggers the cfg download.
5624 The cfg download must occur before we update the SME config
5625 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005626 status = hdd_set_sme_config( pHddCtx );
5627
5628 if ( VOS_STATUS_SUCCESS != status )
5629 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005630 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5631 goto err_vosclose;
5632 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005633
5634 //Initialize the WMM module
5635 status = hdd_wmm_init(pHddCtx);
5636 if (!VOS_IS_STATUS_SUCCESS(status))
5637 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005638 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005639 goto err_vosclose;
5640 }
5641
Jeff Johnson295189b2012-06-20 16:38:30 -07005642 /* In the integrated architecture we update the configuration from
5643 the INI file and from NV before vOSS has been started so that
5644 the final contents are available to send down to the cCPU */
5645
5646 // Apply the cfg.ini to cfg.dat
5647 if (FALSE == hdd_update_config_dat(pHddCtx))
5648 {
5649 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5650 goto err_vosclose;
5651 }
5652
5653 // Apply the NV to cfg.dat
5654 /* Prima Update MAC address only at here */
5655 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5656 {
5657#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5658 /* There was not a valid set of MAC Addresses in NV. See if the
5659 default addresses were modified by the cfg.ini settings. If so,
5660 we'll use them, but if not, we'll autogenerate a set of MAC
5661 addresses based upon the device serial number */
5662
5663 static const v_MACADDR_t default_address =
5664 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5665 unsigned int serialno;
5666 int i;
5667
5668 serialno = wcnss_get_serial_number();
5669 if ((0 != serialno) &&
5670 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5671 sizeof(default_address))))
5672 {
5673 /* cfg.ini has the default address, invoke autogen logic */
5674
5675 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5676 bytes of the serial number that can be used to generate
5677 the other 3 bytes of the MAC address. Mask off all but
5678 the lower 3 bytes (this will also make sure we don't
5679 overflow in the next step) */
5680 serialno &= 0x00FFFFFF;
5681
5682 /* we need a unique address for each session */
5683 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5684
5685 /* autogen all addresses */
5686 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5687 {
5688 /* start with the entire default address */
5689 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5690 /* then replace the lower 3 bytes */
5691 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5692 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5693 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5694
5695 serialno++;
5696 }
5697
5698 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5699 MAC_ADDRESS_STR,
5700 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5701 }
5702 else
5703#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5704 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005705 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005706 "%s: Invalid MAC address in NV, using MAC from ini file "
5707 MAC_ADDRESS_STR, __func__,
5708 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5709 }
5710 }
5711 {
5712 eHalStatus halStatus;
5713 // Set the MAC Address
5714 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5715 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5716 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5717 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5718
5719 if (!HAL_STATUS_SUCCESS( halStatus ))
5720 {
5721 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5722 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005723 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005724 }
5725 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005726
5727 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5728 Note: Firmware image will be read and downloaded inside vos_start API */
5729 status = vos_start( pHddCtx->pvosContext );
5730 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5731 {
5732 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5733 goto err_vosclose;
5734 }
5735
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005736 /* Exchange capability info between Host and FW and also get versioning info from FW */
5737 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005738
5739 status = hdd_post_voss_start_config( pHddCtx );
5740 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5741 {
5742 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5743 __func__);
5744 goto err_vosstop;
5745 }
5746
Jeff Johnson295189b2012-06-20 16:38:30 -07005747 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5748 {
5749 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5750 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5751 }
5752 else
5753 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005754 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5755 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5756 if (pAdapter != NULL)
5757 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305758 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005759 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305760 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5761 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5762 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005763
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305764 /* Generate the P2P Device Address. This consists of the device's
5765 * primary MAC address with the locally administered bit set.
5766 */
5767 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005768 }
5769 else
5770 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305771 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5772 if (p2p_dev_addr != NULL)
5773 {
5774 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5775 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5776 }
5777 else
5778 {
5779 hddLog(VOS_TRACE_LEVEL_FATAL,
5780 "%s: Failed to allocate mac_address for p2p_device",
5781 __func__);
5782 goto err_close_adapter;
5783 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005784 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005785
5786 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5787 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5788 if ( NULL == pP2pAdapter )
5789 {
5790 hddLog(VOS_TRACE_LEVEL_FATAL,
5791 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005792 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005793 goto err_close_adapter;
5794 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005795 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005796 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005797
5798 if( pAdapter == NULL )
5799 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005800 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5801 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005802 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005803
Jeff Johnson295189b2012-06-20 16:38:30 -07005804#ifdef WLAN_BTAMP_FEATURE
5805 vStatus = WLANBAP_Open(pVosContext);
5806 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5807 {
5808 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5809 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005810 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005811 }
5812
5813 vStatus = BSL_Init(pVosContext);
5814 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5815 {
5816 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5817 "%s: Failed to Init BSL",__func__);
5818 goto err_bap_close;
5819 }
5820 vStatus = WLANBAP_Start(pVosContext);
5821 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5822 {
5823 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5824 "%s: Failed to start TL",__func__);
5825 goto err_bap_close;
5826 }
5827
5828 pConfig = pHddCtx->cfg_ini;
5829 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5830 status = WLANBAP_SetConfig(&btAmpConfig);
5831
5832#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005833
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005834#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5835 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5836 {
5837 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5838 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5839 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5840 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5841 }
5842#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005843#ifdef FEATURE_WLAN_SCAN_PNO
5844 /*SME must send channel update configuration to RIVA*/
5845 sme_UpdateChannelConfig(pHddCtx->hHal);
5846#endif
5847
Jeff Johnson295189b2012-06-20 16:38:30 -07005848 /* Register with platform driver as client for Suspend/Resume */
5849 status = hddRegisterPmOps(pHddCtx);
5850 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5851 {
5852 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5853#ifdef WLAN_BTAMP_FEATURE
5854 goto err_bap_stop;
5855#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005856 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005857#endif //WLAN_BTAMP_FEATURE
5858 }
5859
5860 /* Register TM level change handler function to the platform */
5861 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5862 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5863 {
5864 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5865 goto err_unregister_pmops;
5866 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005867
5868 /* register for riva power on lock to platform driver */
5869 if (req_riva_power_on_lock("wlan"))
5870 {
5871 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5872 __func__);
5873 goto err_unregister_pmops;
5874 }
5875
Jeff Johnson295189b2012-06-20 16:38:30 -07005876 // register net device notifier for device change notification
5877 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5878
5879 if(ret < 0)
5880 {
5881 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5882 goto err_free_power_on_lock;
5883 }
5884
5885 //Initialize the nlink service
5886 if(nl_srv_init() != 0)
5887 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305888 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005889 goto err_reg_netdev;
5890 }
5891
5892 //Initialize the BTC service
5893 if(btc_activate_service(pHddCtx) != 0)
5894 {
5895 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5896 goto err_nl_srv;
5897 }
5898
5899#ifdef PTT_SOCK_SVC_ENABLE
5900 //Initialize the PTT service
5901 if(ptt_sock_activate_svc(pHddCtx) != 0)
5902 {
5903 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5904 goto err_nl_srv;
5905 }
5906#endif
5907
Jeff Johnson295189b2012-06-20 16:38:30 -07005908 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005909 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005910 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005911 /* Action frame registered in one adapter which will
5912 * applicable to all interfaces
5913 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005914 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005915 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005916
5917 mutex_init(&pHddCtx->sap_lock);
5918
5919 pHddCtx->isLoadUnloadInProgress = FALSE;
5920
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005921#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005922#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5923 /* Initialize the wake lcok */
5924 wake_lock_init(&pHddCtx->rx_wake_lock,
5925 WAKE_LOCK_SUSPEND,
5926 "qcom_rx_wakelock");
5927#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005928 /* Initialize the wake lcok */
5929 wake_lock_init(&pHddCtx->sap_wake_lock,
5930 WAKE_LOCK_SUSPEND,
5931 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005932#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005933
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005934 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5935 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005936
5937 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5938 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305939
Jeff Johnsone7245742012-09-05 17:12:55 -07005940 // Initialize the restart logic
5941 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305942
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305943 if (!VOS_IS_STATUS_SUCCESS( vos_timer_init( &pHddCtx->hdd_p2p_go_conn_is_in_progress,
5944 VOS_TIMER_TYPE_SW, wlan_hdd_p2p_go_connection_in_progresscb, pAdapter) ) )
5945 {
5946 hddLog(VOS_TRACE_LEVEL_ERROR,
5947 "%s: vos timer init failed for hdd_p2p_go_conn_is_in_progress", __func__);
5948 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005949 goto success;
5950
5951err_nl_srv:
5952 nl_srv_exit();
5953
5954err_reg_netdev:
5955 unregister_netdevice_notifier(&hdd_netdev_notifier);
5956
5957err_free_power_on_lock:
5958 free_riva_power_on_lock("wlan");
5959
5960err_unregister_pmops:
5961 hddDevTmUnregisterNotifyCallback(pHddCtx);
5962 hddDeregisterPmOps(pHddCtx);
5963
5964#ifdef WLAN_BTAMP_FEATURE
5965err_bap_stop:
5966 WLANBAP_Stop(pVosContext);
5967#endif
5968
5969#ifdef WLAN_BTAMP_FEATURE
5970err_bap_close:
5971 WLANBAP_Close(pVosContext);
5972#endif
5973
Jeff Johnson295189b2012-06-20 16:38:30 -07005974err_close_adapter:
5975 hdd_close_all_adapters( pHddCtx );
5976
5977err_vosstop:
5978 vos_stop(pVosContext);
5979
5980err_vosclose:
5981 status = vos_sched_close( pVosContext );
5982 if (!VOS_IS_STATUS_SUCCESS(status)) {
5983 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5984 "%s: Failed to close VOSS Scheduler", __func__);
5985 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5986 }
5987 vos_close(pVosContext );
5988
Jeff Johnson295189b2012-06-20 16:38:30 -07005989err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005990 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005991
5992err_wdclose:
5993 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5994 vos_watchdog_close(pVosContext);
5995
Jeff Johnson295189b2012-06-20 16:38:30 -07005996err_wiphy_reg:
5997 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005998
5999err_config:
6000 kfree(pHddCtx->cfg_ini);
6001 pHddCtx->cfg_ini= NULL;
6002
6003err_free_hdd_context:
6004 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07006005 wiphy_free(wiphy) ;
6006 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006007 VOS_BUG(1);
6008
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08006009 if (hdd_is_ssr_required())
6010 {
6011 /* WDI timeout had happened during load, so SSR is needed here */
6012 subsystem_restart("wcnss");
6013 msleep(5000);
6014 }
6015 hdd_set_ssr_required (VOS_FALSE);
6016
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006017 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006018
6019success:
6020 EXIT();
6021 return 0;
6022}
6023
6024/**---------------------------------------------------------------------------
6025
Jeff Johnson32d95a32012-09-10 13:15:23 -07006026 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07006027
Jeff Johnson32d95a32012-09-10 13:15:23 -07006028 This is the driver entry point - called in different timeline depending
6029 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07006030
6031 \param - None
6032
6033 \return - 0 for success, non zero for failure
6034
6035 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07006036static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006037{
6038 VOS_STATUS status;
6039 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006040 struct device *dev = NULL;
6041 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006042#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6043 int max_retries = 0;
6044#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006045
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306046#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6047 vos_wconn_trace_init();
6048#endif
6049
Jeff Johnson295189b2012-06-20 16:38:30 -07006050 ENTER();
6051
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006052#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006053 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07006054#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006055
6056 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
6057 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
6058
6059 //Power Up Libra WLAN card first if not already powered up
6060 status = vos_chipPowerUp(NULL,NULL,NULL);
6061 if (!VOS_IS_STATUS_SUCCESS(status))
6062 {
6063 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
6064 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306065#ifdef WLAN_OPEN_SOURCE
6066 wake_lock_destroy(&wlan_wake_lock);
6067#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006068 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006069 }
6070
Jeff Johnson295189b2012-06-20 16:38:30 -07006071#ifdef ANI_BUS_TYPE_PCI
6072
6073 dev = wcnss_wlan_get_device();
6074
6075#endif // ANI_BUS_TYPE_PCI
6076
6077#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006078
6079#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6080 /* wait until WCNSS driver downloads NV */
6081 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6082 msleep(1000);
6083 }
6084 if (max_retries >= 5) {
6085 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05306086#ifdef WLAN_OPEN_SOURCE
6087 wake_lock_destroy(&wlan_wake_lock);
6088#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006089 return -ENODEV;
6090 }
6091#endif
6092
Jeff Johnson295189b2012-06-20 16:38:30 -07006093 dev = wcnss_wlan_get_device();
6094#endif // ANI_BUS_TYPE_PLATFORM
6095
6096
6097 do {
6098 if (NULL == dev) {
6099 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6100 ret_status = -1;
6101 break;
6102 }
6103
6104#ifdef MEMORY_DEBUG
6105 vos_mem_init();
6106#endif
6107
6108#ifdef TIMER_MANAGER
6109 vos_timer_manager_init();
6110#endif
6111
6112 /* Preopen VOSS so that it is ready to start at least SAL */
6113 status = vos_preOpen(&pVosContext);
6114
6115 if (!VOS_IS_STATUS_SUCCESS(status))
6116 {
6117 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6118 ret_status = -1;
6119 break;
6120 }
6121
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006122#ifndef MODULE
6123 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6124 */
6125 hdd_set_conparam((v_UINT_t)con_mode);
6126#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006127
6128 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006129 if (hdd_wlan_startup(dev))
6130 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006131 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006132 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006133 vos_preClose( &pVosContext );
6134 ret_status = -1;
6135 break;
6136 }
6137
6138 /* Cancel the vote for XO Core ON
6139 * This is done here for safety purposes in case we re-initialize without turning
6140 * it OFF in any error scenario.
6141 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006142 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006143 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006144 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006145 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6146 {
6147 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6148 " Power consumed will be high\n");
6149 }
6150 } while (0);
6151
6152 if (0 != ret_status)
6153 {
6154 //Assert Deep sleep signal now to put Libra HW in lowest power state
6155 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6156 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6157
6158 //Vote off any PMIC voltage supplies
6159 vos_chipPowerDown(NULL, NULL, NULL);
6160#ifdef TIMER_MANAGER
6161 vos_timer_exit();
6162#endif
6163#ifdef MEMORY_DEBUG
6164 vos_mem_exit();
6165#endif
6166
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006167#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006168 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006169#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006170 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6171 }
6172 else
6173 {
6174 //Send WLAN UP indication to Nlink Service
6175 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6176
6177 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07006178 }
6179
6180 EXIT();
6181
6182 return ret_status;
6183}
6184
Jeff Johnson32d95a32012-09-10 13:15:23 -07006185/**---------------------------------------------------------------------------
6186
6187 \brief hdd_module_init() - Init Function
6188
6189 This is the driver entry point (invoked when module is loaded using insmod)
6190
6191 \param - None
6192
6193 \return - 0 for success, non zero for failure
6194
6195 --------------------------------------------------------------------------*/
6196#ifdef MODULE
6197static int __init hdd_module_init ( void)
6198{
6199 return hdd_driver_init();
6200}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006201#else /* #ifdef MODULE */
6202static int __init hdd_module_init ( void)
6203{
6204 /* Driver initialization is delayed to fwpath_changed_handler */
6205 return 0;
6206}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006207#endif /* #ifdef MODULE */
6208
Jeff Johnson295189b2012-06-20 16:38:30 -07006209
6210/**---------------------------------------------------------------------------
6211
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006212 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006213
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006214 This is the driver exit point (invoked when module is unloaded using rmmod
6215 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006216
6217 \param - None
6218
6219 \return - None
6220
6221 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006222static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006223{
6224 hdd_context_t *pHddCtx = NULL;
6225 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006226 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006227
6228 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6229
6230 //Get the global vos context
6231 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6232
6233 if(!pVosContext)
6234 {
6235 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6236 goto done;
6237 }
6238
6239 //Get the HDD context.
6240 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6241
6242 if(!pHddCtx)
6243 {
6244 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6245 }
6246 else
6247 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006248 while(isWDresetInProgress()) {
6249 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6250 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006251 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006252
6253 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6254 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6255 "%s:SSR never completed, fatal error", __func__);
6256 VOS_BUG(0);
6257 }
6258 }
6259
Jeff Johnson295189b2012-06-20 16:38:30 -07006260
6261 pHddCtx->isLoadUnloadInProgress = TRUE;
6262 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6263
6264 //Do all the cleanup before deregistering the driver
6265 hdd_wlan_exit(pHddCtx);
6266 }
6267
Jeff Johnson295189b2012-06-20 16:38:30 -07006268 vos_preClose( &pVosContext );
6269
6270#ifdef TIMER_MANAGER
6271 vos_timer_exit();
6272#endif
6273#ifdef MEMORY_DEBUG
6274 vos_mem_exit();
6275#endif
6276
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306277#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6278 vos_wconn_trace_exit();
6279#endif
6280
Jeff Johnson295189b2012-06-20 16:38:30 -07006281done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006282#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006283 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006284#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006285 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6286}
6287
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006288/**---------------------------------------------------------------------------
6289
6290 \brief hdd_module_exit() - Exit function
6291
6292 This is the driver exit point (invoked when module is unloaded using rmmod)
6293
6294 \param - None
6295
6296 \return - None
6297
6298 --------------------------------------------------------------------------*/
6299static void __exit hdd_module_exit(void)
6300{
6301 hdd_driver_exit();
6302}
6303
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006304#ifdef MODULE
6305static int fwpath_changed_handler(const char *kmessage,
6306 struct kernel_param *kp)
6307{
Jeff Johnson76052702013-04-16 13:55:05 -07006308 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006309}
6310
6311static int con_mode_handler(const char *kmessage,
6312 struct kernel_param *kp)
6313{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006314 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006315}
6316#else /* #ifdef MODULE */
6317/**---------------------------------------------------------------------------
6318
Jeff Johnson76052702013-04-16 13:55:05 -07006319 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006320
Jeff Johnson76052702013-04-16 13:55:05 -07006321 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006322 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006323 - invoked when module parameter fwpath is modified from userspace to signal
6324 initializing the WLAN driver or when con_mode is modified from userspace
6325 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006326
6327 \return - 0 for success, non zero for failure
6328
6329 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006330static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006331{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006332 int ret_status;
6333
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006334 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006335 ret_status = hdd_driver_init();
6336 wlan_hdd_inited = ret_status ? 0 : 1;
6337 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006338 }
6339
6340 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006341
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006342 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006343
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006344 ret_status = hdd_driver_init();
6345 wlan_hdd_inited = ret_status ? 0 : 1;
6346 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006347}
6348
Jeff Johnson295189b2012-06-20 16:38:30 -07006349/**---------------------------------------------------------------------------
6350
Jeff Johnson76052702013-04-16 13:55:05 -07006351 \brief fwpath_changed_handler() - Handler Function
6352
6353 Handle changes to the fwpath parameter
6354
6355 \return - 0 for success, non zero for failure
6356
6357 --------------------------------------------------------------------------*/
6358static int fwpath_changed_handler(const char *kmessage,
6359 struct kernel_param *kp)
6360{
6361 int ret;
6362
6363 ret = param_set_copystring(kmessage, kp);
6364 if (0 == ret)
6365 ret = kickstart_driver();
6366 return ret;
6367}
6368
6369/**---------------------------------------------------------------------------
6370
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006371 \brief con_mode_handler() -
6372
6373 Handler function for module param con_mode when it is changed by userspace
6374 Dynamically linked - do nothing
6375 Statically linked - exit and init driver, as in rmmod and insmod
6376
Jeff Johnson76052702013-04-16 13:55:05 -07006377 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006378
Jeff Johnson76052702013-04-16 13:55:05 -07006379 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006380
6381 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006382static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006383{
Jeff Johnson76052702013-04-16 13:55:05 -07006384 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006385
Jeff Johnson76052702013-04-16 13:55:05 -07006386 ret = param_set_int(kmessage, kp);
6387 if (0 == ret)
6388 ret = kickstart_driver();
6389 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006390}
6391#endif /* #ifdef MODULE */
6392
6393/**---------------------------------------------------------------------------
6394
Jeff Johnson295189b2012-06-20 16:38:30 -07006395 \brief hdd_get_conparam() -
6396
6397 This is the driver exit point (invoked when module is unloaded using rmmod)
6398
6399 \param - None
6400
6401 \return - tVOS_CON_MODE
6402
6403 --------------------------------------------------------------------------*/
6404tVOS_CON_MODE hdd_get_conparam ( void )
6405{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006406#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006407 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006408#else
6409 return (tVOS_CON_MODE)curr_con_mode;
6410#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006411}
6412void hdd_set_conparam ( v_UINT_t newParam )
6413{
6414 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006415#ifndef MODULE
6416 curr_con_mode = con_mode;
6417#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006418}
6419/**---------------------------------------------------------------------------
6420
6421 \brief hdd_softap_sta_deauth() - function
6422
6423 This to take counter measure to handle deauth req from HDD
6424
6425 \param - pAdapter - Pointer to the HDD
6426
6427 \param - enable - boolean value
6428
6429 \return - None
6430
6431 --------------------------------------------------------------------------*/
6432
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006433VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006434{
Jeff Johnson295189b2012-06-20 16:38:30 -07006435 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006436 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006437
6438 ENTER();
6439
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306440 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006441
6442 //Ignore request to deauth bcmc station
6443 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006444 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006445
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006446 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006447
6448 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006449 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006450}
6451
6452/**---------------------------------------------------------------------------
6453
6454 \brief hdd_softap_sta_disassoc() - function
6455
6456 This to take counter measure to handle deauth req from HDD
6457
6458 \param - pAdapter - Pointer to the HDD
6459
6460 \param - enable - boolean value
6461
6462 \return - None
6463
6464 --------------------------------------------------------------------------*/
6465
6466void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6467{
6468 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6469
6470 ENTER();
6471
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306472 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006473
6474 //Ignore request to disassoc bcmc station
6475 if( pDestMacAddress[0] & 0x1 )
6476 return;
6477
6478 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6479}
6480
6481void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6482{
6483 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6484
6485 ENTER();
6486
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306487 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006488
6489 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6490}
6491
Jeff Johnson295189b2012-06-20 16:38:30 -07006492/**---------------------------------------------------------------------------
6493 *
6494 * \brief hdd_get__concurrency_mode() -
6495 *
6496 *
6497 * \param - None
6498 *
6499 * \return - CONCURRENCY MODE
6500 *
6501 * --------------------------------------------------------------------------*/
6502tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6503{
6504 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6505 hdd_context_t *pHddCtx;
6506
6507 if (NULL != pVosContext)
6508 {
6509 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6510 if (NULL != pHddCtx)
6511 {
6512 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6513 }
6514 }
6515
6516 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006517 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006518 return VOS_STA;
6519}
6520
6521/* Decide whether to allow/not the apps power collapse.
6522 * Allow apps power collapse if we are in connected state.
6523 * if not, allow only if we are in IMPS */
6524v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6525{
6526 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006527 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006528 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006529 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6530 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6531 hdd_adapter_t *pAdapter = NULL;
6532 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006533 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006534
Jeff Johnson295189b2012-06-20 16:38:30 -07006535 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6536 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006537
Yathish9f22e662012-12-10 14:21:35 -08006538 concurrent_state = hdd_get_concurrency_mode();
6539
6540#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6541 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6542 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6543 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6544 return TRUE;
6545#endif
6546
Jeff Johnson295189b2012-06-20 16:38:30 -07006547 /*loop through all adapters. TBD fix for Concurrency */
6548 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6549 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6550 {
6551 pAdapter = pAdapterNode->pAdapter;
6552 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6553 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6554 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006555 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006556 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006557 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006558 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6559 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006560 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006561 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006562 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6563 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006564 return FALSE;
6565 }
6566 }
6567 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6568 pAdapterNode = pNext;
6569 }
6570 return TRUE;
6571}
6572
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006573/* Decides whether to send suspend notification to Riva
6574 * if any adapter is in BMPS; then it is required */
6575v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6576{
6577 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6578 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6579
6580 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6581 {
6582 return TRUE;
6583 }
6584 return FALSE;
6585}
6586
Jeff Johnson295189b2012-06-20 16:38:30 -07006587void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6588{
6589 switch(mode)
6590 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006591 case VOS_STA_MODE:
6592 case VOS_P2P_CLIENT_MODE:
6593 case VOS_P2P_GO_MODE:
6594 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006595 pHddCtx->concurrency_mode |= (1 << mode);
6596 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006597 break;
6598 default:
6599 break;
6600
6601 }
6602 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6603 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6604}
6605
6606
6607void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6608{
6609 switch(mode)
6610 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006611 case VOS_STA_MODE:
6612 case VOS_P2P_CLIENT_MODE:
6613 case VOS_P2P_GO_MODE:
6614 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006615 pHddCtx->no_of_sessions[mode]--;
6616 if (!(pHddCtx->no_of_sessions[mode]))
6617 pHddCtx->concurrency_mode &= (~(1 << mode));
6618 break;
6619 default:
6620 break;
6621 }
6622 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6623 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6624}
6625
Jeff Johnsone7245742012-09-05 17:12:55 -07006626/**---------------------------------------------------------------------------
6627 *
6628 * \brief wlan_hdd_restart_init
6629 *
6630 * This function initalizes restart timer/flag. An internal function.
6631 *
6632 * \param - pHddCtx
6633 *
6634 * \return - None
6635 *
6636 * --------------------------------------------------------------------------*/
6637
6638static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6639{
6640 /* Initialize */
6641 pHddCtx->hdd_restart_retries = 0;
6642 atomic_set(&pHddCtx->isRestartInProgress, 0);
6643 vos_timer_init(&pHddCtx->hdd_restart_timer,
6644 VOS_TIMER_TYPE_SW,
6645 wlan_hdd_restart_timer_cb,
6646 pHddCtx);
6647}
6648/**---------------------------------------------------------------------------
6649 *
6650 * \brief wlan_hdd_restart_deinit
6651 *
6652 * This function cleans up the resources used. An internal function.
6653 *
6654 * \param - pHddCtx
6655 *
6656 * \return - None
6657 *
6658 * --------------------------------------------------------------------------*/
6659
6660static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6661{
6662
6663 VOS_STATUS vos_status;
6664 /* Block any further calls */
6665 atomic_set(&pHddCtx->isRestartInProgress, 1);
6666 /* Cleanup */
6667 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6668 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006669 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006670 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6671 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006672 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006673
6674}
6675
6676/**---------------------------------------------------------------------------
6677 *
6678 * \brief wlan_hdd_framework_restart
6679 *
6680 * This function uses a cfg80211 API to start a framework initiated WLAN
6681 * driver module unload/load.
6682 *
6683 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6684 *
6685 *
6686 * \param - pHddCtx
6687 *
6688 * \return - VOS_STATUS_SUCCESS: Success
6689 * VOS_STATUS_E_EMPTY: Adapter is Empty
6690 * VOS_STATUS_E_NOMEM: No memory
6691
6692 * --------------------------------------------------------------------------*/
6693
6694static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6695{
6696 VOS_STATUS status = VOS_STATUS_SUCCESS;
6697 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006698 int len = (sizeof (struct ieee80211_mgmt));
6699 struct ieee80211_mgmt *mgmt = NULL;
6700
6701 /* Prepare the DEAUTH managment frame with reason code */
6702 mgmt = kzalloc(len, GFP_KERNEL);
6703 if(mgmt == NULL)
6704 {
6705 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6706 "%s: memory allocation failed (%d bytes)", __func__, len);
6707 return VOS_STATUS_E_NOMEM;
6708 }
6709 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006710
6711 /* Iterate over all adapters/devices */
6712 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6713 do
6714 {
6715 if( (status == VOS_STATUS_SUCCESS) &&
6716 pAdapterNode &&
6717 pAdapterNode->pAdapter)
6718 {
6719 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6720 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6721 pAdapterNode->pAdapter->dev->name,
6722 pAdapterNode->pAdapter->device_mode,
6723 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006724 /*
6725 * CFG80211 event to restart the driver
6726 *
6727 * 'cfg80211_send_unprot_deauth' sends a
6728 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6729 * of SME(Linux Kernel) state machine.
6730 *
6731 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6732 * the driver.
6733 *
6734 */
6735
6736 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006737 }
6738 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6739 pAdapterNode = pNext;
6740 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6741
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006742
6743 /* Free the allocated management frame */
6744 kfree(mgmt);
6745
Jeff Johnsone7245742012-09-05 17:12:55 -07006746 /* Retry until we unload or reach max count */
6747 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6748 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6749
6750 return status;
6751
6752}
6753/**---------------------------------------------------------------------------
6754 *
6755 * \brief wlan_hdd_restart_timer_cb
6756 *
6757 * Restart timer callback. An internal function.
6758 *
6759 * \param - User data:
6760 *
6761 * \return - None
6762 *
6763 * --------------------------------------------------------------------------*/
6764
6765void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6766{
6767 hdd_context_t *pHddCtx = usrDataForCallback;
6768 wlan_hdd_framework_restart(pHddCtx);
6769 return;
6770
6771}
6772
6773
6774/**---------------------------------------------------------------------------
6775 *
6776 * \brief wlan_hdd_restart_driver
6777 *
6778 * This function sends an event to supplicant to restart the WLAN driver.
6779 *
6780 * This function is called from vos_wlanRestart.
6781 *
6782 * \param - pHddCtx
6783 *
6784 * \return - VOS_STATUS_SUCCESS: Success
6785 * VOS_STATUS_E_EMPTY: Adapter is Empty
6786 * VOS_STATUS_E_ALREADY: Request already in progress
6787
6788 * --------------------------------------------------------------------------*/
6789VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6790{
6791 VOS_STATUS status = VOS_STATUS_SUCCESS;
6792
6793 /* A tight check to make sure reentrancy */
6794 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6795 {
6796 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6797 "%s: WLAN restart is already in progress", __func__);
6798
6799 return VOS_STATUS_E_ALREADY;
6800 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006801 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006802#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006803 wcnss_reset_intr();
6804#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006805
Jeff Johnsone7245742012-09-05 17:12:55 -07006806 return status;
6807}
6808
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006809/*
6810 * API to find if there is any STA or P2P-Client is connected
6811 */
6812VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6813{
6814 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6815}
Jeff Johnsone7245742012-09-05 17:12:55 -07006816
Jeff Johnson295189b2012-06-20 16:38:30 -07006817//Register the module init/exit functions
6818module_init(hdd_module_init);
6819module_exit(hdd_module_exit);
6820
6821MODULE_LICENSE("Dual BSD/GPL");
6822MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6823MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6824
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006825module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6826 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006827
Jeff Johnson76052702013-04-16 13:55:05 -07006828module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006829 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);