blob: a561f1b00298178fc55e77d779cd7bae1a6af3af [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;
733 int rssi = 0;
734 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
740 sscanf(value, "%d", &rssi);
741 lookUpThreshold = abs(rssi);
742 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
743 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
744 {
745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
746 "Neighbor lookup threshold value %d is out of range"
747 " (Min: %d Max: %d)", lookUpThreshold,
748 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
749 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
750 ret = -EINVAL;
751 goto exit;
752 }
753
754 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
755 "%s: Received Command to Set Roam trigger"
756 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
757
758 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
759 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
760 if (eHAL_STATUS_SUCCESS != status)
761 {
762 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
763 "%s: Failed to set roam trigger, try again", __func__);
764 ret = -EPERM;
765 goto exit;
766 }
767
768 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
769 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
770 }
771 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
772 {
773 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
774 int rssi = (-1) * lookUpThreshold;
775 char extra[32];
776 tANI_U8 len = 0;
777
778 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
779 if (copy_to_user(priv_data.buf, &extra, len + 1))
780 {
781 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
782 "%s: failed to copy data to user buffer", __func__);
783 ret = -EFAULT;
784 goto exit;
785 }
786 }
787 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
788 {
789 tANI_U8 *value = command;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700790 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800791 /* input refresh period is in terms of seconds */
792 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
793 value = value + 18;
794 /* Convert the value from ascii to integer */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700795 ret = kstrtou16(value, 10, &neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800796 if (ret < 0)
797 {
798 /* If the input value is greater than max value of datatype, then also
799 kstrtou16 fails */
800 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
801 "%s: kstrtou16 failed ",
802 "Input value may be out of range[%d - %d]",
803 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700804 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
805 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800806 ret = -EINVAL;
807 goto exit;
808 }
809
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700810 neighborEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod * 1000;
811 if ((neighborEmptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
812 (neighborEmptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800813 {
814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700815 "Neighbor empty scan results refresh period value %d is out of range"
816 " (Min: %d Max: %d)", neighborEmptyScanRefreshPeriod/1000,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700817 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
818 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800819 ret = -EINVAL;
820 goto exit;
821 }
822
823 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
824 "%s: Received Command to Set roam scan period"
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700825 " (Empty Scan refresh period) = %d", __func__, neighborEmptyScanRefreshPeriod/1000);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800826
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700827 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
828 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800829 }
830 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
831 {
832 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
833 char extra[32];
834 tANI_U8 len = 0;
835
836 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
837 /* Returned value is in units of seconds */
838 if (copy_to_user(priv_data.buf, &extra, len + 1))
839 {
840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
841 "%s: failed to copy data to user buffer", __func__);
842 ret = -EFAULT;
843 goto exit;
844 }
845 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700846 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
847 {
848 tANI_U8 *value = command;
849 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
850 /* input refresh period is in terms of seconds */
851 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
852 value = value + 25;
853 /* Convert the value from ascii to integer */
854 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
855 if (ret < 0)
856 {
857 /* If the input value is greater than max value of datatype, then also
858 kstrtou16 fails */
859 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
860 "%s: kstrtou16 failed ",
861 "Input value may be out of range[%d - %d]",
862 __func__,
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700863 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
864 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700865 ret = -EINVAL;
866 goto exit;
867 }
868
869 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700870 if ((neighborScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
871 (neighborScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700872 {
873 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
874 "Neighbor scan results refresh period value %d is out of range"
875 " (Min: %d Max: %d)", neighborScanRefreshPeriod/1000,
876 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
877 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
878 ret = -EINVAL;
879 goto exit;
880 }
881
882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
883 "%s: Received Command to Set roam scan refresh period"
884 " (Scan refresh period) = %d", __func__, neighborScanRefreshPeriod/1000);
885
886 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
887 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
888 }
889 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
890 {
891 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
892 char extra[32];
893 tANI_U8 len = 0;
894
895 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
896 /* Returned value is in units of seconds */
897 if (copy_to_user(priv_data.buf, &extra, len + 1))
898 {
899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
900 "%s: failed to copy data to user buffer", __func__);
901 ret = -EFAULT;
902 goto exit;
903 }
904 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700905#ifdef FEATURE_WLAN_LFR
906 /* SETROAMMODE */
907 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
908 {
909 tANI_U8 *value = command;
910 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
911
912 /* Move pointer to ahead of SETROAMMODE<delimiter> */
913 value = value + SIZE_OF_SETROAMMODE + 1;
914
915 /* Convert the value from ascii to integer */
916 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
917 if (ret < 0)
918 {
919 /* If the input value is greater than max value of datatype, then also
920 kstrtou8 fails */
921 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
922 "%s: kstrtou8 failed range [%d - %d]", __func__,
923 CFG_LFR_FEATURE_ENABLED_MIN,
924 CFG_LFR_FEATURE_ENABLED_MAX);
925 ret = -EINVAL;
926 goto exit;
927 }
928 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
929 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
930 {
931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
932 "Roam Mode value %d is out of range"
933 " (Min: %d Max: %d)", roamMode,
934 CFG_LFR_FEATURE_ENABLED_MIN,
935 CFG_LFR_FEATURE_ENABLED_MAX);
936 ret = -EINVAL;
937 goto exit;
938 }
939
940 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
941 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
942 /*
943 * Note that
944 * SETROAMMODE 0 is to enable LFR while
945 * SETROAMMODE 1 is to disable LFR, but
946 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
947 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
948 */
949 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
950 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
951 else
952 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
953
954 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
955 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
956 }
957 /* GETROAMMODE */
958 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
959 {
960 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
961 char extra[32];
962 tANI_U8 len = 0;
963
964 /*
965 * roamMode value shall be inverted because the sementics is different.
966 */
967 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
968 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
969 else
970 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
971
972 len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode);
973 if (copy_to_user(priv_data.buf, &extra, len + 1))
974 {
975 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
976 "%s: failed to copy data to user buffer", __func__);
977 ret = -EFAULT;
978 goto exit;
979 }
980 }
981#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -0800982#endif
983#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
984 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
985 {
986 tANI_U8 *value = command;
987 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
988
989 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
990 value = value + 13;
991 /* Convert the value from ascii to integer */
992 ret = kstrtou8(value, 10, &roamRssiDiff);
993 if (ret < 0)
994 {
995 /* If the input value is greater than max value of datatype, then also
996 kstrtou8 fails */
997 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
998 "%s: kstrtou8 failed range [%d - %d]", __func__,
999 CFG_ROAM_RSSI_DIFF_MIN,
1000 CFG_ROAM_RSSI_DIFF_MAX);
1001 ret = -EINVAL;
1002 goto exit;
1003 }
1004
1005 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1006 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1007 {
1008 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1009 "Roam rssi diff value %d is out of range"
1010 " (Min: %d Max: %d)", roamRssiDiff,
1011 CFG_ROAM_RSSI_DIFF_MIN,
1012 CFG_ROAM_RSSI_DIFF_MAX);
1013 ret = -EINVAL;
1014 goto exit;
1015 }
1016
1017 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1018 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1019
1020 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1021 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1022 }
1023 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1024 {
1025 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1026 char extra[32];
1027 tANI_U8 len = 0;
1028
1029 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
1030 if (copy_to_user(priv_data.buf, &extra, len + 1))
1031 {
1032 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1033 "%s: failed to copy data to user buffer", __func__);
1034 ret = -EFAULT;
1035 goto exit;
1036 }
1037 }
1038#endif
1039#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1040 else if (strncmp(command, "GETBAND", 7) == 0)
1041 {
1042 int band = -1;
1043 char extra[32];
1044 tANI_U8 len = 0;
1045 hdd_getBand_helper(pHddCtx, &band);
1046
1047 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
1048 if (copy_to_user(priv_data.buf, &extra, len + 1))
1049 {
1050 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1051 "%s: failed to copy data to user buffer", __func__);
1052 ret = -EFAULT;
1053 goto exit;
1054 }
1055 }
1056 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
1057 {
1058 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
1059 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
1060 tANI_U8 revision = 0;
1061 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
1062 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
1063 char extra[32] = {0};
1064 tANI_U8 len = 0;
1065
1066 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
1067 {
1068 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1069 "%s: failed to get country code", __func__);
1070 ret = -EFAULT;
1071 goto exit;
1072 }
1073 pBuf[uBufLen] = '\0';
1074 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
1075
1076 if (0 == strncmp(pBuf, "KR", 2))
1077 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
1078 else
1079 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
1080
1081 if (copy_to_user(priv_data.buf, &extra, len + 1))
1082 {
1083 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1084 "%s: failed to copy data to user buffer", __func__);
1085 ret = -EFAULT;
1086 goto exit;
1087 }
1088 }
1089 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1090 {
1091 tANI_U8 *value = command;
1092 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1093 tANI_U8 numChannels = 0;
1094 eHalStatus status = eHAL_STATUS_SUCCESS;
1095
1096 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1097 if (eHAL_STATUS_SUCCESS != status)
1098 {
1099 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1100 "%s: Failed to parse channel list information", __func__);
1101 ret = -EINVAL;
1102 goto exit;
1103 }
1104
1105 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1106 {
1107 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1108 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1109 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1110 ret = -EINVAL;
1111 goto exit;
1112 }
1113 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1114 numChannels);
1115 if (eHAL_STATUS_SUCCESS != status)
1116 {
1117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1118 "%s: Failed to update channel list information", __func__);
1119 ret = -EINVAL;
1120 goto exit;
1121 }
1122 }
1123 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1124 {
1125 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1126 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001127 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001128 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001129 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001130
1131 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1132 ChannelList, &numChannels ))
1133 {
1134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1135 "%s: failed to get roam scan channel list", __func__);
1136 ret = -EFAULT;
1137 goto exit;
1138 }
1139 /* output channel list is of the format
1140 [Number of roam scan channels][Channel1][Channel2]... */
1141 /* copy the number of channels in the 0th index */
1142 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1143 for (j = 0; (j < numChannels); j++)
1144 {
1145 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1146 }
1147
1148 if (copy_to_user(priv_data.buf, &extra, len + 1))
1149 {
1150 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1151 "%s: failed to copy data to user buffer", __func__);
1152 ret = -EFAULT;
1153 goto exit;
1154 }
1155 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001156 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1157 {
1158 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1159 char extra[32];
1160 tANI_U8 len = 0;
1161
1162 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1163 if (copy_to_user(priv_data.buf, &extra, len + 1))
1164 {
1165 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1166 "%s: failed to copy data to user buffer", __func__);
1167 ret = -EFAULT;
1168 goto exit;
1169 }
1170 }
1171 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1172 {
1173 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1174 char extra[32];
1175 tANI_U8 len = 0;
1176
1177 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1178 if (copy_to_user(priv_data.buf, &extra, len + 1))
1179 {
1180 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1181 "%s: failed to copy data to user buffer", __func__);
1182 ret = -EFAULT;
1183 goto exit;
1184 }
1185 }
1186 else if (strncmp(command, "GETFASTROAM", 10) == 0)
1187 {
1188 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1189 char extra[32];
1190 tANI_U8 len = 0;
1191
1192 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
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, "GETFASTTRANSITION", 17) == 0)
1202 {
1203 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1204 char extra[32];
1205 tANI_U8 len = 0;
1206
1207 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1208 if (copy_to_user(priv_data.buf, &extra, len + 1))
1209 {
1210 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1211 "%s: failed to copy data to user buffer", __func__);
1212 ret = -EFAULT;
1213 goto exit;
1214 }
1215 }
1216 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1217 {
1218 tANI_U8 *value = command;
1219 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1220
1221 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1222 value = value + 26;
1223 /* Convert the value from ascii to integer */
1224 ret = kstrtou8(value, 10, &minTime);
1225 if (ret < 0)
1226 {
1227 /* If the input value is greater than max value of datatype, then also
1228 kstrtou8 fails */
1229 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1230 "%s: kstrtou8 failed range [%d - %d]", __func__,
1231 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1232 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1233 ret = -EINVAL;
1234 goto exit;
1235 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001236 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1237 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1238 {
1239 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1240 "scan min channel time value %d is out of range"
1241 " (Min: %d Max: %d)", minTime,
1242 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1243 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1244 ret = -EINVAL;
1245 goto exit;
1246 }
1247
1248 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1249 "%s: Received Command to change channel min time = %d", __func__, minTime);
1250
1251 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1252 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1253 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001254 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1255 {
1256 tANI_U8 *value = command;
1257 tANI_U8 channel = 0;
1258 tANI_U8 dwellTime = 0;
1259 tANI_U8 bufLen = 0;
1260 tANI_U8 *buf = NULL;
1261 tSirMacAddr targetApBssid;
1262 eHalStatus status = eHAL_STATUS_SUCCESS;
1263 struct ieee80211_channel chan;
1264 tANI_U8 finalLen = 0;
1265 tANI_U8 *finalBuf = NULL;
1266 tANI_U8 temp = 0;
1267 u64 cookie;
1268 hdd_station_ctx_t *pHddStaCtx = NULL;
1269 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1270
1271 /* if not associated, no need to send action frame */
1272 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1273 {
1274 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1275 ret = -EINVAL;
1276 goto exit;
1277 }
1278
1279 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1280 &dwellTime, &buf, &bufLen);
1281 if (eHAL_STATUS_SUCCESS != status)
1282 {
1283 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1284 "%s: Failed to parse send action frame data", __func__);
1285 ret = -EINVAL;
1286 goto exit;
1287 }
1288
1289 /* if the target bssid is different from currently associated AP,
1290 then no need to send action frame */
1291 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1292 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1293 {
1294 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1295 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001296 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001297 goto exit;
1298 }
1299
1300 /* if the channel number is different from operating channel then
1301 no need to send action frame */
1302 if (channel != pHddStaCtx->conn_info.operationChannel)
1303 {
1304 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1305 "%s: channel(%d) is different from operating channel(%d)",
1306 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1307 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001308 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001309 goto exit;
1310 }
1311 chan.center_freq = sme_ChnToFreq(channel);
1312
1313 finalLen = bufLen + 24;
1314 finalBuf = vos_mem_malloc(finalLen);
1315 if (NULL == finalBuf)
1316 {
1317 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1318 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001319 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001320 goto exit;
1321 }
1322 vos_mem_zero(finalBuf, finalLen);
1323
1324 /* Fill subtype */
1325 temp = SIR_MAC_MGMT_ACTION << 4;
1326 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1327
1328 /* Fill type */
1329 temp = SIR_MAC_MGMT_FRAME;
1330 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1331
1332 /* Fill destination address (bssid of the AP) */
1333 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1334
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001335 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001336 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1337
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001338 /* Fill BSSID (AP mac address) */
1339 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001340
1341 /* Fill received buffer from 24th address */
1342 vos_mem_copy(finalBuf + 24, buf, bufLen);
1343
Jeff Johnson11c33152013-04-16 17:52:40 -07001344 /* done with the parsed buffer */
1345 vos_mem_free(buf);
1346
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001347 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1348 1, dwellTime, finalBuf, finalLen, 1,
1349 1, &cookie );
1350 vos_mem_free(finalBuf);
1351 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001352 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1353 {
1354 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1355 char extra[32];
1356 tANI_U8 len = 0;
1357
1358 /* value is interms of msec */
1359 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1360 if (copy_to_user(priv_data.buf, &extra, len + 1))
1361 {
1362 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1363 "%s: failed to copy data to user buffer", __func__);
1364 ret = -EFAULT;
1365 goto exit;
1366 }
1367 }
1368 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1369 {
1370 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001371 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001372 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001373
1374 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1375 value = value + 19;
1376 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001377 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001378 if (ret < 0)
1379 {
1380 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001381 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001382 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001383 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001384 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1385 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1386 ret = -EINVAL;
1387 goto exit;
1388 }
1389
1390 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1391 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1392 {
1393 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1394 "lfr mode value %d is out of range"
1395 " (Min: %d Max: %d)", maxTime,
1396 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1397 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1398 ret = -EINVAL;
1399 goto exit;
1400 }
1401
1402 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1403 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1404
1405 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001406
1407 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1408 * where RFS is the RF Switching time. It is twice RFS to consider the
1409 * time to go off channel and return to the home channel. */
1410 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1411 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1412 {
1413 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1414 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1415 " Hence enforcing home away time to disable (0)",
1416 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1417 homeAwayTime = 0;
1418 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1419 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
1420 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001421 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1422 }
1423 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1424 {
1425 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1426 char extra[32];
1427 tANI_U8 len = 0;
1428
1429 /* value is interms of msec */
1430 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1431 if (copy_to_user(priv_data.buf, &extra, len + 1))
1432 {
1433 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1434 "%s: failed to copy data to user buffer", __func__);
1435 ret = -EFAULT;
1436 goto exit;
1437 }
1438 }
1439 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1440 {
1441 tANI_U8 *value = command;
1442 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1443
1444 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1445 value = value + 16;
1446 /* Convert the value from ascii to integer */
1447 ret = kstrtou16(value, 10, &val);
1448 if (ret < 0)
1449 {
1450 /* If the input value is greater than max value of datatype, then also
1451 kstrtou16 fails */
1452 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1453 "%s: kstrtou16 failed range [%d - %d]", __func__,
1454 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1455 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1456 ret = -EINVAL;
1457 goto exit;
1458 }
1459
1460 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1461 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1462 {
1463 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1464 "scan home time value %d is out of range"
1465 " (Min: %d Max: %d)", val,
1466 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1467 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1468 ret = -EINVAL;
1469 goto exit;
1470 }
1471
1472 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1473 "%s: Received Command to change scan home time = %d", __func__, val);
1474
1475 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1476 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1477 }
1478 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1479 {
1480 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1481 char extra[32];
1482 tANI_U8 len = 0;
1483
1484 /* value is interms of msec */
1485 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1486 if (copy_to_user(priv_data.buf, &extra, len + 1))
1487 {
1488 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1489 "%s: failed to copy data to user buffer", __func__);
1490 ret = -EFAULT;
1491 goto exit;
1492 }
1493 }
1494 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1495 {
1496 tANI_U8 *value = command;
1497 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1498
1499 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1500 value = value + 17;
1501 /* Convert the value from ascii to integer */
1502 ret = kstrtou8(value, 10, &val);
1503 if (ret < 0)
1504 {
1505 /* If the input value is greater than max value of datatype, then also
1506 kstrtou8 fails */
1507 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1508 "%s: kstrtou8 failed range [%d - %d]", __func__,
1509 CFG_ROAM_INTRA_BAND_MIN,
1510 CFG_ROAM_INTRA_BAND_MAX);
1511 ret = -EINVAL;
1512 goto exit;
1513 }
1514
1515 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1516 (val > CFG_ROAM_INTRA_BAND_MAX))
1517 {
1518 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1519 "intra band mode value %d is out of range"
1520 " (Min: %d Max: %d)", val,
1521 CFG_ROAM_INTRA_BAND_MIN,
1522 CFG_ROAM_INTRA_BAND_MAX);
1523 ret = -EINVAL;
1524 goto exit;
1525 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001526 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1527 "%s: Received Command to change intra band = %d", __func__, val);
1528
1529 pHddCtx->cfg_ini->nRoamIntraBand = val;
1530 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1531 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001532 else if (strncmp(command, "SETWESMODE", 10) == 0)
1533 {
1534 tANI_U8 *value = command;
1535 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
1536
1537 /* Move pointer to ahead of SETWESMODE<delimiter> */
1538 value = value + 11;
1539 /* Convert the value from ascii to integer */
1540 ret = kstrtou8(value, 10, &wesMode);
1541 if (ret < 0)
1542 {
1543 /* If the input value is greater than max value of datatype, then also
1544 kstrtou8 fails */
1545 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1546 "%s: kstrtou8 failed range [%d - %d]", __func__,
1547 CFG_ENABLE_WES_MODE_NAME_MIN,
1548 CFG_ENABLE_WES_MODE_NAME_MAX);
1549 ret = -EINVAL;
1550 goto exit;
1551 }
1552
1553 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
1554 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
1555 {
1556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1557 "WES Mode value %d is out of range"
1558 " (Min: %d Max: %d)", wesMode,
1559 CFG_ENABLE_WES_MODE_NAME_MIN,
1560 CFG_ENABLE_WES_MODE_NAME_MAX);
1561 ret = -EINVAL;
1562 goto exit;
1563 }
1564 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1565 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
1566
1567 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
1568 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
1569 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001570 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1571 {
1572 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1573 char extra[32];
1574 tANI_U8 len = 0;
1575
1576 /* value is interms of msec */
1577 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1578 if (copy_to_user(priv_data.buf, &extra, len + 1))
1579 {
1580 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1581 "%s: failed to copy data to user buffer", __func__);
1582 ret = -EFAULT;
1583 goto exit;
1584 }
1585 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001586 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
1587 {
1588 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1589 char extra[32];
1590 tANI_U8 len = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001591
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001592 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
1593 if (copy_to_user(priv_data.buf, &extra, len + 1))
1594 {
1595 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1596 "%s: failed to copy data to user buffer", __func__);
1597 ret = -EFAULT;
1598 goto exit;
1599 }
1600 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001601 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1602 {
1603 tANI_U8 *value = command;
1604 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1605
1606 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1607 value = value + 15;
1608 /* Convert the value from ascii to integer */
1609 ret = kstrtou8(value, 10, &nProbes);
1610 if (ret < 0)
1611 {
1612 /* If the input value is greater than max value of datatype, then also
1613 kstrtou8 fails */
1614 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1615 "%s: kstrtou8 failed range [%d - %d]", __func__,
1616 CFG_ROAM_SCAN_N_PROBES_MIN,
1617 CFG_ROAM_SCAN_N_PROBES_MAX);
1618 ret = -EINVAL;
1619 goto exit;
1620 }
1621
1622 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1623 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1624 {
1625 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1626 "NProbes value %d is out of range"
1627 " (Min: %d Max: %d)", nProbes,
1628 CFG_ROAM_SCAN_N_PROBES_MIN,
1629 CFG_ROAM_SCAN_N_PROBES_MAX);
1630 ret = -EINVAL;
1631 goto exit;
1632 }
1633
1634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1635 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1636
1637 pHddCtx->cfg_ini->nProbes = nProbes;
1638 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1639 }
1640 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1641 {
1642 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1643 char extra[32];
1644 tANI_U8 len = 0;
1645
1646 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1647 if (copy_to_user(priv_data.buf, &extra, len + 1))
1648 {
1649 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1650 "%s: failed to copy data to user buffer", __func__);
1651 ret = -EFAULT;
1652 goto exit;
1653 }
1654 }
1655 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1656 {
1657 tANI_U8 *value = command;
1658 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001659 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001660
1661 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1662 /* input value is in units of msec */
1663 value = value + 20;
1664 /* Convert the value from ascii to integer */
1665 ret = kstrtou16(value, 10, &homeAwayTime);
1666 if (ret < 0)
1667 {
1668 /* If the input value is greater than max value of datatype, then also
1669 kstrtou8 fails */
1670 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1671 "%s: kstrtou8 failed range [%d - %d]", __func__,
1672 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1673 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1674 ret = -EINVAL;
1675 goto exit;
1676 }
1677
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001678 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1679 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1680 {
1681 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1682 "homeAwayTime value %d is out of range"
1683 " (Min: %d Max: %d)", homeAwayTime,
1684 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1685 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1686 ret = -EINVAL;
1687 goto exit;
1688 }
1689
1690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1691 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1692
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001693 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1694 * where RFS is the RF Switching time. It is twice RFS to consider the
1695 * time to go off channel and return to the home channel. */
1696 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1697 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1698 {
1699 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1700 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1701 " Hence enforcing home away time to disable (0)",
1702 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1703 homeAwayTime = 0;
1704 }
1705
1706 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
1707 {
1708 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1709 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
1710 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001711 }
1712 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1713 {
1714 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1715 char extra[32];
1716 tANI_U8 len = 0;
1717
1718 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1719 if (copy_to_user(priv_data.buf, &extra, len + 1))
1720 {
1721 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1722 "%s: failed to copy data to user buffer", __func__);
1723 ret = -EFAULT;
1724 goto exit;
1725 }
1726 }
1727 else if (strncmp(command, "REASSOC", 7) == 0)
1728 {
1729 tANI_U8 *value = command;
1730 tANI_U8 channel = 0;
1731 tSirMacAddr targetApBssid;
1732 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001733#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1734 tCsrHandoffRequest handoffInfo;
1735#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001736 hdd_station_ctx_t *pHddStaCtx = NULL;
1737 tANI_BOOLEAN wesMode = eANI_BOOLEAN_FALSE;
1738 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1739
1740 wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1741
1742 /* Reassoc command is allowed only if WES mode is enabled */
1743 if (!wesMode)
1744 {
1745 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:WES Mode is not enabled(%d)",__func__, wesMode);
1746 ret = -EINVAL;
1747 goto exit;
1748 }
1749
1750 /* if not associated, no need to proceed with reassoc */
1751 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1752 {
1753 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1754 ret = -EINVAL;
1755 goto exit;
1756 }
1757
1758 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1759 if (eHAL_STATUS_SUCCESS != status)
1760 {
1761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1762 "%s: Failed to parse reassoc command data", __func__);
1763 ret = -EINVAL;
1764 goto exit;
1765 }
1766
1767 /* if the target bssid is same as currently associated AP,
1768 then no need to proceed with reassoc */
1769 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1770 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1771 {
1772 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1773 ret = -EINVAL;
1774 goto exit;
1775 }
1776
1777 /* Check channel number is a valid channel number */
1778 if(VOS_STATUS_SUCCESS !=
1779 wlan_hdd_validate_operation_channel(pAdapter, channel))
1780 {
1781 hddLog(VOS_TRACE_LEVEL_ERROR,
1782 "%s: Invalid Channel [%d] \n", __func__, channel);
1783 return -EINVAL;
1784 }
1785
1786 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001787#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1788 handoffInfo.channel = channel;
1789 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1790 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1791#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001792 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001793#endif
1794#ifdef FEATURE_WLAN_LFR
1795 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1796 {
1797 tANI_U8 *value = command;
1798 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1799
1800 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1801 value = value + 12;
1802 /* Convert the value from ascii to integer */
1803 ret = kstrtou8(value, 10, &lfrMode);
1804 if (ret < 0)
1805 {
1806 /* If the input value is greater than max value of datatype, then also
1807 kstrtou8 fails */
1808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1809 "%s: kstrtou8 failed range [%d - %d]", __func__,
1810 CFG_LFR_FEATURE_ENABLED_MIN,
1811 CFG_LFR_FEATURE_ENABLED_MAX);
1812 ret = -EINVAL;
1813 goto exit;
1814 }
1815
1816 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1817 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1818 {
1819 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1820 "lfr mode value %d is out of range"
1821 " (Min: %d Max: %d)", lfrMode,
1822 CFG_LFR_FEATURE_ENABLED_MIN,
1823 CFG_LFR_FEATURE_ENABLED_MAX);
1824 ret = -EINVAL;
1825 goto exit;
1826 }
1827
1828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1829 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1830
1831 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1832 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1833 }
1834#endif
1835#ifdef WLAN_FEATURE_VOWIFI_11R
1836 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1837 {
1838 tANI_U8 *value = command;
1839 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1840
1841 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1842 value = value + 18;
1843 /* Convert the value from ascii to integer */
1844 ret = kstrtou8(value, 10, &ft);
1845 if (ret < 0)
1846 {
1847 /* If the input value is greater than max value of datatype, then also
1848 kstrtou8 fails */
1849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1850 "%s: kstrtou8 failed range [%d - %d]", __func__,
1851 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1852 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1853 ret = -EINVAL;
1854 goto exit;
1855 }
1856
1857 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1858 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1859 {
1860 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1861 "ft mode value %d is out of range"
1862 " (Min: %d Max: %d)", ft,
1863 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1864 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1865 ret = -EINVAL;
1866 goto exit;
1867 }
1868
1869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1870 "%s: Received Command to change ft mode = %d", __func__, ft);
1871
1872 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1873 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1874 }
1875#endif
1876#ifdef FEATURE_WLAN_CCX
1877 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1878 {
1879 tANI_U8 *value = command;
1880 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1881
1882 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1883 value = value + 11;
1884 /* Convert the value from ascii to integer */
1885 ret = kstrtou8(value, 10, &ccxMode);
1886 if (ret < 0)
1887 {
1888 /* If the input value is greater than max value of datatype, then also
1889 kstrtou8 fails */
1890 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1891 "%s: kstrtou8 failed range [%d - %d]", __func__,
1892 CFG_CCX_FEATURE_ENABLED_MIN,
1893 CFG_CCX_FEATURE_ENABLED_MAX);
1894 ret = -EINVAL;
1895 goto exit;
1896 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001897 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1898 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1899 {
1900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1901 "Ccx mode value %d is out of range"
1902 " (Min: %d Max: %d)", ccxMode,
1903 CFG_CCX_FEATURE_ENABLED_MIN,
1904 CFG_CCX_FEATURE_ENABLED_MAX);
1905 ret = -EINVAL;
1906 goto exit;
1907 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1909 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1910
1911 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1912 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1913 }
1914#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001915 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1916 {
1917 tANI_U8 *value = command;
1918 tANI_BOOLEAN roamScanControl = 0;
1919
1920 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1921 value = value + 19;
1922 /* Convert the value from ascii to integer */
1923 ret = kstrtou8(value, 10, &roamScanControl);
1924 if (ret < 0)
1925 {
1926 /* If the input value is greater than max value of datatype, then also
1927 kstrtou8 fails */
1928 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1929 "%s: kstrtou8 failed ", __func__);
1930 ret = -EINVAL;
1931 goto exit;
1932 }
1933
1934 if (0 != roamScanControl)
1935 {
1936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1937 "roam scan control invalid value = %d",
1938 roamScanControl);
1939 ret = -EINVAL;
1940 goto exit;
1941 }
1942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1943 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1944
1945 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1946 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001947#ifdef FEATURE_WLAN_OKC
1948 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1949 {
1950 tANI_U8 *value = command;
1951 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1952
1953 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1954 value = value + 11;
1955 /* Convert the value from ascii to integer */
1956 ret = kstrtou8(value, 10, &okcMode);
1957 if (ret < 0)
1958 {
1959 /* If the input value is greater than max value of datatype, then also
1960 kstrtou8 fails */
1961 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1962 "%s: kstrtou8 failed range [%d - %d]", __func__,
1963 CFG_OKC_FEATURE_ENABLED_MIN,
1964 CFG_OKC_FEATURE_ENABLED_MAX);
1965 ret = -EINVAL;
1966 goto exit;
1967 }
1968
1969 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1970 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1971 {
1972 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1973 "Okc mode value %d is out of range"
1974 " (Min: %d Max: %d)", okcMode,
1975 CFG_OKC_FEATURE_ENABLED_MIN,
1976 CFG_OKC_FEATURE_ENABLED_MAX);
1977 ret = -EINVAL;
1978 goto exit;
1979 }
1980
1981 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1982 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1983
1984 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1985 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001986 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1987 {
1988 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1989 char extra[32];
1990 tANI_U8 len = 0;
1991
1992 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1993 if (copy_to_user(priv_data.buf, &extra, len + 1))
1994 {
1995 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1996 "%s: failed to copy data to user buffer", __func__);
1997 ret = -EFAULT;
1998 goto exit;
1999 }
2000 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002001#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05302002#ifdef WLAN_FEATURE_PACKET_FILTERING
2003 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
2004 {
2005 tANI_U8 filterType = 0;
2006 tANI_U8 *value = command;
2007
2008 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
2009 value = value + 22;
2010
2011 /* Convert the value from ascii to integer */
2012 ret = kstrtou8(value, 10, &filterType);
2013 if (ret < 0)
2014 {
2015 /* If the input value is greater than max value of datatype,
2016 * then also kstrtou8 fails
2017 */
2018 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2019 "%s: kstrtou8 failed range ", __func__);
2020 ret = -EINVAL;
2021 goto exit;
2022 }
2023
2024 if (filterType != 0 && filterType != 1)
2025 {
2026 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2027 "%s: Accepted Values are 0 and 1 ", __func__);
2028 ret = -EINVAL;
2029 goto exit;
2030 }
2031 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
2032 pAdapter->sessionId);
2033 }
2034#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002035 else {
2036 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2037 __func__, command);
2038 }
2039
Jeff Johnson295189b2012-06-20 16:38:30 -07002040 }
2041exit:
2042 if (command)
2043 {
2044 kfree(command);
2045 }
2046 return ret;
2047}
2048
Srinivas Girigowdade697412013-02-14 16:31:48 -08002049#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2050void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2051{
2052 eCsrBand band = -1;
2053 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2054 switch (band)
2055 {
2056 case eCSR_BAND_ALL:
2057 *pBand = WLAN_HDD_UI_BAND_AUTO;
2058 break;
2059
2060 case eCSR_BAND_24:
2061 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2062 break;
2063
2064 case eCSR_BAND_5G:
2065 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2066 break;
2067
2068 default:
2069 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2070 *pBand = -1;
2071 break;
2072 }
2073}
2074
2075/**---------------------------------------------------------------------------
2076
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002077 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2078
2079 This function parses the send action frame data passed in the format
2080 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2081
2082 \param - pValue Pointer to input country code revision
2083 \param - pTargetApBssid Pointer to target Ap bssid
2084 \param - pChannel Pointer to the Target AP channel
2085 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2086 \param - pBuf Pointer to data
2087 \param - pBufLen Pointer to data length
2088
2089 \return - 0 for success non-zero for failure
2090
2091 --------------------------------------------------------------------------*/
2092VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2093 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2094{
2095 tANI_U8 *inPtr = pValue;
2096 tANI_U8 *dataEnd;
2097 int tempInt;
2098 int j = 0;
2099 int i = 0;
2100 int v = 0;
2101 tANI_U8 tempBuf[32];
2102 tANI_U8 tempByte = 0;
2103
2104 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2105 /*no argument after the command*/
2106 if (NULL == inPtr)
2107 {
2108 return -EINVAL;
2109 }
2110
2111 /*no space after the command*/
2112 else if (SPACE_ASCII_VALUE != *inPtr)
2113 {
2114 return -EINVAL;
2115 }
2116
2117 /*removing empty spaces*/
2118 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2119
2120 /*no argument followed by spaces*/
2121 if ('\0' == *inPtr)
2122 {
2123 return -EINVAL;
2124 }
2125
2126 /*getting the first argument ie the target AP bssid */
2127 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2128 {
2129 return -EINVAL;
2130 }
2131 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2132 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2133 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2134
2135 /* point to the next argument */
2136 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2137 /*no argument after the command*/
2138 if (NULL == inPtr) return -EINVAL;
2139
2140 /*removing empty spaces*/
2141 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2142
2143 /*no argument followed by spaces*/
2144 if ('\0' == *inPtr)
2145 {
2146 return -EINVAL;
2147 }
2148
2149 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002150 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002151 v = kstrtos32(tempBuf, 10, &tempInt);
2152 if ( v < 0) return -EINVAL;
2153
2154 *pChannel = tempInt;
2155
2156 /* point to the next argument */
2157 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2158 /*no argument after the command*/
2159 if (NULL == inPtr) return -EINVAL;
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 dwell time */
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 *pDwellTime = 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 /* find the length of data */
2190 dataEnd = inPtr;
2191 while(('\0' != *dataEnd) )
2192 {
2193 dataEnd++;
2194 ++(*pBufLen);
2195 }
2196 if ( *pBufLen <= 0) return -EINVAL;
2197
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002198 /* Allocate the number of bytes based on the number of input characters
2199 whether it is even or odd.
2200 if the number of input characters are even, then we need N/2 byte.
2201 if the number of input characters are odd, then we need do (N+1)/2 to
2202 compensate rounding off.
2203 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2204 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2205 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002206 if (NULL == *pBuf)
2207 {
2208 hddLog(VOS_TRACE_LEVEL_FATAL,
2209 "%s: vos_mem_alloc failed ", __func__);
2210 return -EINVAL;
2211 }
2212
2213 /* the buffer received from the upper layer is character buffer,
2214 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2215 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2216 and f0 in 3rd location */
2217 for (i = 0, j = 0; j < *pBufLen; j += 2)
2218 {
2219 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2220 (*pBuf)[i++] = tempByte;
2221 }
2222 *pBufLen = i;
2223 return VOS_STATUS_SUCCESS;
2224}
2225
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002226/**---------------------------------------------------------------------------
2227
Srinivas Girigowdade697412013-02-14 16:31:48 -08002228 \brief hdd_parse_countryrev() - HDD Parse country code revision
2229
2230 This function parses the country code revision passed in the format
2231 SETCOUNTRYREV<space><Country code><space>revision
2232
2233 \param - pValue Pointer to input country code revision
2234 \param - pCountryCode Pointer to local output array to record country code
2235 \param - pRevision Pointer to store revision integer number
2236
2237 \return - 0 for success non-zero for failure
2238
2239 --------------------------------------------------------------------------*/
2240VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
2241{
2242 tANI_U8 *inPtr = pValue;
2243 int tempInt;
2244
2245 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2246 /*no argument after the command*/
2247 if (NULL == inPtr)
2248 {
2249 return -EINVAL;
2250 }
2251
2252 /*no space after the command*/
2253 else if (SPACE_ASCII_VALUE != *inPtr)
2254 {
2255 return -EINVAL;
2256 }
2257
2258 /*removing empty spaces*/
2259 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
2260
2261 /*no argument followed by spaces*/
2262 if ('\0' == *inPtr)
2263 {
2264 return -EINVAL;
2265 }
2266
2267 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07002268 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002269
2270 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2271 "Country code is : %s", pCountryCode);
2272
2273 /*inPtr pointing to the beginning of first space after country code */
2274 inPtr = strpbrk( inPtr, " " );
2275 /*no revision number after the country code argument */
2276 if (NULL == inPtr)
2277 {
2278 return -EINVAL;
2279 }
2280
2281 inPtr++;
2282
2283 /*removing empty space*/
2284 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2285
2286 /*no channel list after the number of channels argument and spaces*/
2287 if (0 == strncmp(pCountryCode, "KR", 2))
2288 {
2289 if ('\0' == *inPtr)
2290 {
2291 return -EINVAL;
2292 }
2293
2294 sscanf(inPtr, "%d", &tempInt);
2295 *pRevision = tempInt;
2296 }
2297 else
2298 {
2299 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2300 "Revision input is required only for Country KR");
2301 return -EINVAL;
2302 }
2303 return VOS_STATUS_SUCCESS;
2304}
2305
2306/**---------------------------------------------------------------------------
2307
2308 \brief hdd_parse_channellist() - HDD Parse channel list
2309
2310 This function parses the channel list passed in the format
2311 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002312 if the Number of channels (N) does not match with the actual number of channels passed
2313 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2314 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2315 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2316 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002317
2318 \param - pValue Pointer to input channel list
2319 \param - ChannelList Pointer to local output array to record channel list
2320 \param - pNumChannels Pointer to number of roam scan channels
2321
2322 \return - 0 for success non-zero for failure
2323
2324 --------------------------------------------------------------------------*/
2325VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2326{
2327 tANI_U8 *inPtr = pValue;
2328 int tempInt;
2329 int j = 0;
2330 int v = 0;
2331 char buf[32];
2332
2333 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2334 /*no argument after the command*/
2335 if (NULL == inPtr)
2336 {
2337 return -EINVAL;
2338 }
2339
2340 /*no space after the command*/
2341 else if (SPACE_ASCII_VALUE != *inPtr)
2342 {
2343 return -EINVAL;
2344 }
2345
2346 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002347 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002348
2349 /*no argument followed by spaces*/
2350 if ('\0' == *inPtr)
2351 {
2352 return -EINVAL;
2353 }
2354
2355 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002356 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002357 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002358 if ((v < 0) ||
2359 (tempInt <= 0) ||
2360 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2361 {
2362 return -EINVAL;
2363 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002364
2365 *pNumChannels = tempInt;
2366
2367 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2368 "Number of channels are: %d", *pNumChannels);
2369
2370 for (j = 0; j < (*pNumChannels); j++)
2371 {
2372 /*inPtr pointing to the beginning of first space after number of channels*/
2373 inPtr = strpbrk( inPtr, " " );
2374 /*no channel list after the number of channels argument*/
2375 if (NULL == inPtr)
2376 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002377 if (0 != j)
2378 {
2379 *pNumChannels = j;
2380 return VOS_STATUS_SUCCESS;
2381 }
2382 else
2383 {
2384 return -EINVAL;
2385 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002386 }
2387
2388 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002389 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002390
2391 /*no channel list after the number of channels argument and spaces*/
2392 if ( '\0' == *inPtr )
2393 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002394 if (0 != j)
2395 {
2396 *pNumChannels = j;
2397 return VOS_STATUS_SUCCESS;
2398 }
2399 else
2400 {
2401 return -EINVAL;
2402 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002403 }
2404
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002405 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002406 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002407 if ((v < 0) ||
2408 (tempInt <= 0) ||
2409 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2410 {
2411 return -EINVAL;
2412 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002413 pChannelList[j] = tempInt;
2414
2415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2416 "Channel %d added to preferred channel list",
2417 pChannelList[j] );
2418 }
2419
Srinivas Girigowdade697412013-02-14 16:31:48 -08002420 return VOS_STATUS_SUCCESS;
2421}
2422
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002423
2424/**---------------------------------------------------------------------------
2425
2426 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2427
2428 This function parses the reasoc command data passed in the format
2429 REASSOC<space><bssid><space><channel>
2430
2431 \param - pValue Pointer to input country code revision
2432 \param - pTargetApBssid Pointer to target Ap bssid
2433 \param - pChannel Pointer to the Target AP channel
2434
2435 \return - 0 for success non-zero for failure
2436
2437 --------------------------------------------------------------------------*/
2438VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2439{
2440 tANI_U8 *inPtr = pValue;
2441 int tempInt;
2442 int v = 0;
2443 tANI_U8 tempBuf[32];
2444
2445 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2446 /*no argument after the command*/
2447 if (NULL == inPtr)
2448 {
2449 return -EINVAL;
2450 }
2451
2452 /*no space after the command*/
2453 else if (SPACE_ASCII_VALUE != *inPtr)
2454 {
2455 return -EINVAL;
2456 }
2457
2458 /*removing empty spaces*/
2459 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2460
2461 /*no argument followed by spaces*/
2462 if ('\0' == *inPtr)
2463 {
2464 return -EINVAL;
2465 }
2466
2467 /*getting the first argument ie the target AP bssid */
2468 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2469 {
2470 return -EINVAL;
2471 }
2472 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2473 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2474 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2475
2476 /* point to the next argument */
2477 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2478 /*no argument after the command*/
2479 if (NULL == inPtr) return -EINVAL;
2480
2481 /*removing empty spaces*/
2482 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2483
2484 /*no argument followed by spaces*/
2485 if ('\0' == *inPtr)
2486 {
2487 return -EINVAL;
2488 }
2489
2490 /*getting the next argument ie the channel number */
2491 sscanf(inPtr, "%s ", tempBuf);
2492 v = kstrtos32(tempBuf, 10, &tempInt);
2493 if ( v < 0) return -EINVAL;
2494
2495 *pChannel = tempInt;
2496 return VOS_STATUS_SUCCESS;
2497}
2498
2499#endif
2500
Jeff Johnson295189b2012-06-20 16:38:30 -07002501/**---------------------------------------------------------------------------
2502
2503 \brief hdd_open() - HDD Open function
2504
2505 This is called in response to ifconfig up
2506
2507 \param - dev Pointer to net_device structure
2508
2509 \return - 0 for success non-zero for failure
2510
2511 --------------------------------------------------------------------------*/
2512int hdd_open (struct net_device *dev)
2513{
2514 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2515 hdd_context_t *pHddCtx;
2516 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2517 VOS_STATUS status;
2518 v_BOOL_t in_standby = TRUE;
2519
2520 if (NULL == pAdapter)
2521 {
2522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002523 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002524 return -ENODEV;
2525 }
2526
2527 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2528 if (NULL == pHddCtx)
2529 {
2530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002531 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002532 return -ENODEV;
2533 }
2534
2535 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2536 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2537 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002538 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2539 {
2540 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302541 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002542 in_standby = FALSE;
2543 break;
2544 }
2545 else
2546 {
2547 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2548 pAdapterNode = pNext;
2549 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002550 }
2551
2552 if (TRUE == in_standby)
2553 {
2554 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2555 {
2556 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2557 "wlan out of power save", __func__);
2558 return -EINVAL;
2559 }
2560 }
2561
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002562 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002563 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2564 {
2565 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002566 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002567 /* Enable TX queues only when we are connected */
2568 netif_tx_start_all_queues(dev);
2569 }
2570
2571 return 0;
2572}
2573
2574int hdd_mon_open (struct net_device *dev)
2575{
2576 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2577
2578 if(pAdapter == NULL) {
2579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002580 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002581 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002582 }
2583
2584 netif_start_queue(dev);
2585
2586 return 0;
2587}
2588/**---------------------------------------------------------------------------
2589
2590 \brief hdd_stop() - HDD stop function
2591
2592 This is called in response to ifconfig down
2593
2594 \param - dev Pointer to net_device structure
2595
2596 \return - 0 for success non-zero for failure
2597
2598 --------------------------------------------------------------------------*/
2599
2600int hdd_stop (struct net_device *dev)
2601{
2602 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2603 hdd_context_t *pHddCtx;
2604 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2605 VOS_STATUS status;
2606 v_BOOL_t enter_standby = TRUE;
2607
2608 ENTER();
2609
2610 if (NULL == pAdapter)
2611 {
2612 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002613 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002614 return -ENODEV;
2615 }
2616
2617 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2618 if (NULL == pHddCtx)
2619 {
2620 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002621 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002622 return -ENODEV;
2623 }
2624
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002625 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002626 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2627 netif_tx_disable(pAdapter->dev);
2628 netif_carrier_off(pAdapter->dev);
2629
2630
2631 /* SoftAP ifaces should never go in power save mode
2632 making sure same here. */
2633 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2634 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002635 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002636 )
2637 {
2638 /* SoftAP mode, so return from here */
2639 EXIT();
2640 return 0;
2641 }
2642
2643 /* Find if any iface is up then
2644 if any iface is up then can't put device to sleep/ power save mode. */
2645 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2646 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2647 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002648 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2649 {
2650 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302651 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002652 enter_standby = FALSE;
2653 break;
2654 }
2655 else
2656 {
2657 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2658 pAdapterNode = pNext;
2659 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002660 }
2661
2662 if (TRUE == enter_standby)
2663 {
2664 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2665 "entering standby", __func__);
2666 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2667 {
2668 /*log and return success*/
2669 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2670 "wlan in power save", __func__);
2671 }
2672 }
2673
2674 EXIT();
2675 return 0;
2676}
2677
2678/**---------------------------------------------------------------------------
2679
2680 \brief hdd_uninit() - HDD uninit function
2681
2682 This is called during the netdev unregister to uninitialize all data
2683associated with the device
2684
2685 \param - dev Pointer to net_device structure
2686
2687 \return - void
2688
2689 --------------------------------------------------------------------------*/
2690static void hdd_uninit (struct net_device *dev)
2691{
2692 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2693
2694 ENTER();
2695
2696 do
2697 {
2698 if (NULL == pAdapter)
2699 {
2700 hddLog(VOS_TRACE_LEVEL_FATAL,
2701 "%s: NULL pAdapter", __func__);
2702 break;
2703 }
2704
2705 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2706 {
2707 hddLog(VOS_TRACE_LEVEL_FATAL,
2708 "%s: Invalid magic", __func__);
2709 break;
2710 }
2711
2712 if (NULL == pAdapter->pHddCtx)
2713 {
2714 hddLog(VOS_TRACE_LEVEL_FATAL,
2715 "%s: NULL pHddCtx", __func__);
2716 break;
2717 }
2718
2719 if (dev != pAdapter->dev)
2720 {
2721 hddLog(VOS_TRACE_LEVEL_FATAL,
2722 "%s: Invalid device reference", __func__);
2723 /* we haven't validated all cases so let this go for now */
2724 }
2725
2726 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2727
2728 /* after uninit our adapter structure will no longer be valid */
2729 pAdapter->dev = NULL;
2730 pAdapter->magic = 0;
2731 } while (0);
2732
2733 EXIT();
2734}
2735
2736/**---------------------------------------------------------------------------
2737
2738 \brief hdd_release_firmware() -
2739
2740 This function calls the release firmware API to free the firmware buffer.
2741
2742 \param - pFileName Pointer to the File Name.
2743 pCtx - Pointer to the adapter .
2744
2745
2746 \return - 0 for success, non zero for failure
2747
2748 --------------------------------------------------------------------------*/
2749
2750VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2751{
2752 VOS_STATUS status = VOS_STATUS_SUCCESS;
2753 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2754 ENTER();
2755
2756
2757 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2758
2759 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2760
2761 if(pHddCtx->fw) {
2762 release_firmware(pHddCtx->fw);
2763 pHddCtx->fw = NULL;
2764 }
2765 else
2766 status = VOS_STATUS_E_FAILURE;
2767 }
2768 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2769 if(pHddCtx->nv) {
2770 release_firmware(pHddCtx->nv);
2771 pHddCtx->nv = NULL;
2772 }
2773 else
2774 status = VOS_STATUS_E_FAILURE;
2775
2776 }
2777
2778 EXIT();
2779 return status;
2780}
2781
2782/**---------------------------------------------------------------------------
2783
2784 \brief hdd_request_firmware() -
2785
2786 This function reads the firmware file using the request firmware
2787 API and returns the the firmware data and the firmware file size.
2788
2789 \param - pfileName - Pointer to the file name.
2790 - pCtx - Pointer to the adapter .
2791 - ppfw_data - Pointer to the pointer of the firmware data.
2792 - pSize - Pointer to the file size.
2793
2794 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2795
2796 --------------------------------------------------------------------------*/
2797
2798
2799VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2800{
2801 int status;
2802 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2803 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2804 ENTER();
2805
2806 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2807
2808 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2809
2810 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2811 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2812 __func__, pfileName);
2813 retval = VOS_STATUS_E_FAILURE;
2814 }
2815
2816 else {
2817 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2818 *pSize = pHddCtx->fw->size;
2819 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2820 __func__, *pSize);
2821 }
2822 }
2823 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2824
2825 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2826
2827 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2828 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2829 __func__, pfileName);
2830 retval = VOS_STATUS_E_FAILURE;
2831 }
2832
2833 else {
2834 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2835 *pSize = pHddCtx->nv->size;
2836 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2837 __func__, *pSize);
2838 }
2839 }
2840
2841 EXIT();
2842 return retval;
2843}
2844/**---------------------------------------------------------------------------
2845 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2846
2847 This is the function invoked by SME to inform the result of a full power
2848 request issued by HDD
2849
2850 \param - callbackcontext - Pointer to cookie
2851 status - result of request
2852
2853 \return - None
2854
2855--------------------------------------------------------------------------*/
2856void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2857{
2858 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2859
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002860 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002861 if(&pHddCtx->full_pwr_comp_var)
2862 {
2863 complete(&pHddCtx->full_pwr_comp_var);
2864 }
2865}
2866
2867/**---------------------------------------------------------------------------
2868
2869 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2870
2871 This is the function invoked by SME to inform the result of BMPS
2872 request issued by HDD
2873
2874 \param - callbackcontext - Pointer to cookie
2875 status - result of request
2876
2877 \return - None
2878
2879--------------------------------------------------------------------------*/
2880void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2881{
2882
2883 struct completion *completion_var = (struct completion*) callbackContext;
2884
2885 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2886 if(completion_var != NULL)
2887 {
2888 complete(completion_var);
2889 }
2890}
2891
2892/**---------------------------------------------------------------------------
2893
2894 \brief hdd_get_cfg_file_size() -
2895
2896 This function reads the configuration file using the request firmware
2897 API and returns the configuration file size.
2898
2899 \param - pCtx - Pointer to the adapter .
2900 - pFileName - Pointer to the file name.
2901 - pBufSize - Pointer to the buffer size.
2902
2903 \return - 0 for success, non zero for failure
2904
2905 --------------------------------------------------------------------------*/
2906
2907VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2908{
2909 int status;
2910 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2911
2912 ENTER();
2913
2914 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2915
2916 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2917 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2918 status = VOS_STATUS_E_FAILURE;
2919 }
2920 else {
2921 *pBufSize = pHddCtx->fw->size;
2922 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2923 release_firmware(pHddCtx->fw);
2924 pHddCtx->fw = NULL;
2925 }
2926
2927 EXIT();
2928 return VOS_STATUS_SUCCESS;
2929}
2930
2931/**---------------------------------------------------------------------------
2932
2933 \brief hdd_read_cfg_file() -
2934
2935 This function reads the configuration file using the request firmware
2936 API and returns the cfg data and the buffer size of the configuration file.
2937
2938 \param - pCtx - Pointer to the adapter .
2939 - pFileName - Pointer to the file name.
2940 - pBuffer - Pointer to the data buffer.
2941 - pBufSize - Pointer to the buffer size.
2942
2943 \return - 0 for success, non zero for failure
2944
2945 --------------------------------------------------------------------------*/
2946
2947VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2948 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2949{
2950 int status;
2951 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2952
2953 ENTER();
2954
2955 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2956
2957 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2958 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2959 return VOS_STATUS_E_FAILURE;
2960 }
2961 else {
2962 if(*pBufSize != pHddCtx->fw->size) {
2963 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2964 "file size", __func__);
2965 release_firmware(pHddCtx->fw);
2966 pHddCtx->fw = NULL;
2967 return VOS_STATUS_E_FAILURE;
2968 }
2969 else {
2970 if(pBuffer) {
2971 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2972 }
2973 release_firmware(pHddCtx->fw);
2974 pHddCtx->fw = NULL;
2975 }
2976 }
2977
2978 EXIT();
2979
2980 return VOS_STATUS_SUCCESS;
2981}
2982
2983/**---------------------------------------------------------------------------
2984
Jeff Johnson295189b2012-06-20 16:38:30 -07002985 \brief hdd_set_mac_address() -
2986
2987 This function sets the user specified mac address using
2988 the command ifconfig wlanX hw ether <mac adress>.
2989
2990 \param - dev - Pointer to the net device.
2991 - addr - Pointer to the sockaddr.
2992 \return - 0 for success, non zero for failure
2993
2994 --------------------------------------------------------------------------*/
2995
2996static int hdd_set_mac_address(struct net_device *dev, void *addr)
2997{
2998 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2999 struct sockaddr *psta_mac_addr = addr;
3000 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3001
3002 ENTER();
3003
3004 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
3005
3006#ifdef HDD_SESSIONIZE
3007 // set the MAC address though the STA ID CFG.
3008 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
3009 (v_U8_t *)&pAdapter->macAddressCurrent,
3010 sizeof( pAdapter->macAddressCurrent ),
3011 hdd_set_mac_addr_cb, VOS_FALSE );
3012#endif
3013
3014 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
3015
3016 EXIT();
3017 return halStatus;
3018}
3019
3020tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
3021{
3022 int i;
3023 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3024 {
3025 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
3026 break;
3027 }
3028
3029 if( VOS_MAX_CONCURRENCY_PERSONA == i)
3030 return NULL;
3031
3032 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
3033 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
3034}
3035
3036void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
3037{
3038 int i;
3039 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3040 {
3041 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
3042 {
3043 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
3044 break;
3045 }
3046 }
3047 return;
3048}
3049
3050#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3051 static struct net_device_ops wlan_drv_ops = {
3052 .ndo_open = hdd_open,
3053 .ndo_stop = hdd_stop,
3054 .ndo_uninit = hdd_uninit,
3055 .ndo_start_xmit = hdd_hard_start_xmit,
3056 .ndo_tx_timeout = hdd_tx_timeout,
3057 .ndo_get_stats = hdd_stats,
3058 .ndo_do_ioctl = hdd_ioctl,
3059 .ndo_set_mac_address = hdd_set_mac_address,
3060 .ndo_select_queue = hdd_select_queue,
3061#ifdef WLAN_FEATURE_PACKET_FILTERING
3062#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3063 .ndo_set_rx_mode = hdd_set_multicast_list,
3064#else
3065 .ndo_set_multicast_list = hdd_set_multicast_list,
3066#endif //LINUX_VERSION_CODE
3067#endif
3068 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003069 static struct net_device_ops wlan_mon_drv_ops = {
3070 .ndo_open = hdd_mon_open,
3071 .ndo_stop = hdd_stop,
3072 .ndo_uninit = hdd_uninit,
3073 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3074 .ndo_tx_timeout = hdd_tx_timeout,
3075 .ndo_get_stats = hdd_stats,
3076 .ndo_do_ioctl = hdd_ioctl,
3077 .ndo_set_mac_address = hdd_set_mac_address,
3078 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003079
3080#endif
3081
3082void hdd_set_station_ops( struct net_device *pWlanDev )
3083{
3084#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3085 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3086 pWlanDev->netdev_ops = &wlan_drv_ops;
3087#else
3088 pWlanDev->open = hdd_open;
3089 pWlanDev->stop = hdd_stop;
3090 pWlanDev->uninit = hdd_uninit;
3091 pWlanDev->hard_start_xmit = NULL;
3092 pWlanDev->tx_timeout = hdd_tx_timeout;
3093 pWlanDev->get_stats = hdd_stats;
3094 pWlanDev->do_ioctl = hdd_ioctl;
3095 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3096 pWlanDev->set_mac_address = hdd_set_mac_address;
3097#endif
3098}
3099
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003100static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003101{
3102 struct net_device *pWlanDev = NULL;
3103 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003104 /*
3105 * cfg80211 initialization and registration....
3106 */
3107 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3108
Jeff Johnson295189b2012-06-20 16:38:30 -07003109 if(pWlanDev != NULL)
3110 {
3111
3112 //Save the pointer to the net_device in the HDD adapter
3113 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3114
Jeff Johnson295189b2012-06-20 16:38:30 -07003115 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3116
3117 pAdapter->dev = pWlanDev;
3118 pAdapter->pHddCtx = pHddCtx;
3119 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3120
3121 init_completion(&pAdapter->session_open_comp_var);
3122 init_completion(&pAdapter->session_close_comp_var);
3123 init_completion(&pAdapter->disconnect_comp_var);
3124 init_completion(&pAdapter->linkup_event_var);
3125 init_completion(&pAdapter->cancel_rem_on_chan_var);
3126 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003127#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3128 init_completion(&pAdapter->offchannel_tx_event);
3129#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003130 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003131#ifdef FEATURE_WLAN_TDLS
3132 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003133 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003134 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303135 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003136#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003137 init_completion(&pHddCtx->mc_sus_event_var);
3138 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303139 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003140 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003141
Jeff Johnson295189b2012-06-20 16:38:30 -07003142 pAdapter->isLinkUpSvcNeeded = FALSE;
3143 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3144 //Init the net_device structure
3145 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3146
3147 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3148 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3149 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3150 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3151
3152 hdd_set_station_ops( pAdapter->dev );
3153
3154 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003155 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3156 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3157 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003158 /* set pWlanDev's parent to underlying device */
3159 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3160 }
3161
3162 return pAdapter;
3163}
3164
3165VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3166{
3167 struct net_device *pWlanDev = pAdapter->dev;
3168 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3169 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3170 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3171
3172 if( rtnl_lock_held )
3173 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003174 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003175 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3176 {
3177 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3178 return VOS_STATUS_E_FAILURE;
3179 }
3180 }
3181 if (register_netdevice(pWlanDev))
3182 {
3183 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3184 return VOS_STATUS_E_FAILURE;
3185 }
3186 }
3187 else
3188 {
3189 if(register_netdev(pWlanDev))
3190 {
3191 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3192 return VOS_STATUS_E_FAILURE;
3193 }
3194 }
3195 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3196
3197 return VOS_STATUS_SUCCESS;
3198}
3199
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003200static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003201{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003202 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003203
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003204 if (NULL == pAdapter)
3205 {
3206 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3207 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003208 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003209
3210 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3211 {
3212 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3213 return eHAL_STATUS_NOT_INITIALIZED;
3214 }
3215
3216 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3217
3218 /* need to make sure all of our scheduled work has completed.
3219 * This callback is called from MC thread context, so it is safe to
3220 * to call below flush workqueue API from here.
3221 */
3222 flush_scheduled_work();
3223
3224 /* We can be blocked while waiting for scheduled work to be
3225 * flushed, and the adapter structure can potentially be freed, in
3226 * which case the magic will have been reset. So make sure the
3227 * magic is still good, and hence the adapter structure is still
3228 * valid, before signaling completion */
3229 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3230 {
3231 complete(&pAdapter->session_close_comp_var);
3232 }
3233
Jeff Johnson295189b2012-06-20 16:38:30 -07003234 return eHAL_STATUS_SUCCESS;
3235}
3236
3237VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3238{
3239 struct net_device *pWlanDev = pAdapter->dev;
3240 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3241 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3242 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3243 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3244 int rc = 0;
3245
3246 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003247 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003248 //Open a SME session for future operation
3249 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003250 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003251 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3252 {
3253 hddLog(VOS_TRACE_LEVEL_FATAL,
3254 "sme_OpenSession() failed with status code %08d [x%08lx]",
3255 halStatus, halStatus );
3256 status = VOS_STATUS_E_FAILURE;
3257 goto error_sme_open;
3258 }
3259
3260 //Block on a completion variable. Can't wait forever though.
3261 rc = wait_for_completion_interruptible_timeout(
3262 &pAdapter->session_open_comp_var,
3263 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3264 if (!rc)
3265 {
3266 hddLog(VOS_TRACE_LEVEL_FATAL,
3267 "Session is not opened within timeout period code %08d", rc );
3268 status = VOS_STATUS_E_FAILURE;
3269 goto error_sme_open;
3270 }
3271
3272 // Register wireless extensions
3273 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3274 {
3275 hddLog(VOS_TRACE_LEVEL_FATAL,
3276 "hdd_register_wext() failed with status code %08d [x%08lx]",
3277 halStatus, halStatus );
3278 status = VOS_STATUS_E_FAILURE;
3279 goto error_register_wext;
3280 }
3281 //Safe to register the hard_start_xmit function again
3282#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3283 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3284#else
3285 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3286#endif
3287
3288 //Set the Connection State to Not Connected
3289 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3290
3291 //Set the default operation channel
3292 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3293
3294 /* Make the default Auth Type as OPEN*/
3295 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3296
3297 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3298 {
3299 hddLog(VOS_TRACE_LEVEL_FATAL,
3300 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3301 status, status );
3302 goto error_init_txrx;
3303 }
3304
3305 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3306
3307 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3308 {
3309 hddLog(VOS_TRACE_LEVEL_FATAL,
3310 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3311 status, status );
3312 goto error_wmm_init;
3313 }
3314
3315 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3316
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003317#ifdef FEATURE_WLAN_TDLS
3318 if(0 != wlan_hdd_tdls_init(pAdapter))
3319 {
3320 status = VOS_STATUS_E_FAILURE;
3321 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3322 goto error_tdls_init;
3323 }
3324 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3325#endif
3326
Jeff Johnson295189b2012-06-20 16:38:30 -07003327 return VOS_STATUS_SUCCESS;
3328
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003329#ifdef FEATURE_WLAN_TDLS
3330error_tdls_init:
3331 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3332 hdd_wmm_adapter_close(pAdapter);
3333#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003334error_wmm_init:
3335 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3336 hdd_deinit_tx_rx(pAdapter);
3337error_init_txrx:
3338 hdd_UnregisterWext(pWlanDev);
3339error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003340 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003341 {
3342 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003343 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003344 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003345 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003346 {
3347 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003348 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003349 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003350 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003351 }
3352}
3353error_sme_open:
3354 return status;
3355}
3356
Jeff Johnson295189b2012-06-20 16:38:30 -07003357void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3358{
3359 hdd_cfg80211_state_t *cfgState;
3360
3361 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3362
3363 if( NULL != cfgState->buf )
3364 {
3365 int rc;
3366 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3367 rc = wait_for_completion_interruptible_timeout(
3368 &pAdapter->tx_action_cnf_event,
3369 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3370 if(!rc)
3371 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003372 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003373 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3374 }
3375 }
3376 return;
3377}
Jeff Johnson295189b2012-06-20 16:38:30 -07003378
3379void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3380{
3381 ENTER();
3382 switch ( pAdapter->device_mode )
3383 {
3384 case WLAN_HDD_INFRA_STATION:
3385 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003386 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003387 {
3388 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3389 {
3390 hdd_deinit_tx_rx( pAdapter );
3391 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3392 }
3393
3394 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3395 {
3396 hdd_wmm_adapter_close( pAdapter );
3397 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3398 }
3399
Jeff Johnson295189b2012-06-20 16:38:30 -07003400 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003401#ifdef FEATURE_WLAN_TDLS
3402 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3403 {
3404 wlan_hdd_tdls_exit(pAdapter);
3405 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3406 }
3407#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003408
3409 break;
3410 }
3411
3412 case WLAN_HDD_SOFTAP:
3413 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003414 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003415 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003416
3417 hdd_unregister_hostapd(pAdapter);
3418 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003419 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003420 break;
3421 }
3422
3423 case WLAN_HDD_MONITOR:
3424 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003425 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003426 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3427 {
3428 hdd_deinit_tx_rx( pAdapter );
3429 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3430 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003431 if(NULL != pAdapterforTx)
3432 {
3433 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3434 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003435 break;
3436 }
3437
3438
3439 default:
3440 break;
3441 }
3442
3443 EXIT();
3444}
3445
3446void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3447{
3448 struct net_device *pWlanDev = pAdapter->dev;
3449
3450 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3451 if( rtnl_held )
3452 {
3453 unregister_netdevice(pWlanDev);
3454 }
3455 else
3456 {
3457 unregister_netdev(pWlanDev);
3458 }
3459 // note that the pAdapter is no longer valid at this point
3460 // since the memory has been reclaimed
3461 }
3462
3463}
3464
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003465void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3466{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303467 VOS_STATUS status;
3468 hdd_adapter_t *pAdapter = NULL;
3469 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003470
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303471 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003472
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303473 /*loop through all adapters.*/
3474 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003475 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303476 pAdapter = pAdapterNode->pAdapter;
3477 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3478 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003479
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303480 { // we skip this registration for modes other than STA and P2P client modes.
3481 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3482 pAdapterNode = pNext;
3483 continue;
3484 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003485
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303486 //Apply Dynamic DTIM For P2P
3487 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3488 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3489 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3490 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3491 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3492 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3493 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3494 (eConnectionState_Associated ==
3495 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3496 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3497 {
3498 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003499
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303500 powerRequest.uIgnoreDTIM = 1;
3501 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3502
3503 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3504 {
3505 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3506 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3507 }
3508 else
3509 {
3510 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3511 }
3512
3513 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3514 * specified during Enter/Exit BMPS when LCD off*/
3515 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3516 NULL, eANI_BOOLEAN_FALSE);
3517 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3518 NULL, eANI_BOOLEAN_FALSE);
3519
3520 /* switch to the DTIM specified in cfg.ini */
3521 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3522 "Switch to DTIM %d", powerRequest.uListenInterval);
3523 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3524 break;
3525
3526 }
3527
3528 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3529 pAdapterNode = pNext;
3530 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003531}
3532
3533void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3534{
3535 /*Switch back to DTIM 1*/
3536 tSirSetPowerParamsReq powerRequest = { 0 };
3537
3538 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3539 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003540 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003541
3542 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3543 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3544 NULL, eANI_BOOLEAN_FALSE);
3545 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3546 NULL, eANI_BOOLEAN_FALSE);
3547
3548 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3549 "Switch to DTIM%d",powerRequest.uListenInterval);
3550 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3551
3552}
3553
Jeff Johnson295189b2012-06-20 16:38:30 -07003554VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3555{
3556 VOS_STATUS status = VOS_STATUS_SUCCESS;
3557
3558 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3559 {
3560 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3561 }
3562
3563 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3564 {
3565 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3566 }
3567
3568 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3569 {
3570 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3571 }
3572
3573 return status;
3574}
3575
3576VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3577{
3578 hdd_adapter_t *pAdapter = NULL;
3579 eHalStatus halStatus;
3580 VOS_STATUS status = VOS_STATUS_E_INVAL;
3581 v_BOOL_t disableBmps = FALSE;
3582 v_BOOL_t disableImps = FALSE;
3583
3584 switch(session_type)
3585 {
3586 case WLAN_HDD_INFRA_STATION:
3587 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003588 case WLAN_HDD_P2P_CLIENT:
3589 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003590 //Exit BMPS -> Is Sta/P2P Client is already connected
3591 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3592 if((NULL != pAdapter)&&
3593 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3594 {
3595 disableBmps = TRUE;
3596 }
3597
3598 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3599 if((NULL != pAdapter)&&
3600 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3601 {
3602 disableBmps = TRUE;
3603 }
3604
3605 //Exit both Bmps and Imps incase of Go/SAP Mode
3606 if((WLAN_HDD_SOFTAP == session_type) ||
3607 (WLAN_HDD_P2P_GO == session_type))
3608 {
3609 disableBmps = TRUE;
3610 disableImps = TRUE;
3611 }
3612
3613 if(TRUE == disableImps)
3614 {
3615 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3616 {
3617 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3618 }
3619 }
3620
3621 if(TRUE == disableBmps)
3622 {
3623 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3624 {
3625 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3626
3627 if(eHAL_STATUS_SUCCESS != halStatus)
3628 {
3629 status = VOS_STATUS_E_FAILURE;
3630 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3631 VOS_ASSERT(0);
3632 return status;
3633 }
3634 }
3635
3636 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3637 {
3638 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3639
3640 if(eHAL_STATUS_SUCCESS != halStatus)
3641 {
3642 status = VOS_STATUS_E_FAILURE;
3643 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3644 VOS_ASSERT(0);
3645 return status;
3646 }
3647 }
3648 }
3649
3650 if((TRUE == disableBmps) ||
3651 (TRUE == disableImps))
3652 {
3653 /* Now, get the chip into Full Power now */
3654 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3655 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3656 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3657
3658 if(halStatus != eHAL_STATUS_SUCCESS)
3659 {
3660 if(halStatus == eHAL_STATUS_PMC_PENDING)
3661 {
3662 //Block on a completion variable. Can't wait forever though
3663 wait_for_completion_interruptible_timeout(
3664 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3665 }
3666 else
3667 {
3668 status = VOS_STATUS_E_FAILURE;
3669 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3670 VOS_ASSERT(0);
3671 return status;
3672 }
3673 }
3674
3675 status = VOS_STATUS_SUCCESS;
3676 }
3677
3678 break;
3679 }
3680 return status;
3681}
3682
3683hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003684 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003685 tANI_U8 rtnl_held )
3686{
3687 hdd_adapter_t *pAdapter = NULL;
3688 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3689 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3690 VOS_STATUS exitbmpsStatus;
3691
3692 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3693
3694 //Disable BMPS incase of Concurrency
3695 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3696
3697 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3698 {
3699 //Fail to Exit BMPS
3700 VOS_ASSERT(0);
3701 return NULL;
3702 }
3703
3704 switch(session_type)
3705 {
3706 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003707 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003708 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003709 {
3710 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3711
3712 if( NULL == pAdapter )
3713 return NULL;
3714
Jeff Johnsone7245742012-09-05 17:12:55 -07003715 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3716 NL80211_IFTYPE_P2P_CLIENT:
3717 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003718
Jeff Johnson295189b2012-06-20 16:38:30 -07003719 pAdapter->device_mode = session_type;
3720
3721 status = hdd_init_station_mode( pAdapter );
3722 if( VOS_STATUS_SUCCESS != status )
3723 goto err_free_netdev;
3724
3725 status = hdd_register_interface( pAdapter, rtnl_held );
3726 if( VOS_STATUS_SUCCESS != status )
3727 {
3728 hdd_deinit_adapter(pHddCtx, pAdapter);
3729 goto err_free_netdev;
3730 }
3731 //Stop the Interface TX queue.
3732 netif_tx_disable(pAdapter->dev);
3733 //netif_tx_disable(pWlanDev);
3734 netif_carrier_off(pAdapter->dev);
3735
3736 break;
3737 }
3738
Jeff Johnson295189b2012-06-20 16:38:30 -07003739 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003740 case WLAN_HDD_SOFTAP:
3741 {
3742 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3743 if( NULL == pAdapter )
3744 return NULL;
3745
Jeff Johnson295189b2012-06-20 16:38:30 -07003746 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3747 NL80211_IFTYPE_AP:
3748 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003749 pAdapter->device_mode = session_type;
3750
3751 status = hdd_init_ap_mode(pAdapter);
3752 if( VOS_STATUS_SUCCESS != status )
3753 goto err_free_netdev;
3754
3755 status = hdd_register_hostapd( pAdapter, rtnl_held );
3756 if( VOS_STATUS_SUCCESS != status )
3757 {
3758 hdd_deinit_adapter(pHddCtx, pAdapter);
3759 goto err_free_netdev;
3760 }
3761
3762 netif_tx_disable(pAdapter->dev);
3763 netif_carrier_off(pAdapter->dev);
3764
3765 hdd_set_conparam( 1 );
3766 break;
3767 }
3768 case WLAN_HDD_MONITOR:
3769 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003770 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3771 if( NULL == pAdapter )
3772 return NULL;
3773
3774 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3775 pAdapter->device_mode = session_type;
3776 status = hdd_register_interface( pAdapter, rtnl_held );
3777#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3778 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3779#else
3780 pAdapter->dev->open = hdd_mon_open;
3781 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3782#endif
3783 hdd_init_tx_rx( pAdapter );
3784 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3785 //Set adapter to be used for data tx. It will use either GO or softap.
3786 pAdapter->sessionCtx.monitor.pAdapterForTx =
3787 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003788 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3789 {
3790 pAdapter->sessionCtx.monitor.pAdapterForTx =
3791 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3792 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003793 /* This workqueue will be used to transmit management packet over
3794 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003795 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3796 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3797 return NULL;
3798 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003799
Jeff Johnson295189b2012-06-20 16:38:30 -07003800 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3801 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003802 }
3803 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003804 case WLAN_HDD_FTM:
3805 {
3806 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3807
3808 if( NULL == pAdapter )
3809 return NULL;
3810 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3811 * message while loading driver in FTM mode. */
3812 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3813 pAdapter->device_mode = session_type;
3814 status = hdd_register_interface( pAdapter, rtnl_held );
3815 }
3816 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003817 default:
3818 {
3819 VOS_ASSERT(0);
3820 return NULL;
3821 }
3822 }
3823
3824
3825 if( VOS_STATUS_SUCCESS == status )
3826 {
3827 //Add it to the hdd's session list.
3828 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3829 if( NULL == pHddAdapterNode )
3830 {
3831 status = VOS_STATUS_E_NOMEM;
3832 }
3833 else
3834 {
3835 pHddAdapterNode->pAdapter = pAdapter;
3836 status = hdd_add_adapter_back ( pHddCtx,
3837 pHddAdapterNode );
3838 }
3839 }
3840
3841 if( VOS_STATUS_SUCCESS != status )
3842 {
3843 if( NULL != pAdapter )
3844 {
3845 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3846 pAdapter = NULL;
3847 }
3848 if( NULL != pHddAdapterNode )
3849 {
3850 vos_mem_free( pHddAdapterNode );
3851 }
3852
3853 goto resume_bmps;
3854 }
3855
3856 if(VOS_STATUS_SUCCESS == status)
3857 {
3858 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3859
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003860 //Initialize the WoWL service
3861 if(!hdd_init_wowl(pAdapter))
3862 {
3863 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3864 goto err_free_netdev;
3865 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003866 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003867 return pAdapter;
3868
3869err_free_netdev:
3870 free_netdev(pAdapter->dev);
3871 wlan_hdd_release_intf_addr( pHddCtx,
3872 pAdapter->macAddressCurrent.bytes );
3873
3874resume_bmps:
3875 //If bmps disabled enable it
3876 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3877 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303878 if (pHddCtx->hdd_wlan_suspended)
3879 {
3880 hdd_set_pwrparams(pHddCtx);
3881 }
3882 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003883 }
3884 return NULL;
3885}
3886
3887VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3888 tANI_U8 rtnl_held )
3889{
3890 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3891 VOS_STATUS status;
3892
3893 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3894 if( VOS_STATUS_SUCCESS != status )
3895 return status;
3896
3897 while ( pCurrent->pAdapter != pAdapter )
3898 {
3899 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3900 if( VOS_STATUS_SUCCESS != status )
3901 break;
3902
3903 pCurrent = pNext;
3904 }
3905 pAdapterNode = pCurrent;
3906 if( VOS_STATUS_SUCCESS == status )
3907 {
3908 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3909 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3910 hdd_remove_adapter( pHddCtx, pAdapterNode );
3911 vos_mem_free( pAdapterNode );
3912
Jeff Johnson295189b2012-06-20 16:38:30 -07003913
3914 /* If there is a single session of STA/P2P client, re-enable BMPS */
3915 if ((!vos_concurrent_sessions_running()) &&
3916 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3917 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3918 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303919 if (pHddCtx->hdd_wlan_suspended)
3920 {
3921 hdd_set_pwrparams(pHddCtx);
3922 }
3923 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003924 }
3925
3926 return VOS_STATUS_SUCCESS;
3927 }
3928
3929 return VOS_STATUS_E_FAILURE;
3930}
3931
3932VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3933{
3934 hdd_adapter_list_node_t *pHddAdapterNode;
3935 VOS_STATUS status;
3936
3937 ENTER();
3938
3939 do
3940 {
3941 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3942 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3943 {
3944 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3945 vos_mem_free( pHddAdapterNode );
3946 }
3947 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3948
3949 EXIT();
3950
3951 return VOS_STATUS_SUCCESS;
3952}
3953
3954void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3955{
3956 v_U8_t addIE[1] = {0};
3957
3958 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3959 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3960 eANI_BOOLEAN_FALSE) )
3961 {
3962 hddLog(LOGE,
3963 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3964 }
3965
3966 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3967 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3968 eANI_BOOLEAN_FALSE) )
3969 {
3970 hddLog(LOGE,
3971 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3972 }
3973
3974 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3975 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3976 eANI_BOOLEAN_FALSE) )
3977 {
3978 hddLog(LOGE,
3979 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3980 }
3981}
3982
3983VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3984{
3985 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3986 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3987 union iwreq_data wrqu;
3988
3989 ENTER();
3990
3991 switch(pAdapter->device_mode)
3992 {
3993 case WLAN_HDD_INFRA_STATION:
3994 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003995 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003996 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3997 {
3998 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3999 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4000 pAdapter->sessionId,
4001 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
4002 else
4003 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4004 pAdapter->sessionId,
4005 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4006 //success implies disconnect command got queued up successfully
4007 if(halStatus == eHAL_STATUS_SUCCESS)
4008 {
4009 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
4010 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4011 }
4012 memset(&wrqu, '\0', sizeof(wrqu));
4013 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4014 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4015 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
4016 }
4017 else
4018 {
4019 hdd_abort_mac_scan(pHddCtx);
4020 }
4021
4022 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
4023 {
4024 INIT_COMPLETION(pAdapter->session_close_comp_var);
4025 if (eHAL_STATUS_SUCCESS ==
4026 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
4027 hdd_smeCloseSessionCallback, pAdapter))
4028 {
4029 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004030 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004031 &pAdapter->session_close_comp_var,
4032 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4033 }
4034 }
4035
4036 break;
4037
4038 case WLAN_HDD_SOFTAP:
4039 case WLAN_HDD_P2P_GO:
4040 //Any softap specific cleanup here...
4041 mutex_lock(&pHddCtx->sap_lock);
4042 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4043 {
4044 VOS_STATUS status;
4045 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4046
4047 //Stop Bss.
4048 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4049 if (VOS_IS_STATUS_SUCCESS(status))
4050 {
4051 hdd_hostapd_state_t *pHostapdState =
4052 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4053
4054 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4055
4056 if (!VOS_IS_STATUS_SUCCESS(status))
4057 {
4058 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004059 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004060 }
4061 }
4062 else
4063 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004064 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004065 }
4066 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4067
4068 if (eHAL_STATUS_FAILURE ==
4069 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4070 0, NULL, eANI_BOOLEAN_FALSE))
4071 {
4072 hddLog(LOGE,
4073 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004074 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004075 }
4076
4077 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4078 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4079 eANI_BOOLEAN_FALSE) )
4080 {
4081 hddLog(LOGE,
4082 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4083 }
4084
4085 // Reset WNI_CFG_PROBE_RSP Flags
4086 wlan_hdd_reset_prob_rspies(pAdapter);
4087 kfree(pAdapter->sessionCtx.ap.beacon);
4088 pAdapter->sessionCtx.ap.beacon = NULL;
4089 }
4090 mutex_unlock(&pHddCtx->sap_lock);
4091 break;
4092 case WLAN_HDD_MONITOR:
4093 break;
4094 default:
4095 break;
4096 }
4097
4098 EXIT();
4099 return VOS_STATUS_SUCCESS;
4100}
4101
4102VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4103{
4104 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4105 VOS_STATUS status;
4106 hdd_adapter_t *pAdapter;
4107
4108 ENTER();
4109
4110 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4111
4112 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4113 {
4114 pAdapter = pAdapterNode->pAdapter;
4115 netif_tx_disable(pAdapter->dev);
4116 netif_carrier_off(pAdapter->dev);
4117
4118 hdd_stop_adapter( pHddCtx, pAdapter );
4119
4120 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4121 pAdapterNode = pNext;
4122 }
4123
4124 EXIT();
4125
4126 return VOS_STATUS_SUCCESS;
4127}
4128
4129VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4130{
4131 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4132 VOS_STATUS status;
4133 hdd_adapter_t *pAdapter;
4134
4135 ENTER();
4136
4137 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4138
4139 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4140 {
4141 pAdapter = pAdapterNode->pAdapter;
4142 netif_tx_disable(pAdapter->dev);
4143 netif_carrier_off(pAdapter->dev);
4144
Jeff Johnson295189b2012-06-20 16:38:30 -07004145 hdd_deinit_tx_rx(pAdapter);
4146 hdd_wmm_adapter_close(pAdapter);
4147
4148 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4149 pAdapterNode = pNext;
4150 }
4151
4152 EXIT();
4153
4154 return VOS_STATUS_SUCCESS;
4155}
4156
4157VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4158{
4159 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4160 VOS_STATUS status;
4161 hdd_adapter_t *pAdapter;
4162 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304163 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004164
4165 ENTER();
4166
4167 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4168
4169 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4170 {
4171 pAdapter = pAdapterNode->pAdapter;
4172
4173 switch(pAdapter->device_mode)
4174 {
4175 case WLAN_HDD_INFRA_STATION:
4176 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004177 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304178
4179 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4180
Jeff Johnson295189b2012-06-20 16:38:30 -07004181 hdd_init_station_mode(pAdapter);
4182 /* Open the gates for HDD to receive Wext commands */
4183 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004184 pHddCtx->scan_info.mScanPending = FALSE;
4185 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004186
4187 //Trigger the initial scan
4188 hdd_wlan_initial_scan(pAdapter);
4189
4190 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304191 if (eConnectionState_Associated == connState ||
4192 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004193 {
4194 union iwreq_data wrqu;
4195 memset(&wrqu, '\0', sizeof(wrqu));
4196 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4197 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4198 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004199
Jeff Johnson295189b2012-06-20 16:38:30 -07004200 /* indicate disconnected event to nl80211 */
4201 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4202 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004203 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304204 else if (eConnectionState_Connecting == connState)
4205 {
4206 /*
4207 * Indicate connect failure to supplicant if we were in the
4208 * process of connecting
4209 */
4210 cfg80211_connect_result(pAdapter->dev, NULL,
4211 NULL, 0, NULL, 0,
4212 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4213 GFP_KERNEL);
4214 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004215 break;
4216
4217 case WLAN_HDD_SOFTAP:
4218 /* softAP can handle SSR */
4219 break;
4220
4221 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004222 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4223 __func__);
4224 /* event supplicant to restart */
4225 cfg80211_del_sta(pAdapter->dev,
4226 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004227 break;
4228
4229 case WLAN_HDD_MONITOR:
4230 /* monitor interface start */
4231 break;
4232 default:
4233 break;
4234 }
4235
4236 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4237 pAdapterNode = pNext;
4238 }
4239
4240 EXIT();
4241
4242 return VOS_STATUS_SUCCESS;
4243}
4244
4245VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4246{
4247 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4248 hdd_adapter_t *pAdapter;
4249 VOS_STATUS status;
4250 v_U32_t roamId;
4251
4252 ENTER();
4253
4254 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4255
4256 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4257 {
4258 pAdapter = pAdapterNode->pAdapter;
4259
4260 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4261 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4262 {
4263 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4264 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4265
4266 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4267 init_completion(&pAdapter->disconnect_comp_var);
4268 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4269 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4270
4271 wait_for_completion_interruptible_timeout(
4272 &pAdapter->disconnect_comp_var,
4273 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4274
4275 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4276 pHddCtx->isAmpAllowed = VOS_FALSE;
4277 sme_RoamConnect(pHddCtx->hHal,
4278 pAdapter->sessionId, &(pWextState->roamProfile),
4279 &roamId);
4280 }
4281
4282 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4283 pAdapterNode = pNext;
4284 }
4285
4286 EXIT();
4287
4288 return VOS_STATUS_SUCCESS;
4289}
4290
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004291void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4292{
4293 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4294 VOS_STATUS status;
4295 hdd_adapter_t *pAdapter;
4296 hdd_station_ctx_t *pHddStaCtx;
4297 hdd_ap_ctx_t *pHddApCtx;
4298 hdd_hostapd_state_t * pHostapdState;
4299 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4300 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4301 const char *p2pMode = "DEV";
4302 const char *ccMode = "Standalone";
4303 int n;
4304
4305 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4306 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4307 {
4308 pAdapter = pAdapterNode->pAdapter;
4309 switch (pAdapter->device_mode) {
4310 case WLAN_HDD_INFRA_STATION:
4311 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4312 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4313 staChannel = pHddStaCtx->conn_info.operationChannel;
4314 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4315 }
4316 break;
4317 case WLAN_HDD_P2P_CLIENT:
4318 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4319 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4320 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4321 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4322 p2pMode = "CLI";
4323 }
4324 break;
4325 case WLAN_HDD_P2P_GO:
4326 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4327 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4328 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4329 p2pChannel = pHddApCtx->operatingChannel;
4330 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4331 }
4332 p2pMode = "GO";
4333 break;
4334 case WLAN_HDD_SOFTAP:
4335 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4336 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4337 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4338 apChannel = pHddApCtx->operatingChannel;
4339 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4340 }
4341 break;
4342 default:
4343 break;
4344 }
4345 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4346 pAdapterNode = pNext;
4347 }
4348 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4349 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4350 }
4351 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4352 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4353 if (p2pChannel > 0) {
4354 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4355 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4356 }
4357 if (apChannel > 0) {
4358 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4359 apChannel, MAC_ADDR_ARRAY(apBssid));
4360 }
4361
4362 if (p2pChannel > 0 && apChannel > 0) {
4363 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4364 }
4365}
4366
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004367bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004368{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004369 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004370}
4371
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004372/* Once SSR is disabled then it cannot be set. */
4373void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004374{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004375 if (HDD_SSR_DISABLED == isSsrRequired)
4376 return;
4377
Jeff Johnson295189b2012-06-20 16:38:30 -07004378 isSsrRequired = value;
4379}
4380
4381VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4382 hdd_adapter_list_node_t** ppAdapterNode)
4383{
4384 VOS_STATUS status;
4385 spin_lock(&pHddCtx->hddAdapters.lock);
4386 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4387 (hdd_list_node_t**) ppAdapterNode );
4388 spin_unlock(&pHddCtx->hddAdapters.lock);
4389 return status;
4390}
4391
4392VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4393 hdd_adapter_list_node_t* pAdapterNode,
4394 hdd_adapter_list_node_t** pNextAdapterNode)
4395{
4396 VOS_STATUS status;
4397 spin_lock(&pHddCtx->hddAdapters.lock);
4398 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4399 (hdd_list_node_t*) pAdapterNode,
4400 (hdd_list_node_t**)pNextAdapterNode );
4401
4402 spin_unlock(&pHddCtx->hddAdapters.lock);
4403 return status;
4404}
4405
4406VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4407 hdd_adapter_list_node_t* pAdapterNode)
4408{
4409 VOS_STATUS status;
4410 spin_lock(&pHddCtx->hddAdapters.lock);
4411 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4412 &pAdapterNode->node );
4413 spin_unlock(&pHddCtx->hddAdapters.lock);
4414 return status;
4415}
4416
4417VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4418 hdd_adapter_list_node_t** ppAdapterNode)
4419{
4420 VOS_STATUS status;
4421 spin_lock(&pHddCtx->hddAdapters.lock);
4422 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4423 (hdd_list_node_t**) ppAdapterNode );
4424 spin_unlock(&pHddCtx->hddAdapters.lock);
4425 return status;
4426}
4427
4428VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4429 hdd_adapter_list_node_t* pAdapterNode)
4430{
4431 VOS_STATUS status;
4432 spin_lock(&pHddCtx->hddAdapters.lock);
4433 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4434 (hdd_list_node_t*) pAdapterNode );
4435 spin_unlock(&pHddCtx->hddAdapters.lock);
4436 return status;
4437}
4438
4439VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4440 hdd_adapter_list_node_t* pAdapterNode)
4441{
4442 VOS_STATUS status;
4443 spin_lock(&pHddCtx->hddAdapters.lock);
4444 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4445 (hdd_list_node_t*) pAdapterNode );
4446 spin_unlock(&pHddCtx->hddAdapters.lock);
4447 return status;
4448}
4449
4450hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4451 tSirMacAddr macAddr )
4452{
4453 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4454 hdd_adapter_t *pAdapter;
4455 VOS_STATUS status;
4456
4457 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4458
4459 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4460 {
4461 pAdapter = pAdapterNode->pAdapter;
4462
4463 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4464 macAddr, sizeof(tSirMacAddr) ) )
4465 {
4466 return pAdapter;
4467 }
4468 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4469 pAdapterNode = pNext;
4470 }
4471
4472 return NULL;
4473
4474}
4475
4476hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4477{
4478 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4479 hdd_adapter_t *pAdapter;
4480 VOS_STATUS status;
4481
4482 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4483
4484 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4485 {
4486 pAdapter = pAdapterNode->pAdapter;
4487
4488 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4489 IFNAMSIZ ) )
4490 {
4491 return pAdapter;
4492 }
4493 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4494 pAdapterNode = pNext;
4495 }
4496
4497 return NULL;
4498
4499}
4500
4501hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4502{
4503 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4504 hdd_adapter_t *pAdapter;
4505 VOS_STATUS status;
4506
4507 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4508
4509 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4510 {
4511 pAdapter = pAdapterNode->pAdapter;
4512
4513 if( pAdapter && (mode == pAdapter->device_mode) )
4514 {
4515 return pAdapter;
4516 }
4517 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4518 pAdapterNode = pNext;
4519 }
4520
4521 return NULL;
4522
4523}
4524
4525//Remove this function later
4526hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4527{
4528 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4529 hdd_adapter_t *pAdapter;
4530 VOS_STATUS status;
4531
4532 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4533
4534 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4535 {
4536 pAdapter = pAdapterNode->pAdapter;
4537
4538 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4539 {
4540 return pAdapter;
4541 }
4542
4543 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4544 pAdapterNode = pNext;
4545 }
4546
4547 return NULL;
4548
4549}
4550
Jeff Johnson295189b2012-06-20 16:38:30 -07004551/**---------------------------------------------------------------------------
4552
4553 \brief hdd_set_monitor_tx_adapter() -
4554
4555 This API initializes the adapter to be used while transmitting on monitor
4556 adapter.
4557
4558 \param - pHddCtx - Pointer to the HDD context.
4559 pAdapter - Adapter that will used for TX. This can be NULL.
4560 \return - None.
4561 --------------------------------------------------------------------------*/
4562void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4563{
4564 hdd_adapter_t *pMonAdapter;
4565
4566 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4567
4568 if( NULL != pMonAdapter )
4569 {
4570 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4571 }
4572}
Jeff Johnson295189b2012-06-20 16:38:30 -07004573/**---------------------------------------------------------------------------
4574
4575 \brief hdd_select_queue() -
4576
4577 This API returns the operating channel of the requested device mode
4578
4579 \param - pHddCtx - Pointer to the HDD context.
4580 - mode - Device mode for which operating channel is required
4581 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4582 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4583 \return - channel number. "0" id the requested device is not found OR it is not connected.
4584 --------------------------------------------------------------------------*/
4585v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4586{
4587 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4588 VOS_STATUS status;
4589 hdd_adapter_t *pAdapter;
4590 v_U8_t operatingChannel = 0;
4591
4592 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4593
4594 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4595 {
4596 pAdapter = pAdapterNode->pAdapter;
4597
4598 if( mode == pAdapter->device_mode )
4599 {
4600 switch(pAdapter->device_mode)
4601 {
4602 case WLAN_HDD_INFRA_STATION:
4603 case WLAN_HDD_P2P_CLIENT:
4604 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4605 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4606 break;
4607 case WLAN_HDD_SOFTAP:
4608 case WLAN_HDD_P2P_GO:
4609 /*softap connection info */
4610 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4611 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4612 break;
4613 default:
4614 break;
4615 }
4616
4617 break; //Found the device of interest. break the loop
4618 }
4619
4620 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4621 pAdapterNode = pNext;
4622 }
4623 return operatingChannel;
4624}
4625
4626#ifdef WLAN_FEATURE_PACKET_FILTERING
4627/**---------------------------------------------------------------------------
4628
4629 \brief hdd_set_multicast_list() -
4630
4631 This used to set the multicast address list.
4632
4633 \param - dev - Pointer to the WLAN device.
4634 - skb - Pointer to OS packet (sk_buff).
4635 \return - success/fail
4636
4637 --------------------------------------------------------------------------*/
4638static void hdd_set_multicast_list(struct net_device *dev)
4639{
4640 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004641 int mc_count;
4642 int i = 0;
4643 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304644
4645 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004646 {
4647 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304648 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004649 return;
4650 }
4651
4652 if (dev->flags & IFF_ALLMULTI)
4653 {
4654 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004655 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304656 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004657 }
4658 else
4659 {
4660 mc_count = netdev_mc_count(dev);
4661 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004662 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004663 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4664 {
4665 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004666 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304667 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004668 return;
4669 }
4670
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304671 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004672
4673 netdev_for_each_mc_addr(ha, dev) {
4674 if (i == mc_count)
4675 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304676 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4677 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4678 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004679 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304680 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004681 i++;
4682 }
4683 }
4684 return;
4685}
4686#endif
4687
4688/**---------------------------------------------------------------------------
4689
4690 \brief hdd_select_queue() -
4691
4692 This function is registered with the Linux OS for network
4693 core to decide which queue to use first.
4694
4695 \param - dev - Pointer to the WLAN device.
4696 - skb - Pointer to OS packet (sk_buff).
4697 \return - ac, Queue Index/access category corresponding to UP in IP header
4698
4699 --------------------------------------------------------------------------*/
4700v_U16_t hdd_select_queue(struct net_device *dev,
4701 struct sk_buff *skb)
4702{
4703 return hdd_wmm_select_queue(dev, skb);
4704}
4705
4706
4707/**---------------------------------------------------------------------------
4708
4709 \brief hdd_wlan_initial_scan() -
4710
4711 This function triggers the initial scan
4712
4713 \param - pAdapter - Pointer to the HDD adapter.
4714
4715 --------------------------------------------------------------------------*/
4716void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4717{
4718 tCsrScanRequest scanReq;
4719 tCsrChannelInfo channelInfo;
4720 eHalStatus halStatus;
4721 unsigned long scanId;
4722 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4723
4724 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4725 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4726 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4727
4728 if(sme_Is11dSupported(pHddCtx->hHal))
4729 {
4730 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4731 if ( HAL_STATUS_SUCCESS( halStatus ) )
4732 {
4733 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4734 if( !scanReq.ChannelInfo.ChannelList )
4735 {
4736 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4737 vos_mem_free(channelInfo.ChannelList);
4738 return;
4739 }
4740 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4741 channelInfo.numOfChannels);
4742 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4743 vos_mem_free(channelInfo.ChannelList);
4744 }
4745
4746 scanReq.scanType = eSIR_PASSIVE_SCAN;
4747 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4748 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4749 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4750 }
4751 else
4752 {
4753 scanReq.scanType = eSIR_ACTIVE_SCAN;
4754 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4755 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4756 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4757 }
4758
4759 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4760 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4761 {
4762 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4763 __func__, halStatus );
4764 }
4765
4766 if(sme_Is11dSupported(pHddCtx->hHal))
4767 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4768}
4769
4770struct fullPowerContext
4771{
4772 struct completion completion;
4773 unsigned int magic;
4774};
4775#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4776
4777/**---------------------------------------------------------------------------
4778
4779 \brief hdd_full_power_callback() - HDD full power callback function
4780
4781 This is the function invoked by SME to inform the result of a full power
4782 request issued by HDD
4783
4784 \param - callbackcontext - Pointer to cookie
4785 \param - status - result of request
4786
4787 \return - None
4788
4789 --------------------------------------------------------------------------*/
4790static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4791{
4792 struct fullPowerContext *pContext = callbackContext;
4793
4794 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304795 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004796
4797 if (NULL == callbackContext)
4798 {
4799 hddLog(VOS_TRACE_LEVEL_ERROR,
4800 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004801 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004802 return;
4803 }
4804
4805 /* there is a race condition that exists between this callback function
4806 and the caller since the caller could time out either before or
4807 while this code is executing. we'll assume the timeout hasn't
4808 occurred, but we'll verify that right before we save our work */
4809
4810 if (POWER_CONTEXT_MAGIC != pContext->magic)
4811 {
4812 /* the caller presumably timed out so there is nothing we can do */
4813 hddLog(VOS_TRACE_LEVEL_WARN,
4814 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004815 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004816 return;
4817 }
4818
4819 /* the race is on. caller could have timed out immediately after
4820 we verified the magic, but if so, caller will wait a short time
4821 for us to notify the caller, so the context will stay valid */
4822 complete(&pContext->completion);
4823}
4824
4825/**---------------------------------------------------------------------------
4826
4827 \brief hdd_wlan_exit() - HDD WLAN exit function
4828
4829 This is the driver exit point (invoked during rmmod)
4830
4831 \param - pHddCtx - Pointer to the HDD Context
4832
4833 \return - None
4834
4835 --------------------------------------------------------------------------*/
4836void hdd_wlan_exit(hdd_context_t *pHddCtx)
4837{
4838 eHalStatus halStatus;
4839 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4840 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304841 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004842 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004843 struct fullPowerContext powerContext;
4844 long lrc;
4845
4846 ENTER();
4847
Jeff Johnson88ba7742013-02-27 14:36:02 -08004848 if (VOS_FTM_MODE != hdd_get_conparam())
4849 {
4850 // Unloading, restart logic is no more required.
4851 wlan_hdd_restart_deinit(pHddCtx);
4852 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004853
Jeff Johnson295189b2012-06-20 16:38:30 -07004854 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004855 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004856 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004857 {
4858 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4859 WLAN_HDD_INFRA_STATION);
4860 if (pAdapter == NULL)
4861 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4862
4863 if (pAdapter != NULL)
4864 {
4865 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4866 hdd_UnregisterWext(pAdapter->dev);
4867 }
4868 }
4869 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004870
Jeff Johnson295189b2012-06-20 16:38:30 -07004871 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004872 {
4873 wlan_hdd_ftm_close(pHddCtx);
4874 goto free_hdd_ctx;
4875 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004876 //Stop the Interface TX queue.
4877 //netif_tx_disable(pWlanDev);
4878 //netif_carrier_off(pWlanDev);
4879
Jeff Johnson295189b2012-06-20 16:38:30 -07004880 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4881 {
4882 pAdapter = hdd_get_adapter(pHddCtx,
4883 WLAN_HDD_SOFTAP);
4884 }
4885 else
4886 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004887 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004888 {
4889 pAdapter = hdd_get_adapter(pHddCtx,
4890 WLAN_HDD_INFRA_STATION);
4891 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004892 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004893 /* DeRegister with platform driver as client for Suspend/Resume */
4894 vosStatus = hddDeregisterPmOps(pHddCtx);
4895 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4896 {
4897 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4898 VOS_ASSERT(0);
4899 }
4900
4901 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4902 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4903 {
4904 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4905 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004906
4907 // Cancel any outstanding scan requests. We are about to close all
4908 // of our adapters, but an adapter structure is what SME passes back
4909 // to our callback function. Hence if there are any outstanding scan
4910 // requests then there is a race condition between when the adapter
4911 // is closed and when the callback is invoked. We try to resolve that
4912 // race condition here by canceling any outstanding scans before we
4913 // close the adapters.
4914 // Note that the scans may be cancelled in an asynchronous manner, so
4915 // ideally there needs to be some kind of synchronization. Rather than
4916 // introduce a new synchronization here, we will utilize the fact that
4917 // we are about to Request Full Power, and since that is synchronized,
4918 // the expectation is that by the time Request Full Power has completed,
4919 // all scans will be cancelled.
4920 hdd_abort_mac_scan( pHddCtx );
4921
4922 //Disable IMPS/BMPS as we do not want the device to enter any power
4923 //save mode during shutdown
4924 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4925 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4926 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4927
4928 //Ensure that device is in full power as we will touch H/W during vos_Stop
4929 init_completion(&powerContext.completion);
4930 powerContext.magic = POWER_CONTEXT_MAGIC;
4931
4932 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4933 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4934
4935 if (eHAL_STATUS_SUCCESS != halStatus)
4936 {
4937 if (eHAL_STATUS_PMC_PENDING == halStatus)
4938 {
4939 /* request was sent -- wait for the response */
4940 lrc = wait_for_completion_interruptible_timeout(
4941 &powerContext.completion,
4942 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4943 /* either we have a response or we timed out
4944 either way, first invalidate our magic */
4945 powerContext.magic = 0;
4946 if (lrc <= 0)
4947 {
4948 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004949 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004950 /* there is a race condition such that the callback
4951 function could be executing at the same time we are. of
4952 primary concern is if the callback function had already
4953 verified the "magic" but hasn't yet set the completion
4954 variable. Since the completion variable is on our
4955 stack, we'll delay just a bit to make sure the data is
4956 still valid if that is the case */
4957 msleep(50);
4958 }
4959 }
4960 else
4961 {
4962 hddLog(VOS_TRACE_LEVEL_ERROR,
4963 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004964 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004965 VOS_ASSERT(0);
4966 /* continue -- need to clean up as much as possible */
4967 }
4968 }
4969
4970 // Unregister the Net Device Notifier
4971 unregister_netdevice_notifier(&hdd_netdev_notifier);
4972
Jeff Johnson295189b2012-06-20 16:38:30 -07004973 hdd_stop_all_adapters( pHddCtx );
4974
Jeff Johnson295189b2012-06-20 16:38:30 -07004975#ifdef WLAN_BTAMP_FEATURE
4976 vosStatus = WLANBAP_Stop(pVosContext);
4977 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4978 {
4979 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4980 "%s: Failed to stop BAP",__func__);
4981 }
4982#endif //WLAN_BTAMP_FEATURE
4983
4984 //Stop all the modules
4985 vosStatus = vos_stop( pVosContext );
4986 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4987 {
4988 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4989 "%s: Failed to stop VOSS",__func__);
4990 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4991 }
4992
Jeff Johnson295189b2012-06-20 16:38:30 -07004993 //Assert Deep sleep signal now to put Libra HW in lowest power state
4994 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4995 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4996
4997 //Vote off any PMIC voltage supplies
4998 vos_chipPowerDown(NULL, NULL, NULL);
4999
5000 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
5001
Jeff Johnson295189b2012-06-20 16:38:30 -07005002 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07005003 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005004
5005 //Close the scheduler before calling vos_close to make sure no thread is
5006 // scheduled after the each module close is called i.e after all the data
5007 // structures are freed.
5008 vosStatus = vos_sched_close( pVosContext );
5009 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
5010 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5011 "%s: Failed to close VOSS Scheduler",__func__);
5012 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5013 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005014#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005015#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5016 /* Destroy the wake lock */
5017 wake_lock_destroy(&pHddCtx->rx_wake_lock);
5018#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005019 /* Destroy the wake lock */
5020 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005021#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005022
5023 //Close VOSS
5024 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
5025 vos_close(pVosContext);
5026
Jeff Johnson295189b2012-06-20 16:38:30 -07005027 //Close Watchdog
5028 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5029 vos_watchdog_close(pVosContext);
5030
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305031 //Clean up HDD Nlink Service
5032 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
5033 nl_srv_exit();
5034
Jeff Johnson295189b2012-06-20 16:38:30 -07005035 /* Cancel the vote for XO Core ON.
5036 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5037 * exited at this point
5038 */
5039 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5040 " when WLAN is turned OFF\n");
5041 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5042 {
5043 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5044 " Not returning failure."
5045 " Power consumed will be high\n");
5046 }
5047
5048 hdd_close_all_adapters( pHddCtx );
5049
5050
5051 //Free up dynamically allocated members inside HDD Adapter
5052 kfree(pHddCtx->cfg_ini);
5053 pHddCtx->cfg_ini= NULL;
5054
5055 /* free the power on lock from platform driver */
5056 if (free_riva_power_on_lock("wlan"))
5057 {
5058 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5059 __func__);
5060 }
5061
Jeff Johnson88ba7742013-02-27 14:36:02 -08005062free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08005063 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005064 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005065 if (hdd_is_ssr_required())
5066 {
5067 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005068 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005069 msleep(5000);
5070 }
5071 hdd_set_ssr_required (VOS_FALSE);
5072}
5073
5074
5075/**---------------------------------------------------------------------------
5076
5077 \brief hdd_update_config_from_nv() - Function to update the contents of
5078 the running configuration with parameters taken from NV storage
5079
5080 \param - pHddCtx - Pointer to the HDD global context
5081
5082 \return - VOS_STATUS_SUCCESS if successful
5083
5084 --------------------------------------------------------------------------*/
5085static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5086{
Jeff Johnson295189b2012-06-20 16:38:30 -07005087 v_BOOL_t itemIsValid = VOS_FALSE;
5088 VOS_STATUS status;
5089 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5090 v_U8_t macLoop;
5091
5092 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5093 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5094 if(status != VOS_STATUS_SUCCESS)
5095 {
5096 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5097 return VOS_STATUS_E_FAILURE;
5098 }
5099
5100 if (itemIsValid == VOS_TRUE)
5101 {
5102 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5103 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5104 VOS_MAX_CONCURRENCY_PERSONA);
5105 if(status != VOS_STATUS_SUCCESS)
5106 {
5107 /* Get MAC from NV fail, not update CFG info
5108 * INI MAC value will be used for MAC setting */
5109 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5110 return VOS_STATUS_E_FAILURE;
5111 }
5112
5113 /* If first MAC is not valid, treat all others are not valid
5114 * Then all MACs will be got from ini file */
5115 if(vos_is_macaddr_zero(&macFromNV[0]))
5116 {
5117 /* MAC address in NV file is not configured yet */
5118 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5119 return VOS_STATUS_E_INVAL;
5120 }
5121
5122 /* Get MAC address from NV, update CFG info */
5123 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5124 {
5125 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5126 {
5127 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5128 /* This MAC is not valid, skip it
5129 * This MAC will be got from ini file */
5130 }
5131 else
5132 {
5133 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5134 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5135 VOS_MAC_ADDR_SIZE);
5136 }
5137 }
5138 }
5139 else
5140 {
5141 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5142 return VOS_STATUS_E_FAILURE;
5143 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005144
Jeff Johnson295189b2012-06-20 16:38:30 -07005145
5146 return VOS_STATUS_SUCCESS;
5147}
5148
5149/**---------------------------------------------------------------------------
5150
5151 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5152
5153 \param - pAdapter - Pointer to the HDD
5154
5155 \return - None
5156
5157 --------------------------------------------------------------------------*/
5158VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5159{
5160 eHalStatus halStatus;
5161 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305162 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005163
Jeff Johnson295189b2012-06-20 16:38:30 -07005164
5165 // Send ready indication to the HDD. This will kick off the MAC
5166 // into a 'running' state and should kick off an initial scan.
5167 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5168 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5169 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305170 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005171 "code %08d [x%08x]",__func__, halStatus, halStatus );
5172 return VOS_STATUS_E_FAILURE;
5173 }
5174
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305175 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005176 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5177 // And RIVA will crash
5178 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5179 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305180 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5181 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5182
5183
Jeff Johnson295189b2012-06-20 16:38:30 -07005184 return VOS_STATUS_SUCCESS;
5185}
5186
Jeff Johnson295189b2012-06-20 16:38:30 -07005187/* wake lock APIs for HDD */
5188void hdd_prevent_suspend(void)
5189{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005190#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005191 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005192#else
5193 wcnss_prevent_suspend();
5194#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005195}
5196
5197void hdd_allow_suspend(void)
5198{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005199#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005200 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005201#else
5202 wcnss_allow_suspend();
5203#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005204}
5205
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005206void hdd_allow_suspend_timeout(v_U32_t timeout)
5207{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005208#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005209 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005210#else
5211 /* Do nothing as there is no API in wcnss for timeout*/
5212#endif
5213}
5214
Jeff Johnson295189b2012-06-20 16:38:30 -07005215/**---------------------------------------------------------------------------
5216
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005217 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5218 information between Host and Riva
5219
5220 This function gets reported version of FW
5221 It also finds the version of Riva headers used to compile the host
5222 It compares the above two and prints a warning if they are different
5223 It gets the SW and HW version string
5224 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5225 indicating the features they support through a bitmap
5226
5227 \param - pHddCtx - Pointer to HDD context
5228
5229 \return - void
5230
5231 --------------------------------------------------------------------------*/
5232
5233void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5234{
5235
5236 tSirVersionType versionCompiled;
5237 tSirVersionType versionReported;
5238 tSirVersionString versionString;
5239 tANI_U8 fwFeatCapsMsgSupported = 0;
5240 VOS_STATUS vstatus;
5241
5242 /* retrieve and display WCNSS version information */
5243 do {
5244
5245 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5246 &versionCompiled);
5247 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5248 {
5249 hddLog(VOS_TRACE_LEVEL_FATAL,
5250 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005251 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005252 break;
5253 }
5254
5255 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5256 &versionReported);
5257 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5258 {
5259 hddLog(VOS_TRACE_LEVEL_FATAL,
5260 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005261 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005262 break;
5263 }
5264
5265 if ((versionCompiled.major != versionReported.major) ||
5266 (versionCompiled.minor != versionReported.minor) ||
5267 (versionCompiled.version != versionReported.version) ||
5268 (versionCompiled.revision != versionReported.revision))
5269 {
5270 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5271 "Host expected %u.%u.%u.%u\n",
5272 WLAN_MODULE_NAME,
5273 (int)versionReported.major,
5274 (int)versionReported.minor,
5275 (int)versionReported.version,
5276 (int)versionReported.revision,
5277 (int)versionCompiled.major,
5278 (int)versionCompiled.minor,
5279 (int)versionCompiled.version,
5280 (int)versionCompiled.revision);
5281 }
5282 else
5283 {
5284 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5285 WLAN_MODULE_NAME,
5286 (int)versionReported.major,
5287 (int)versionReported.minor,
5288 (int)versionReported.version,
5289 (int)versionReported.revision);
5290 }
5291
5292 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5293 versionString,
5294 sizeof(versionString));
5295 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5296 {
5297 hddLog(VOS_TRACE_LEVEL_FATAL,
5298 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005299 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005300 break;
5301 }
5302
5303 pr_info("%s: WCNSS software version %s\n",
5304 WLAN_MODULE_NAME, versionString);
5305
5306 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5307 versionString,
5308 sizeof(versionString));
5309 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5310 {
5311 hddLog(VOS_TRACE_LEVEL_FATAL,
5312 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005313 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005314 break;
5315 }
5316
5317 pr_info("%s: WCNSS hardware version %s\n",
5318 WLAN_MODULE_NAME, versionString);
5319
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005320 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5321 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005322 send the message only if it the riva is 1.1
5323 minor numbers for different riva branches:
5324 0 -> (1.0)Mainline Build
5325 1 -> (1.1)Mainline Build
5326 2->(1.04) Stability Build
5327 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005328 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005329 ((versionReported.minor>=1) && (versionReported.version>=1)))
5330 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5331 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005332
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005333 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005334 {
5335#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5336 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5337 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5338#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005339 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005340 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005341
5342 } while (0);
5343
5344}
5345
5346/**---------------------------------------------------------------------------
5347
Jeff Johnson295189b2012-06-20 16:38:30 -07005348 \brief hdd_wlan_startup() - HDD init function
5349
5350 This is the driver startup code executed once a WLAN device has been detected
5351
5352 \param - dev - Pointer to the underlying device
5353
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005354 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005355
5356 --------------------------------------------------------------------------*/
5357
5358int hdd_wlan_startup(struct device *dev )
5359{
5360 VOS_STATUS status;
5361 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005362 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005363 hdd_context_t *pHddCtx = NULL;
5364 v_CONTEXT_t pVosContext= NULL;
5365#ifdef WLAN_BTAMP_FEATURE
5366 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5367 WLANBAP_ConfigType btAmpConfig;
5368 hdd_config_t *pConfig;
5369#endif
5370 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005371 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005372
5373 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005374 /*
5375 * cfg80211: wiphy allocation
5376 */
5377 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5378
5379 if(wiphy == NULL)
5380 {
5381 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005382 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005383 }
5384
5385 pHddCtx = wiphy_priv(wiphy);
5386
Jeff Johnson295189b2012-06-20 16:38:30 -07005387 //Initialize the adapter context to zeros.
5388 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5389
Jeff Johnson295189b2012-06-20 16:38:30 -07005390 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005391 hdd_prevent_suspend();
5392 pHddCtx->isLoadUnloadInProgress = TRUE;
5393
5394 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5395
5396 /*Get vos context here bcoz vos_open requires it*/
5397 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5398
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005399 if(pVosContext == NULL)
5400 {
5401 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5402 goto err_free_hdd_context;
5403 }
5404
Jeff Johnson295189b2012-06-20 16:38:30 -07005405 //Save the Global VOSS context in adapter context for future.
5406 pHddCtx->pvosContext = pVosContext;
5407
5408 //Save the adapter context in global context for future.
5409 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5410
Jeff Johnson295189b2012-06-20 16:38:30 -07005411 pHddCtx->parent_dev = dev;
5412
5413 init_completion(&pHddCtx->full_pwr_comp_var);
5414 init_completion(&pHddCtx->standby_comp_var);
5415 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005416 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005417 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005418
5419 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5420
5421 // Load all config first as TL config is needed during vos_open
5422 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5423 if(pHddCtx->cfg_ini == NULL)
5424 {
5425 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5426 goto err_free_hdd_context;
5427 }
5428
5429 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5430
5431 // Read and parse the qcom_cfg.ini file
5432 status = hdd_parse_config_ini( pHddCtx );
5433 if ( VOS_STATUS_SUCCESS != status )
5434 {
5435 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5436 __func__, WLAN_INI_FILE);
5437 goto err_config;
5438 }
5439
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305440 /* INI has been read, initialise the configuredMcastBcastFilter with
5441 * INI value as this will serve as the default value
5442 */
5443 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5444 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5445 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Jeff Johnson295189b2012-06-20 16:38:30 -07005446 /*
5447 * cfg80211: Initialization and registration ...
5448 */
5449 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5450 {
5451 hddLog(VOS_TRACE_LEVEL_FATAL,
5452 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5453 goto err_wiphy_reg;
5454 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005455
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005456 // Update VOS trace levels based upon the cfg.ini
5457 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5458 pHddCtx->cfg_ini->vosTraceEnableBAP);
5459 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5460 pHddCtx->cfg_ini->vosTraceEnableTL);
5461 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5462 pHddCtx->cfg_ini->vosTraceEnableWDI);
5463 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5464 pHddCtx->cfg_ini->vosTraceEnableHDD);
5465 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5466 pHddCtx->cfg_ini->vosTraceEnableSME);
5467 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5468 pHddCtx->cfg_ini->vosTraceEnablePE);
5469 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5470 pHddCtx->cfg_ini->vosTraceEnableWDA);
5471 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5472 pHddCtx->cfg_ini->vosTraceEnableSYS);
5473 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5474 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005475 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5476 pHddCtx->cfg_ini->vosTraceEnableSAP);
5477 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5478 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005479
Jeff Johnson295189b2012-06-20 16:38:30 -07005480 // Update WDI trace levels based upon the cfg.ini
5481 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5482 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5483 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5484 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5485 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5486 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5487 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5488 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005489
Jeff Johnson88ba7742013-02-27 14:36:02 -08005490 if (VOS_FTM_MODE == hdd_get_conparam())
5491 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005492 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5493 {
5494 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5495 goto err_free_hdd_context;
5496 }
5497 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5498 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005499 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005500
Jeff Johnson88ba7742013-02-27 14:36:02 -08005501 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005502 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5503 {
5504 status = vos_watchdog_open(pVosContext,
5505 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5506
5507 if(!VOS_IS_STATUS_SUCCESS( status ))
5508 {
5509 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005510 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005511 }
5512 }
5513
5514 pHddCtx->isLogpInProgress = FALSE;
5515 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5516
Jeff Johnson295189b2012-06-20 16:38:30 -07005517 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5518 if(!VOS_IS_STATUS_SUCCESS(status))
5519 {
5520 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005521 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005522 }
5523
Jeff Johnson295189b2012-06-20 16:38:30 -07005524 status = vos_open( &pVosContext, 0);
5525 if ( !VOS_IS_STATUS_SUCCESS( status ))
5526 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005527 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5528 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005529 }
5530
Jeff Johnson295189b2012-06-20 16:38:30 -07005531 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5532
5533 if ( NULL == pHddCtx->hHal )
5534 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005535 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005536 goto err_vosclose;
5537 }
5538
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005539 status = vos_preStart( pHddCtx->pvosContext );
5540 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5541 {
5542 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5543 goto err_vosclose;
5544 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005545
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005546 /* Note that the vos_preStart() sequence triggers the cfg download.
5547 The cfg download must occur before we update the SME config
5548 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005549 status = hdd_set_sme_config( pHddCtx );
5550
5551 if ( VOS_STATUS_SUCCESS != status )
5552 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005553 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5554 goto err_vosclose;
5555 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005556
5557 //Initialize the WMM module
5558 status = hdd_wmm_init(pHddCtx);
5559 if (!VOS_IS_STATUS_SUCCESS(status))
5560 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005561 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005562 goto err_vosclose;
5563 }
5564
Jeff Johnson295189b2012-06-20 16:38:30 -07005565 /* In the integrated architecture we update the configuration from
5566 the INI file and from NV before vOSS has been started so that
5567 the final contents are available to send down to the cCPU */
5568
5569 // Apply the cfg.ini to cfg.dat
5570 if (FALSE == hdd_update_config_dat(pHddCtx))
5571 {
5572 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5573 goto err_vosclose;
5574 }
5575
5576 // Apply the NV to cfg.dat
5577 /* Prima Update MAC address only at here */
5578 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5579 {
5580#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5581 /* There was not a valid set of MAC Addresses in NV. See if the
5582 default addresses were modified by the cfg.ini settings. If so,
5583 we'll use them, but if not, we'll autogenerate a set of MAC
5584 addresses based upon the device serial number */
5585
5586 static const v_MACADDR_t default_address =
5587 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5588 unsigned int serialno;
5589 int i;
5590
5591 serialno = wcnss_get_serial_number();
5592 if ((0 != serialno) &&
5593 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5594 sizeof(default_address))))
5595 {
5596 /* cfg.ini has the default address, invoke autogen logic */
5597
5598 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5599 bytes of the serial number that can be used to generate
5600 the other 3 bytes of the MAC address. Mask off all but
5601 the lower 3 bytes (this will also make sure we don't
5602 overflow in the next step) */
5603 serialno &= 0x00FFFFFF;
5604
5605 /* we need a unique address for each session */
5606 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5607
5608 /* autogen all addresses */
5609 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5610 {
5611 /* start with the entire default address */
5612 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5613 /* then replace the lower 3 bytes */
5614 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5615 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5616 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5617
5618 serialno++;
5619 }
5620
5621 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5622 MAC_ADDRESS_STR,
5623 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5624 }
5625 else
5626#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5627 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005628 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005629 "%s: Invalid MAC address in NV, using MAC from ini file "
5630 MAC_ADDRESS_STR, __func__,
5631 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5632 }
5633 }
5634 {
5635 eHalStatus halStatus;
5636 // Set the MAC Address
5637 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5638 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5639 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5640 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5641
5642 if (!HAL_STATUS_SUCCESS( halStatus ))
5643 {
5644 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5645 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005646 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005647 }
5648 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005649
5650 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5651 Note: Firmware image will be read and downloaded inside vos_start API */
5652 status = vos_start( pHddCtx->pvosContext );
5653 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5654 {
5655 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5656 goto err_vosclose;
5657 }
5658
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005659 /* Exchange capability info between Host and FW and also get versioning info from FW */
5660 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005661
5662 status = hdd_post_voss_start_config( pHddCtx );
5663 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5664 {
5665 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5666 __func__);
5667 goto err_vosstop;
5668 }
5669
Jeff Johnson295189b2012-06-20 16:38:30 -07005670 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5671 {
5672 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5673 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5674 }
5675 else
5676 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005677 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5678 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5679 if (pAdapter != NULL)
5680 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305681 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005682 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305683 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5684 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5685 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005686
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305687 /* Generate the P2P Device Address. This consists of the device's
5688 * primary MAC address with the locally administered bit set.
5689 */
5690 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005691 }
5692 else
5693 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305694 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5695 if (p2p_dev_addr != NULL)
5696 {
5697 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5698 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5699 }
5700 else
5701 {
5702 hddLog(VOS_TRACE_LEVEL_FATAL,
5703 "%s: Failed to allocate mac_address for p2p_device",
5704 __func__);
5705 goto err_close_adapter;
5706 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005707 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005708
5709 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5710 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5711 if ( NULL == pP2pAdapter )
5712 {
5713 hddLog(VOS_TRACE_LEVEL_FATAL,
5714 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005715 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005716 goto err_close_adapter;
5717 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005718 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005719 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005720
5721 if( pAdapter == NULL )
5722 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005723 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5724 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005725 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005726
Jeff Johnson295189b2012-06-20 16:38:30 -07005727#ifdef WLAN_BTAMP_FEATURE
5728 vStatus = WLANBAP_Open(pVosContext);
5729 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5730 {
5731 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5732 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005733 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005734 }
5735
5736 vStatus = BSL_Init(pVosContext);
5737 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5738 {
5739 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5740 "%s: Failed to Init BSL",__func__);
5741 goto err_bap_close;
5742 }
5743 vStatus = WLANBAP_Start(pVosContext);
5744 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5745 {
5746 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5747 "%s: Failed to start TL",__func__);
5748 goto err_bap_close;
5749 }
5750
5751 pConfig = pHddCtx->cfg_ini;
5752 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5753 status = WLANBAP_SetConfig(&btAmpConfig);
5754
5755#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005756
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005757#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5758 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5759 {
5760 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5761 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5762 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5763 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5764 }
5765#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005766#ifdef FEATURE_WLAN_SCAN_PNO
5767 /*SME must send channel update configuration to RIVA*/
5768 sme_UpdateChannelConfig(pHddCtx->hHal);
5769#endif
5770
Jeff Johnson295189b2012-06-20 16:38:30 -07005771 /* Register with platform driver as client for Suspend/Resume */
5772 status = hddRegisterPmOps(pHddCtx);
5773 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5774 {
5775 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5776#ifdef WLAN_BTAMP_FEATURE
5777 goto err_bap_stop;
5778#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005779 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005780#endif //WLAN_BTAMP_FEATURE
5781 }
5782
5783 /* Register TM level change handler function to the platform */
5784 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5785 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5786 {
5787 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5788 goto err_unregister_pmops;
5789 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005790
5791 /* register for riva power on lock to platform driver */
5792 if (req_riva_power_on_lock("wlan"))
5793 {
5794 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5795 __func__);
5796 goto err_unregister_pmops;
5797 }
5798
Jeff Johnson295189b2012-06-20 16:38:30 -07005799 // register net device notifier for device change notification
5800 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5801
5802 if(ret < 0)
5803 {
5804 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5805 goto err_free_power_on_lock;
5806 }
5807
5808 //Initialize the nlink service
5809 if(nl_srv_init() != 0)
5810 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305811 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005812 goto err_reg_netdev;
5813 }
5814
5815 //Initialize the BTC service
5816 if(btc_activate_service(pHddCtx) != 0)
5817 {
5818 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5819 goto err_nl_srv;
5820 }
5821
5822#ifdef PTT_SOCK_SVC_ENABLE
5823 //Initialize the PTT service
5824 if(ptt_sock_activate_svc(pHddCtx) != 0)
5825 {
5826 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5827 goto err_nl_srv;
5828 }
5829#endif
5830
Jeff Johnson295189b2012-06-20 16:38:30 -07005831 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005832 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005833 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005834 /* Action frame registered in one adapter which will
5835 * applicable to all interfaces
5836 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005837 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005838 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005839
5840 mutex_init(&pHddCtx->sap_lock);
5841
5842 pHddCtx->isLoadUnloadInProgress = FALSE;
5843
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005844#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005845#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5846 /* Initialize the wake lcok */
5847 wake_lock_init(&pHddCtx->rx_wake_lock,
5848 WAKE_LOCK_SUSPEND,
5849 "qcom_rx_wakelock");
5850#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005851 /* Initialize the wake lcok */
5852 wake_lock_init(&pHddCtx->sap_wake_lock,
5853 WAKE_LOCK_SUSPEND,
5854 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005855#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005856
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005857 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5858 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005859
5860 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5861 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005862
5863 // Initialize the restart logic
5864 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305865
Jeff Johnson295189b2012-06-20 16:38:30 -07005866 goto success;
5867
5868err_nl_srv:
5869 nl_srv_exit();
5870
5871err_reg_netdev:
5872 unregister_netdevice_notifier(&hdd_netdev_notifier);
5873
5874err_free_power_on_lock:
5875 free_riva_power_on_lock("wlan");
5876
5877err_unregister_pmops:
5878 hddDevTmUnregisterNotifyCallback(pHddCtx);
5879 hddDeregisterPmOps(pHddCtx);
5880
5881#ifdef WLAN_BTAMP_FEATURE
5882err_bap_stop:
5883 WLANBAP_Stop(pVosContext);
5884#endif
5885
5886#ifdef WLAN_BTAMP_FEATURE
5887err_bap_close:
5888 WLANBAP_Close(pVosContext);
5889#endif
5890
Jeff Johnson295189b2012-06-20 16:38:30 -07005891err_close_adapter:
5892 hdd_close_all_adapters( pHddCtx );
5893
5894err_vosstop:
5895 vos_stop(pVosContext);
5896
5897err_vosclose:
5898 status = vos_sched_close( pVosContext );
5899 if (!VOS_IS_STATUS_SUCCESS(status)) {
5900 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5901 "%s: Failed to close VOSS Scheduler", __func__);
5902 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5903 }
5904 vos_close(pVosContext );
5905
Jeff Johnson295189b2012-06-20 16:38:30 -07005906err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005907 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005908
5909err_wdclose:
5910 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5911 vos_watchdog_close(pVosContext);
5912
Jeff Johnson295189b2012-06-20 16:38:30 -07005913err_wiphy_reg:
5914 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005915
5916err_config:
5917 kfree(pHddCtx->cfg_ini);
5918 pHddCtx->cfg_ini= NULL;
5919
5920err_free_hdd_context:
5921 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005922 wiphy_free(wiphy) ;
5923 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005924 VOS_BUG(1);
5925
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005926 if (hdd_is_ssr_required())
5927 {
5928 /* WDI timeout had happened during load, so SSR is needed here */
5929 subsystem_restart("wcnss");
5930 msleep(5000);
5931 }
5932 hdd_set_ssr_required (VOS_FALSE);
5933
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005934 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005935
5936success:
5937 EXIT();
5938 return 0;
5939}
5940
5941/**---------------------------------------------------------------------------
5942
Jeff Johnson32d95a32012-09-10 13:15:23 -07005943 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005944
Jeff Johnson32d95a32012-09-10 13:15:23 -07005945 This is the driver entry point - called in different timeline depending
5946 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005947
5948 \param - None
5949
5950 \return - 0 for success, non zero for failure
5951
5952 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005953static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005954{
5955 VOS_STATUS status;
5956 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005957 struct device *dev = NULL;
5958 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005959#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5960 int max_retries = 0;
5961#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005962
Gopichand Nakkalad0774962013-05-24 11:32:21 +05305963#ifdef WCONN_TRACE_KMSG_LOG_BUFF
5964 vos_wconn_trace_init();
5965#endif
5966
Jeff Johnson295189b2012-06-20 16:38:30 -07005967 ENTER();
5968
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005969#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005970 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005971#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005972
5973 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5974 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5975
5976 //Power Up Libra WLAN card first if not already powered up
5977 status = vos_chipPowerUp(NULL,NULL,NULL);
5978 if (!VOS_IS_STATUS_SUCCESS(status))
5979 {
5980 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5981 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005982 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005983 }
5984
Jeff Johnson295189b2012-06-20 16:38:30 -07005985#ifdef ANI_BUS_TYPE_PCI
5986
5987 dev = wcnss_wlan_get_device();
5988
5989#endif // ANI_BUS_TYPE_PCI
5990
5991#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005992
5993#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5994 /* wait until WCNSS driver downloads NV */
5995 while (!wcnss_device_ready() && 5 >= ++max_retries) {
5996 msleep(1000);
5997 }
5998 if (max_retries >= 5) {
5999 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
6000 return -ENODEV;
6001 }
6002#endif
6003
Jeff Johnson295189b2012-06-20 16:38:30 -07006004 dev = wcnss_wlan_get_device();
6005#endif // ANI_BUS_TYPE_PLATFORM
6006
6007
6008 do {
6009 if (NULL == dev) {
6010 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6011 ret_status = -1;
6012 break;
6013 }
6014
6015#ifdef MEMORY_DEBUG
6016 vos_mem_init();
6017#endif
6018
6019#ifdef TIMER_MANAGER
6020 vos_timer_manager_init();
6021#endif
6022
6023 /* Preopen VOSS so that it is ready to start at least SAL */
6024 status = vos_preOpen(&pVosContext);
6025
6026 if (!VOS_IS_STATUS_SUCCESS(status))
6027 {
6028 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6029 ret_status = -1;
6030 break;
6031 }
6032
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006033#ifndef MODULE
6034 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6035 */
6036 hdd_set_conparam((v_UINT_t)con_mode);
6037#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006038
6039 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006040 if (hdd_wlan_startup(dev))
6041 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006042 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006043 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006044 vos_preClose( &pVosContext );
6045 ret_status = -1;
6046 break;
6047 }
6048
6049 /* Cancel the vote for XO Core ON
6050 * This is done here for safety purposes in case we re-initialize without turning
6051 * it OFF in any error scenario.
6052 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006053 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006054 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006055 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006056 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6057 {
6058 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6059 " Power consumed will be high\n");
6060 }
6061 } while (0);
6062
6063 if (0 != ret_status)
6064 {
6065 //Assert Deep sleep signal now to put Libra HW in lowest power state
6066 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6067 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6068
6069 //Vote off any PMIC voltage supplies
6070 vos_chipPowerDown(NULL, NULL, NULL);
6071#ifdef TIMER_MANAGER
6072 vos_timer_exit();
6073#endif
6074#ifdef MEMORY_DEBUG
6075 vos_mem_exit();
6076#endif
6077
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006078#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006079 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006080#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006081 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6082 }
6083 else
6084 {
6085 //Send WLAN UP indication to Nlink Service
6086 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6087
6088 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
6089
6090 }
6091
6092 EXIT();
6093
6094 return ret_status;
6095}
6096
Jeff Johnson32d95a32012-09-10 13:15:23 -07006097/**---------------------------------------------------------------------------
6098
6099 \brief hdd_module_init() - Init Function
6100
6101 This is the driver entry point (invoked when module is loaded using insmod)
6102
6103 \param - None
6104
6105 \return - 0 for success, non zero for failure
6106
6107 --------------------------------------------------------------------------*/
6108#ifdef MODULE
6109static int __init hdd_module_init ( void)
6110{
6111 return hdd_driver_init();
6112}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006113#else /* #ifdef MODULE */
6114static int __init hdd_module_init ( void)
6115{
6116 /* Driver initialization is delayed to fwpath_changed_handler */
6117 return 0;
6118}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006119#endif /* #ifdef MODULE */
6120
Jeff Johnson295189b2012-06-20 16:38:30 -07006121
6122/**---------------------------------------------------------------------------
6123
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006124 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006125
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006126 This is the driver exit point (invoked when module is unloaded using rmmod
6127 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006128
6129 \param - None
6130
6131 \return - None
6132
6133 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006134static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006135{
6136 hdd_context_t *pHddCtx = NULL;
6137 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006138 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006139
6140 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6141
6142 //Get the global vos context
6143 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6144
6145 if(!pVosContext)
6146 {
6147 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6148 goto done;
6149 }
6150
6151 //Get the HDD context.
6152 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6153
6154 if(!pHddCtx)
6155 {
6156 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6157 }
6158 else
6159 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006160 while(isWDresetInProgress()) {
6161 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6162 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006163 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006164
6165 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6166 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6167 "%s:SSR never completed, fatal error", __func__);
6168 VOS_BUG(0);
6169 }
6170 }
6171
Jeff Johnson295189b2012-06-20 16:38:30 -07006172
6173 pHddCtx->isLoadUnloadInProgress = TRUE;
6174 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6175
6176 //Do all the cleanup before deregistering the driver
6177 hdd_wlan_exit(pHddCtx);
6178 }
6179
Jeff Johnson295189b2012-06-20 16:38:30 -07006180 vos_preClose( &pVosContext );
6181
6182#ifdef TIMER_MANAGER
6183 vos_timer_exit();
6184#endif
6185#ifdef MEMORY_DEBUG
6186 vos_mem_exit();
6187#endif
6188
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306189#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6190 vos_wconn_trace_exit();
6191#endif
6192
Jeff Johnson295189b2012-06-20 16:38:30 -07006193done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006194#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006195 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006196#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006197 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6198}
6199
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006200/**---------------------------------------------------------------------------
6201
6202 \brief hdd_module_exit() - Exit function
6203
6204 This is the driver exit point (invoked when module is unloaded using rmmod)
6205
6206 \param - None
6207
6208 \return - None
6209
6210 --------------------------------------------------------------------------*/
6211static void __exit hdd_module_exit(void)
6212{
6213 hdd_driver_exit();
6214}
6215
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006216#ifdef MODULE
6217static int fwpath_changed_handler(const char *kmessage,
6218 struct kernel_param *kp)
6219{
Jeff Johnson76052702013-04-16 13:55:05 -07006220 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006221}
6222
6223static int con_mode_handler(const char *kmessage,
6224 struct kernel_param *kp)
6225{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006226 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006227}
6228#else /* #ifdef MODULE */
6229/**---------------------------------------------------------------------------
6230
Jeff Johnson76052702013-04-16 13:55:05 -07006231 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006232
Jeff Johnson76052702013-04-16 13:55:05 -07006233 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006234 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006235 - invoked when module parameter fwpath is modified from userspace to signal
6236 initializing the WLAN driver or when con_mode is modified from userspace
6237 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006238
6239 \return - 0 for success, non zero for failure
6240
6241 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006242static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006243{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006244 int ret_status;
6245
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006246 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006247 ret_status = hdd_driver_init();
6248 wlan_hdd_inited = ret_status ? 0 : 1;
6249 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006250 }
6251
6252 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006253
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006254 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006255
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006256 ret_status = hdd_driver_init();
6257 wlan_hdd_inited = ret_status ? 0 : 1;
6258 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006259}
6260
Jeff Johnson295189b2012-06-20 16:38:30 -07006261/**---------------------------------------------------------------------------
6262
Jeff Johnson76052702013-04-16 13:55:05 -07006263 \brief fwpath_changed_handler() - Handler Function
6264
6265 Handle changes to the fwpath parameter
6266
6267 \return - 0 for success, non zero for failure
6268
6269 --------------------------------------------------------------------------*/
6270static int fwpath_changed_handler(const char *kmessage,
6271 struct kernel_param *kp)
6272{
6273 int ret;
6274
6275 ret = param_set_copystring(kmessage, kp);
6276 if (0 == ret)
6277 ret = kickstart_driver();
6278 return ret;
6279}
6280
6281/**---------------------------------------------------------------------------
6282
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006283 \brief con_mode_handler() -
6284
6285 Handler function for module param con_mode when it is changed by userspace
6286 Dynamically linked - do nothing
6287 Statically linked - exit and init driver, as in rmmod and insmod
6288
Jeff Johnson76052702013-04-16 13:55:05 -07006289 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006290
Jeff Johnson76052702013-04-16 13:55:05 -07006291 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006292
6293 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006294static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006295{
Jeff Johnson76052702013-04-16 13:55:05 -07006296 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006297
Jeff Johnson76052702013-04-16 13:55:05 -07006298 ret = param_set_int(kmessage, kp);
6299 if (0 == ret)
6300 ret = kickstart_driver();
6301 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006302}
6303#endif /* #ifdef MODULE */
6304
6305/**---------------------------------------------------------------------------
6306
Jeff Johnson295189b2012-06-20 16:38:30 -07006307 \brief hdd_get_conparam() -
6308
6309 This is the driver exit point (invoked when module is unloaded using rmmod)
6310
6311 \param - None
6312
6313 \return - tVOS_CON_MODE
6314
6315 --------------------------------------------------------------------------*/
6316tVOS_CON_MODE hdd_get_conparam ( void )
6317{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006318#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006319 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006320#else
6321 return (tVOS_CON_MODE)curr_con_mode;
6322#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006323}
6324void hdd_set_conparam ( v_UINT_t newParam )
6325{
6326 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006327#ifndef MODULE
6328 curr_con_mode = con_mode;
6329#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006330}
6331/**---------------------------------------------------------------------------
6332
6333 \brief hdd_softap_sta_deauth() - function
6334
6335 This to take counter measure to handle deauth req from HDD
6336
6337 \param - pAdapter - Pointer to the HDD
6338
6339 \param - enable - boolean value
6340
6341 \return - None
6342
6343 --------------------------------------------------------------------------*/
6344
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006345VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006346{
Jeff Johnson295189b2012-06-20 16:38:30 -07006347 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006348 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006349
6350 ENTER();
6351
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306352 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006353
6354 //Ignore request to deauth bcmc station
6355 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006356 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006357
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006358 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006359
6360 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006361 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006362}
6363
6364/**---------------------------------------------------------------------------
6365
6366 \brief hdd_softap_sta_disassoc() - function
6367
6368 This to take counter measure to handle deauth req from HDD
6369
6370 \param - pAdapter - Pointer to the HDD
6371
6372 \param - enable - boolean value
6373
6374 \return - None
6375
6376 --------------------------------------------------------------------------*/
6377
6378void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6379{
6380 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6381
6382 ENTER();
6383
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306384 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006385
6386 //Ignore request to disassoc bcmc station
6387 if( pDestMacAddress[0] & 0x1 )
6388 return;
6389
6390 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6391}
6392
6393void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6394{
6395 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6396
6397 ENTER();
6398
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306399 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006400
6401 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6402}
6403
Jeff Johnson295189b2012-06-20 16:38:30 -07006404/**---------------------------------------------------------------------------
6405 *
6406 * \brief hdd_get__concurrency_mode() -
6407 *
6408 *
6409 * \param - None
6410 *
6411 * \return - CONCURRENCY MODE
6412 *
6413 * --------------------------------------------------------------------------*/
6414tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6415{
6416 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6417 hdd_context_t *pHddCtx;
6418
6419 if (NULL != pVosContext)
6420 {
6421 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6422 if (NULL != pHddCtx)
6423 {
6424 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6425 }
6426 }
6427
6428 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006429 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006430 return VOS_STA;
6431}
6432
6433/* Decide whether to allow/not the apps power collapse.
6434 * Allow apps power collapse if we are in connected state.
6435 * if not, allow only if we are in IMPS */
6436v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6437{
6438 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006439 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006440 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006441 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6442 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6443 hdd_adapter_t *pAdapter = NULL;
6444 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006445 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006446
Jeff Johnson295189b2012-06-20 16:38:30 -07006447 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6448 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006449
Yathish9f22e662012-12-10 14:21:35 -08006450 concurrent_state = hdd_get_concurrency_mode();
6451
6452#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6453 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6454 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6455 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6456 return TRUE;
6457#endif
6458
Jeff Johnson295189b2012-06-20 16:38:30 -07006459 /*loop through all adapters. TBD fix for Concurrency */
6460 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6461 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6462 {
6463 pAdapter = pAdapterNode->pAdapter;
6464 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6465 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6466 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006467 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006468 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006469 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006470 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6471 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006472 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006473 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006474 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6475 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006476 return FALSE;
6477 }
6478 }
6479 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6480 pAdapterNode = pNext;
6481 }
6482 return TRUE;
6483}
6484
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006485/* Decides whether to send suspend notification to Riva
6486 * if any adapter is in BMPS; then it is required */
6487v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6488{
6489 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6490 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6491
6492 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6493 {
6494 return TRUE;
6495 }
6496 return FALSE;
6497}
6498
Jeff Johnson295189b2012-06-20 16:38:30 -07006499void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6500{
6501 switch(mode)
6502 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006503 case VOS_STA_MODE:
6504 case VOS_P2P_CLIENT_MODE:
6505 case VOS_P2P_GO_MODE:
6506 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006507 pHddCtx->concurrency_mode |= (1 << mode);
6508 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006509 break;
6510 default:
6511 break;
6512
6513 }
6514 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6515 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6516}
6517
6518
6519void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6520{
6521 switch(mode)
6522 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006523 case VOS_STA_MODE:
6524 case VOS_P2P_CLIENT_MODE:
6525 case VOS_P2P_GO_MODE:
6526 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006527 pHddCtx->no_of_sessions[mode]--;
6528 if (!(pHddCtx->no_of_sessions[mode]))
6529 pHddCtx->concurrency_mode &= (~(1 << mode));
6530 break;
6531 default:
6532 break;
6533 }
6534 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6535 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6536}
6537
Jeff Johnsone7245742012-09-05 17:12:55 -07006538/**---------------------------------------------------------------------------
6539 *
6540 * \brief wlan_hdd_restart_init
6541 *
6542 * This function initalizes restart timer/flag. An internal function.
6543 *
6544 * \param - pHddCtx
6545 *
6546 * \return - None
6547 *
6548 * --------------------------------------------------------------------------*/
6549
6550static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6551{
6552 /* Initialize */
6553 pHddCtx->hdd_restart_retries = 0;
6554 atomic_set(&pHddCtx->isRestartInProgress, 0);
6555 vos_timer_init(&pHddCtx->hdd_restart_timer,
6556 VOS_TIMER_TYPE_SW,
6557 wlan_hdd_restart_timer_cb,
6558 pHddCtx);
6559}
6560/**---------------------------------------------------------------------------
6561 *
6562 * \brief wlan_hdd_restart_deinit
6563 *
6564 * This function cleans up the resources used. An internal function.
6565 *
6566 * \param - pHddCtx
6567 *
6568 * \return - None
6569 *
6570 * --------------------------------------------------------------------------*/
6571
6572static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6573{
6574
6575 VOS_STATUS vos_status;
6576 /* Block any further calls */
6577 atomic_set(&pHddCtx->isRestartInProgress, 1);
6578 /* Cleanup */
6579 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6580 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006581 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006582 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6583 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006584 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006585
6586}
6587
6588/**---------------------------------------------------------------------------
6589 *
6590 * \brief wlan_hdd_framework_restart
6591 *
6592 * This function uses a cfg80211 API to start a framework initiated WLAN
6593 * driver module unload/load.
6594 *
6595 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6596 *
6597 *
6598 * \param - pHddCtx
6599 *
6600 * \return - VOS_STATUS_SUCCESS: Success
6601 * VOS_STATUS_E_EMPTY: Adapter is Empty
6602 * VOS_STATUS_E_NOMEM: No memory
6603
6604 * --------------------------------------------------------------------------*/
6605
6606static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6607{
6608 VOS_STATUS status = VOS_STATUS_SUCCESS;
6609 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006610 int len = (sizeof (struct ieee80211_mgmt));
6611 struct ieee80211_mgmt *mgmt = NULL;
6612
6613 /* Prepare the DEAUTH managment frame with reason code */
6614 mgmt = kzalloc(len, GFP_KERNEL);
6615 if(mgmt == NULL)
6616 {
6617 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6618 "%s: memory allocation failed (%d bytes)", __func__, len);
6619 return VOS_STATUS_E_NOMEM;
6620 }
6621 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006622
6623 /* Iterate over all adapters/devices */
6624 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6625 do
6626 {
6627 if( (status == VOS_STATUS_SUCCESS) &&
6628 pAdapterNode &&
6629 pAdapterNode->pAdapter)
6630 {
6631 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6632 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6633 pAdapterNode->pAdapter->dev->name,
6634 pAdapterNode->pAdapter->device_mode,
6635 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006636 /*
6637 * CFG80211 event to restart the driver
6638 *
6639 * 'cfg80211_send_unprot_deauth' sends a
6640 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6641 * of SME(Linux Kernel) state machine.
6642 *
6643 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6644 * the driver.
6645 *
6646 */
6647
6648 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006649 }
6650 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6651 pAdapterNode = pNext;
6652 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6653
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006654
6655 /* Free the allocated management frame */
6656 kfree(mgmt);
6657
Jeff Johnsone7245742012-09-05 17:12:55 -07006658 /* Retry until we unload or reach max count */
6659 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6660 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6661
6662 return status;
6663
6664}
6665/**---------------------------------------------------------------------------
6666 *
6667 * \brief wlan_hdd_restart_timer_cb
6668 *
6669 * Restart timer callback. An internal function.
6670 *
6671 * \param - User data:
6672 *
6673 * \return - None
6674 *
6675 * --------------------------------------------------------------------------*/
6676
6677void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6678{
6679 hdd_context_t *pHddCtx = usrDataForCallback;
6680 wlan_hdd_framework_restart(pHddCtx);
6681 return;
6682
6683}
6684
6685
6686/**---------------------------------------------------------------------------
6687 *
6688 * \brief wlan_hdd_restart_driver
6689 *
6690 * This function sends an event to supplicant to restart the WLAN driver.
6691 *
6692 * This function is called from vos_wlanRestart.
6693 *
6694 * \param - pHddCtx
6695 *
6696 * \return - VOS_STATUS_SUCCESS: Success
6697 * VOS_STATUS_E_EMPTY: Adapter is Empty
6698 * VOS_STATUS_E_ALREADY: Request already in progress
6699
6700 * --------------------------------------------------------------------------*/
6701VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6702{
6703 VOS_STATUS status = VOS_STATUS_SUCCESS;
6704
6705 /* A tight check to make sure reentrancy */
6706 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6707 {
6708 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6709 "%s: WLAN restart is already in progress", __func__);
6710
6711 return VOS_STATUS_E_ALREADY;
6712 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006713 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006714#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006715 wcnss_reset_intr();
6716#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006717
Jeff Johnsone7245742012-09-05 17:12:55 -07006718 return status;
6719}
6720
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006721/*
6722 * API to find if there is any STA or P2P-Client is connected
6723 */
6724VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6725{
6726 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6727}
Jeff Johnsone7245742012-09-05 17:12:55 -07006728
Jeff Johnson295189b2012-06-20 16:38:30 -07006729//Register the module init/exit functions
6730module_init(hdd_module_init);
6731module_exit(hdd_module_exit);
6732
6733MODULE_LICENSE("Dual BSD/GPL");
6734MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6735MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6736
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006737module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6738 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006739
Jeff Johnson76052702013-04-16 13:55:05 -07006740module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006741 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);